mcpField
D
designing-user-experience

designing-user-experience

github.com/osmontero设计与 UI16466 次安装今天更新
代码仓库

关于 designing-user-experience

面向界面设计者和开发者的 UX 技能,强调为组件设计空、加载、错误和部分状态,并覆盖流程、表单、反馈、导航及小屏幕体验。它提供检查清单,帮助在实现前发现失败路径和恢复方式。

主要功能

  1. 01绘制用户流程与分支
  2. 02枚举数据组件状态
  3. 03设计表单验证与错误文案
  4. 04规划反馈时机和恢复路径
  5. 05检查导航与小屏幕交互

适用场景

  1. 01为新用户设计空状态
  2. 02规划搜索无结果与错误恢复
  3. 03改进多步骤表单验证
  4. 04检查删除等不可逆操作

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/osmontero/opencode-skills --skill designing-user-experience

安装后在 Claude Code 中输入/designing-user-experience确认已加载。

附带文件references/flow-patterns.md

详细介绍

设计用户体验

概述

视觉设计决定界面在一切顺利时是什么样子。UX 决定其他时候会发生什么,而大多数时候都并不顺利。

核心原则: 设计状态,而不是屏幕。“屏幕”只是组件的一种状态;只交付这一种状态,就是生成式 UI 看起来已经完成、却经不起真实数据考验的原因。

配套技能: designing-frontend-interfaces 用于视觉设计,building-accessible-interfaces 用于无障碍访问,reviewing-interface-quality 用于审查完成的 UI。

铁律

NO COMPONENT IS DONE UNTIL ITS EMPTY, LOADING, ERROR, AND PARTIAL STATES EXIST

一个只有在有项目时才会渲染的列表,不是列表组件,而只是个演示。如果设计没有回答“没有任何数据的新用户会看到什么”,那设计就不完整。

检查清单

为每一项创建一个任务:

  1. 梳理流程 — 入口 → 步骤 → 成功,以及每个分支
  2. 补全状态矩阵 — 涉及数据的每个组件都要检查
  3. 设计失败路径 — 什么会出错、用户会看到什么、如何恢复
  4. 撰写文案 — 按钮、错误、空状态、确认信息
  5. 设定反馈时限 — 100 毫秒、1 秒、10 秒时会发生什么
  6. 处理具有破坏性和不可逆的操作 — 确认、撤销,或两者兼有
  7. 检查触控和小视口 — 点击目标、触达范围、键盘弹出时的行为
  8. 以首次使用者的身份走一遍流程 — 没有数据、没有权限、网络缓慢时

第 1 步:梳理流程

设计屏幕之前,先用文字写出流程。这只需两分钟,却能暴露出模型图无法揭示的缺口。

GOAL: Reviewer approves a pending expense

Entry:    Email link → deep link into the item (may not be authenticated)
Step 1:   Authenticate                → already logged in? skip
Step 2:   View item + receipt
Step 3:   Approve | Reject | Request info
Success:  Confirmation + next pending item queued
Exit:     No items left → done state, not an empty table

Branches:
  Not authorized for this item     → explain who is, offer to forward
  Item already actioned by someone → show who and when, no error framing
  Receipt fails to load            → approve still possible, receipt shows retry
  Offline mid-approve              → queue and retry, tell them it is queued

分支才是设计工作的重点。 任何分支列表为空的流程,都还没有经过充分思考。

先精简步骤,再美化它们。 每一步都可能让用户放弃。逐一思考:这一步能否设为默认值、推断得出、留待以后,或直接移除?可以推导得出的表单字段就不该询问用户。

常见模式的流程示例——引导入门、搜索与筛选、多步骤向导、撤销、权限和付费墙:references/flow-patterns.md。

第 2 步:状态矩阵

每个显示数据或接受输入的组件都有以下状态。逐一明确列出,不要等到上线后才发现它们。

状态触发条件要求
空 — 首次使用新用户,尚未创建任何内容说明该功能并提供主要操作。不要只写“没有数据”。
空 — 无结果筛选或搜索没有匹配结果回显查询内容,并提供清除筛选条件的选项。此状态不同于首次使用时的空状态。
空 — 已清空用户已完成所有事项对此予以确认。这是成功状态,而不是缺失状态。
加载中 — 首次加载没有缓存数据显示与实际布局一致的骨架屏,延迟约 200 毫秒
加载中 — 刷新已有数据,正在更新保留旧数据可见,并显示不显眼的指示器。绝不要清空屏幕。
部分加载部分来源加载失败显示已加载的内容,标记未加载的内容,并提供针对该部分的重试选项
错误 — 可恢复超时、5xx、网络问题说明发生了什么、该怎么做,并提供重试控件
错误 — 永久性404、已删除、已撤销明确说明情况,并提供最接近的有用目标位置
错误 — 权限403说明谁有访问权限,以及如何申请
离线连接中断说明哪些功能仍可用,以及哪些操作已排队
数据过多10,000 行使用分页或虚拟化,并显示数量
数据过期缓存超过阈值显示时间戳和刷新控件
成功操作已完成确认操作,并说明发生了什么变化

四种空状态确实各不相同。 把它们统统简化为“找不到项目”,是生成式界面中最常见的 UX 捷径。

First use:   "No expenses yet — add your first to start tracking."     [Add expense]
No results:  "No expenses match 'q3 travel'."                          [Clear filters]
Cleared:     "All caught up. Nothing needs review."
Error:       "Couldn't load expenses. Check your connection."          [Retry]

第 3 步:表单

大多数 UX 问题都出在表单上,因为用户正是在这里实际输入内容。

结构
  • 单列。 多列表单会导致字段被跳过,且键盘导航顺序不明确。例外:确实成对的字段(城市/州、有效期/CVC)。
  • 标签放在输入框上方,并始终可见。用占位符充当标签会在聚焦时消失、对比度低时难以辨认,还会影响自动填充和屏幕阅读器。
  • 用恰当的间距将相关字段分组(参见 designing-frontend-interfaces 中的邻近原则)。
  • 标注较少见的情况——如果大多数字段为必填项,就标注选填项。绝不能什么都不标。
  • 在用户输入前说明要求,不要等到输入后再报错。“至少 8 个字符,包含一个数字”应从一开始就显示在字段下方。
验证时机
何时怎么做
用户正在输入,且字段从未失焦不做任何操作。在用户输入邮箱的第 3 个字符时就验证,会让人反感。
字段非空且失焦时验证该字段
输入过程中,且已显示错误后实时重新验证,以便用户修正后清除错误
提交时验证所有字段,将焦点移至第一个无效字段;若无效字段超过 2 个,则在顶部汇总
服务端拒绝时将错误对应到具体字段;绝不能只显示横幅

错误应显示在字段旁边,不能只在汇总中显示。对于较长的表单,顶部汇总是补充,绝不能替代字段旁的错误提示。

输入类型

正确设置这些内容,是移动端表单体验的关键所在——这样就会自动显示正确的键盘。

<input type="email"    inputmode="email"    autocomplete="email">
<input type="tel"      inputmode="tel"      autocomplete="tel">
<input type="text"     inputmode="numeric"  autocomplete="one-time-code" pattern="[0-9]*">
<input type="password" autocomplete="current-password">
<input type="password" autocomplete="new-password">
<input type="text"     autocomplete="street-address">

对于代码、PIN 和银行卡号,应使用 inputmode="numeric",而不是 type="number"——type="number" 会添加微调按钮、允许输入 e 和 -,还会悄悄去掉前导零。

绝不要阻止粘贴。 在密码或确认字段中阻止粘贴会破坏密码管理器的功能,对任何人都没有帮助。

数据处理
  • 出错时绝不要清空表单。 输入的数据丢失,是表单最令人恼火的行为。
  • 表单较长时,应在页面导航过程中保留输入内容——可以使用 sessionStorage 或服务端草稿。
  • 尽量宽松地接受输入。 对银行卡号和电话号码去除空格,而不是直接拒绝。接受 +1 (555) 123-4567,并自行将其规范化。
  • 仅在提交过程中禁用提交按钮,绝不能将其用作验证门槛。按钮始终处于禁用状态又没有任何说明,会让用户无从操作。

第 4 步:文案

界面文案属于用户体验,而不是装饰。它往往决定了某种状态是否可用。

按钮

写明具体操作,而不是抽象概念。

弱强
提交发送邀请
确定删除 3 个文件
是/否放弃更改/继续编辑
继续查看订单

确认对话框中的按钮必须在不看对话框文字的情况下也能看懂。在删除确认框中使用“确定”和“取消”,会迫使用户重新阅读提示,才能判断哪个操作具有破坏性。

错误

包含三个部分:发生了什么、为什么、该怎么做。绝不要向用户显示堆栈跟踪或原始状态码。

差好
“错误:输入无效”“请输入今天之后的日期——此活动已经结束。”
“出了点问题”“无法保存。连接已断开——我们保留了你的更改。[重试]”
“错误 403”“你无权访问此项目。请向项目所有者 Dana Reyes 申请访问权限。”
“邮箱无效”“邮箱中需要包含 @——你想输入的是 [email protected] 吗?”

绝不要责怪用户。“你输入了无效日期”→“该日期已经过去。”

语气
  • 使用第二人称、主动语态和现在时。
  • 简短。删掉所有不会影响用户操作的句子。
  • 错误状态中不要使用感叹号。
  • 不要使用用户未提及的术语——“身份验证令牌已过期”→“你已退出登录。”
  • 按钮和标题使用句首字母大写;在界面中,标题式大小写会显得像在大喊。

第 5 步:反馈与延迟

每次用户操作都需要在 100ms 内得到确认,即使结果需要更长时间才能完成。

耗时要求
0-100ms感觉即时完成。不要显示额外内容。闪烁的加载指示器还不如不显示。
100ms-1s立即提供本地反馈——按钮进入按下/忙碌状态
1-10s显示骨架屏或确定进度。保持布局稳定。
10s+显示实际进度、预计时间和取消控件

对于几乎总能成功的操作(如点赞、加星、重新排序),使用乐观更新:立即应用更改,在收到响应后进行校准;如果失败,则清晰地提示并还原。对于任何涉及财务或破坏性后果的操作,都不要使用乐观更新。

绝不要让内容在指针下方移动。 加载后发生位移的内容会导致误点击。为即将加载的内容预留空间:图片使用 width/height,以及广告位、异步徽章。

第 6 步:破坏性和不可逆操作

优先使用撤销,而不是确认。 确认对话框会打断每位用户,只为防止罕见的错误;撤销则能防止错误,又不会打断任何人。

Do:      [Delete]  →  item removed  →  toast: "Message deleted. [Undo]"  (8-10s)
Instead of:  [Delete]  →  "Are you sure?"  →  [Yes] [No]

仅当撤销确实不可能时才要求确认——例如发送电子邮件、扣款、永久销毁数据,以及任何会影响他人的操作。

真正有效的确认对话框:

  • 用具体信息说明后果,包括数量和名称:“要删除 Q3 Archive 中的 47 条记录吗?此操作无法撤销。”
  • 按钮应标明具体操作,绝不要使用“是/否”。
  • 破坏性操作的按钮应使用醒目的破坏性颜色,并且采用明确的措辞。
  • 仅当操作后果严重且不可逆时,才要求用户输入资源名称。谨慎使用这种阻碍;过度使用会让用户习惯于不加思考地输入。
  • 默认将焦点放在安全选项上。

生产环境的 UI 中绝不要使用 window.confirm()——它无法设置样式、会阻塞主线程,而且屏幕阅读器难以朗读。

第 7 步:导航与信息架构

  • 用户必须始终知道自己身处何处。 在导航中标明当前分区;页面标题应与用户点击进入的目标一致。
  • 层级超过两层时使用面包屑。
  • 返回功能必须有效。 模态框、筛选器、标签页和步骤都应可通过 URL 访问,以确保返回和刷新时行为正常。刷新后筛选视图重置,就说明功能有问题。
  • 深层链接在身份验证后也必须有效。 用户应先进入登录页,然后返回最初请求的资源,而不是仪表板。
  • 扁平胜过深层。 同一层级的七个项目,比三层、每层三个项目更容易理解。只有当某个类别确实有自己的落地内容时,才增加层级。
  • 搜索是一项功能,不是备用方案。 如果“用户如何找到 X”的答案是“搜索”,说明信息架构还需改进——但仍要提供搜索功能。

第 8 步:触控与小视口

规则数值
最小触控目标44×44 CSS px(WCAG 2.2 SC 2.5.8)
目标之间的间距至少 8px
主要操作屏幕下半部分——方便拇指触及
破坏性操作与主要操作保持距离,绝不相邻
仅悬停时显示的操作提示禁止。触控设备没有悬停。
固定底栏需考虑屏幕键盘和安全区域
.bottom-bar { padding-bottom: max(var(--space-s), env(safe-area-inset-bottom)); }
body { min-height: 100dvh; }  /* not 100vh — browser chrome makes it overflow */

每种手势都必须有可见的替代方式。滑动删除可以作为快捷操作,但不能成为唯一的删除方式。

自我检查

  • 每个数据组件都明确区分四种空状态
  • 加载时绝不清空已显示的内容
  • 每条错误信息都说明下一步该做什么,并提供相应操作控件
  • 错误文本不会暴露状态码或堆栈跟踪
  • 表单出错时绝不清空内容
  • 在失去焦点时触发验证,而不是在按键时触发
  • 每个输入框都设置了正确的 type、inputmode 和 autocomplete
  • 按钮标签明确说明其操作,且脱离上下文也能看懂
  • 破坏性操作可撤销,或会显示确认信息并说明具体后果
  • 筛选器、标签页和模态框的状态都反映在 URL 中
  • 触控目标 ≥ 44px,主要操作位于拇指可触及范围内
  • 任何内容都不能只通过悬停才能访问
  • 完整走查整个流程,测试无数据、无权限和网络受限的情况

常见错误

只考虑顺利完成的路径。 使用 3 个预置条目时,一切显示得十分完美;条目数为 0 或 10,000 时,界面却会崩溃。

把“无数据”当作空状态。 这既没有告诉用户任何信息,也没有提供任何操作。空状态是产品中引导新用户效果最显著的界面。

刷新时用加载指示器替换整个页面。 用户原本能看到内容,现在却什么也看不到。保留现有内容,并提示内容正在更新。

禁用提交按钮,却不作解释。 用户不知道还缺少什么。应启用按钮,并在点击时验证;或者说明哪些内容尚未完成。

到处都用确认对话框。 对所有操作都要求确认,会让用户养成不看内容就关闭对话框的习惯,这比不提供确认更糟。可以撤销时,就提供撤销功能。

会自动消失的错误提示。 用 4 秒后消失的提示来传达故障的唯一说明,用户很可能会错过。错误信息应持续显示,直到用户将其关闭;只有成功提示才自动消失。

模态框中再嵌套模态框。 这几乎总是说明该流程需要一个页面,而不是再叠加一层界面。

没有标签的纯图标按钮。 容易识别的图标只有少数几种:关闭、搜索、菜单和加号。其他图标都需要配上可见标签;至少也要提供工具提示和无障碍名称。

评论

支持 Markdown