Claude 工作流实验室
独立第三方实践站 · 非 Anthropic 官方;域名中的 6 不代表官方模型版本独立中文指南
任务拆解

让 Claude 写能用键盘操作的弹窗:从原生 dialog 开始

用一份可直接打开的 HTML,明确弹窗名称、初始焦点、取消行为和保存结果,再按键盘路径逐项验收。

让 Claude “写一个漂亮弹窗”,很容易得到能用鼠标点击、却无法完整用键盘操作的页面。改进方法是把视觉需求和交互契约一起交给它:打开时焦点在哪里,按 Escape 会发生什么,取消是否保留原值,关闭后又回到哪里。本文用昵称编辑器演示,数据只保存在当前页面,不涉及账号修改。

一 先写下四条交互约定

打开弹窗后,焦点进入昵称输入框;取消与 Escape 都不保存;保存后更新页面文本;关闭后焦点回到打开按钮。弹窗应有可访问名称,输入框应有显式标签,并保留看得见的关闭方式。对于简单模态编辑器,原生 <dialog> 可以作为起点,减少自己模拟焦点和背景交互的工作。

MDN dialog 文档介绍了 showModal()、初始焦点和 Escape 的默认行为。仍需在目标浏览器与辅助技术组合中检查,使用原生元素不等于整页自动符合无障碍要求。

二 完整示例

把下面内容保存成 dialog-demo.html,用目标浏览器打开。它没有外部依赖,也没有向服务器提交数据。

html 示例代码
<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>昵称编辑示例</title>
<style>
  body { font: 18px/1.6 system-ui; margin: 2rem; }
  dialog { max-width: min(26rem, 85vw); border-radius: 12px; }
  dialog::backdrop { background: rgb(0 0 0 / .45); }
  input, button { font: inherit; margin-block: .4rem; }
  :focus-visible { outline: 3px solid #165bca; outline-offset: 3px; }
</style>
<p>昵称:<span id="name">小林</span></p>
<button id="open" type="button">编辑昵称</button>
<dialog id="editor" aria-labelledby="dialog-title">
  <h1 id="dialog-title">编辑昵称</h1>
  <form method="dialog">
    <label for="nickname">昵称,最多 20 个字符</label>
    <input id="nickname" name="nickname" required maxlength="20" autofocus>
    <p>
      <button id="cancel" type="button">取消</button>
      <button value="save">保存</button>
    </p>
  </form>
</dialog>
<script>
  const opener = document.querySelector('#open');
  const editor = document.querySelector('#editor');
  const input = document.querySelector('#nickname');
  const name = document.querySelector('#name');
  opener.addEventListener('click', () => {
    input.value = name.textContent;
    editor.returnValue = '';
    editor.showModal();
  });
  document.querySelector('#cancel').addEventListener('click', () => {
    editor.close('cancel');
  });
  editor.addEventListener('close', () => {
    if (editor.returnValue === 'save') name.textContent = input.value;
    opener.focus();
  });
</script>
</html>

取消按钮使用普通按钮并显式关闭,保存是唯一提交按钮,避免在输入框按 Enter 时触发取消。每次打开都清空 returnValue,避免上一次保存留下的值影响后续取消判断。显示昵称使用 textContent,不把用户输入当作 HTML 解析。这里的 maxlength 是浏览器输入长度约束,并非精确的“用户感知字符”计数;如果产品按表情或组合字符计费,应另定规则。

三 给 Claude 的提示词

可复制提示词
请为一个本地昵称编辑器实现原生 dialog 弹窗,不使用框架或外部依赖。
页面初始昵称为“小林”。打开后聚焦带显式 label 的输入框;取消与 Escape 不保存;
保存更新页面纯文本;关闭后焦点返回打开按钮。弹窗需要可访问名称和可见焦点样式。
给出单个完整 HTML 文件,并逐项解释交互状态。
不要声称通过无障碍认证。请列出需要真实浏览器和屏幕阅读器手动检查的步骤。

如果让 Claude 修改既有组件,附上打开按钮与弹窗的完整结构,而不只贴 CSS。焦点问题经常发生在组件卸载、按钮消失或多个弹窗共享状态的地方,截图无法证明这些行为。

四 按操作路径验收

先只使用键盘:Tab 到打开按钮,按 Enter,确认输入框获得焦点;修改后按 Escape,原昵称不变;重新打开并保存,确认新值显示。输入留空时,保存应被原生校验阻止,取消仍应可用。还要检查 Tab 与 Shift+Tab 的移动、关闭后的焦点位置,以及小屏幕放大后的可读性。

再用你支持的屏幕阅读器确认弹窗名称、输入标签和按钮用途能被理解。本文提供完整示例与验收清单,未在真实浏览器或屏幕阅读器中执行,因此不把这些检查标为通过。如果接入服务器,保存失败时应留在弹窗并说明错误;只有保存成功后才更新原值与关闭,不能沿用本地示例直接假定网络成功。

五 不同弹窗需要不同关闭规则

删除确认、长篇条款和多步骤表单的焦点安排,不一定与昵称编辑器相同。先确定用户进入后最需要理解或操作什么,再决定初始焦点,别把所有弹窗都强制聚焦第一个按钮。若打开按钮会在保存后被移除,应选一个仍存在且合理的返回位置,而不是盲目调用它的焦点方法。对有未保存长文本的表单,关闭前是否提示也应由产品明确决定,不能把昵称示例的立即取消行为照搬过去。

方法参考:Anthropic 提示工程概览。