mcpField
H
harden

harden

github.com/pbakaus设计与 UI92.5k53.0k 次安装今天更新
代码仓库

关于 harden

harden 是一项设计技能,用于检查界面在边界情况和现实故障下的表现。它涵盖输入、错误处理、无障碍、性能和国际化等方面的韧性检查。

主要功能

  1. 01测试极端输入和空数据
  2. 02检查网络与 API 错误
  3. 03改善国际化支持
  4. 04处理无障碍与性能问题
  5. 05检查引导和加载状态

适用场景

  1. 01检查表单对无效或超长输入的处理
  2. 02让布局适应 RTL 和翻译文本
  3. 03规划网络故障后的恢复行为
  4. 04测试空状态和大型数据集

安装

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

$npx skills add https://github.com/pbakaus/impeccable --skill harden

安装后在 Claude Code 中输入/harden确认已加载。

详细介绍

增强界面,使其能够应对边界情况、错误、国际化问题以及会破坏理想化设计的真实使用场景。

评估加固需求

识别薄弱环节和边界情况:

  1. 使用极端输入进行测试:

    • 超长文本(名称、描述、标题)
    • 超短文本(空文本、单个字符)
    • 特殊字符(表情符号、从右向左书写的文本、带变音符号的字符)
    • 大数值(百万、十亿)
    • 大量条目(1000+ 个列表项、50+ 个选项)
    • 无数据(空状态)
  2. 测试错误场景:

    • 网络故障(离线、缓慢、超时)
    • API 错误(400、401、403、404、500)
    • 验证错误
    • 权限错误
    • 速率限制
    • 并发操作
  3. 测试国际化:

    • 较长的译文(德语通常比英语长 30%)
    • RTL 语言(阿拉伯语、希伯来语)
    • 字符集(中文、日语、韩语、表情符号)
    • 日期/时间格式
    • 数字格式(1,000 与 1.000)
    • 货币符号

重要:只适用于完美数据的设计尚未达到可用于生产环境的标准。应针对实际情况进行加固。

加固维度

系统性地提升韧性:

文本溢出与换行

长文本处理:

/* Single line with ellipsis */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Multi-line with clamp */
.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Allow wrapping */
.wrap {
  word-wrap: break-word;
  overflow-wrap: break-word;
  hyphens: auto;
}

Flex/Grid 溢出:

/* Prevent flex items from overflowing */
.flex-item {
  min-width: 0; /* Allow shrinking below content size */
  overflow: hidden;
}

/* Prevent grid items from overflowing */
.grid-item {
  min-width: 0;
  min-height: 0;
}

响应式文本大小:

  • 使用 clamp() 实现流式排版
  • 设置最小可读字号(移动设备上为 14px)
  • 测试文本缩放(缩放至 200%)
  • 确保容器可随文本扩展
国际化(i18n)

文本扩展:

  • 为译文预留 30-40% 的空间
  • 使用可适应内容的 flexbox/grid
  • 使用最长的语言进行测试(通常是德语)
  • 避免为文本容器设置固定宽度
// ❌ Bad: Assumes short English text
<button className="w-24">Submit</button>

// ✅ Good: Adapts to content
<button className="px-4 py-2">Submit</button>

RTL(从右向左)支持:

/* Use logical properties */
margin-inline-start: 1rem; /* Not margin-left */
padding-inline: 1rem; /* Not padding-left/right */
border-inline-end: 1px solid; /* Not border-right */

/* Or use dir attribute */
[dir="rtl"] .arrow { transform: scaleX(-1); }

字符集支持:

  • 全程使用 UTF-8 编码
  • 使用中文/日语/韩语(CJK)字符进行测试
  • 使用表情符号进行测试(每个表情符号可能占 2-4 个字节)
  • 处理不同的文字体系(拉丁文、西里尔文、阿拉伯文等)

日期/时间格式:

// ✅ Use Intl API for proper formatting
new Intl.DateTimeFormat('en-US').format(date); // 1/15/2024
new Intl.DateTimeFormat('de-DE').format(date); // 15.1.2024

new Intl.NumberFormat('en-US', { 
  style: 'currency', 
  currency: 'USD' 
}).format(1234.56); // $1,234.56

复数形式:

// ❌ Bad: Assumes English pluralization
`${count} item${count !== 1 ? 's' : ''}`

// ✅ Good: Use proper i18n library
t('items', { count }) // Handles complex plural rules
错误处理

网络错误:

  • 显示清晰的错误消息
  • 提供重试按钮
  • 说明发生了什么
  • 提供离线模式(如适用)
  • 处理超时场景
// Error states with recovery
{error && (
  <ErrorMessage>
    <p>Failed to load data. {error.message}</p>
    <button onClick={retry}>Try again</button>
  </ErrorMessage>
)}

表单验证错误:

  • 在字段附近显示行内错误
  • 提供清晰、具体的消息
  • 建议如何修正
  • 不要不必要地阻止提交
  • 出错时保留用户输入

API 错误:

  • 根据状态码进行适当处理
    • 400:显示验证错误
    • 401:重定向至登录页面
    • 403:显示权限错误
    • 404:显示未找到状态
    • 429:显示速率限制消息
    • 500:显示通用错误,并提供获取支持的方式

优雅降级:

  • 即使没有 JavaScript,核心功能也能正常运行
  • 图片应有替代文本
  • 渐进式增强
  • 为不受支持的功能提供回退方案
边界情况与临界条件

空状态:

  • 列表中没有条目
  • 没有搜索结果
  • 没有通知
  • 没有可显示的数据
  • 提供清晰的后续操作

加载状态:

  • 初始加载
  • 分页加载
  • 刷新
  • 显示正在加载的内容(“正在加载你的项目……”)
  • 为耗时较长的操作提供时间估计

大型数据集:

  • 分页或虚拟滚动
  • 搜索/筛选功能
  • 性能优化
  • 不要一次性加载全部 10,000 个条目

并发操作:

  • 防止重复提交(加载期间禁用按钮)
  • 处理竞态条件
  • 使用乐观更新,并在失败时回滚
  • 解决冲突

权限状态:

  • 无权查看
  • 无权编辑
  • 只读模式
  • 清楚说明原因

浏览器兼容性:

  • 为现代功能提供 polyfill
  • 为不受支持的 CSS 提供回退方案
  • 进行功能检测(而非浏览器检测)
  • 在目标浏览器中测试
新手引导与首次使用体验

适用于生产环境的功能应服务首次使用的用户,而不只是高级用户。设计能帮助新用户快速获得价值的路径:

空状态:每个无数据页面都需要:

  • 说明或插图,展示这里将显示什么
  • 说明这对用户为何重要
  • 明确的 CTA,用于创建第一项内容或从模板开始
  • 有吸引力的视觉设计(不能只是一片空白,上面写着“还没有内容”)

需要处理的空状态类型:

  • 首次使用:突出价值,提供模板
  • 用户已清空:轻量提示,便于重新创建
  • 无搜索结果:建议更换查询,提供清除筛选条件的选项
  • 无权限:说明原因以及如何获取访问权限

首次使用体验:尽快帮助用户获得“顿悟时刻”。

  • 展示而非讲解——用可运行的示例代替说明
  • 渐进式呈现——一次教一件事,不要一开始就讲完所有内容
  • 让新手引导成为可选项——允许有经验的用户跳过
  • 提供智能默认值,将必要设置降到最低

功能发现:在用户需要时介绍功能,而不是提前讲解。

  • 在使用位置提供情境化提示(简短、可关闭、仅显示一次)
  • 为新功能或未使用的功能添加徽标或指示标记
  • 安静地庆祝功能启用事件(使用 Toast,而不是模态框)

绝不要:

  • 在用户能够使用产品前强制进行冗长的新手引导
  • 反复显示相同的工具提示(记录用户的关闭操作并予以尊重)
  • 在引导式演示期间阻塞整个 UI
  • 创建与真实产品脱节的独立教程模式
  • 设计只写着“没有内容”、却不提供下一步操作的空状态
输入验证与清理

客户端验证:

  • 必填字段
  • 格式验证(电子邮件、电话、URL)
  • 长度限制
  • 模式匹配
  • 自定义验证规则

服务端验证(始终执行):

  • 绝不要只信任客户端
  • 验证并清理所有输入
  • 防范注入攻击
  • 速率限制

约束处理:


<input 
  type="text"
  maxlength="100"
  pattern="[A-Za-z0-9]+"
  required
  aria-describedby="username-hint"
/>
<small id="username-hint">
  Letters and numbers only, up to 100 characters
</small>
无障碍韧性

键盘导航:

  • 所有功能均可通过键盘访问
  • 合理的 Tab 顺序
  • 在模态框中管理焦点
  • 为长内容提供跳转链接

屏幕阅读器支持:

  • 使用恰当的 ARIA 标签
  • 播报动态变化(实时区域)
  • 提供描述性替代文本
  • 使用语义化 HTML

动作敏感性:

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

高对比度模式:

  • 在 Windows 高对比度模式下进行测试
  • 不要只依赖颜色
  • 提供其他视觉提示
性能韧性

网络连接缓慢:

  • 渐进式加载图片
  • 骨架屏
  • 乐观 UI 更新
  • 离线支持(service workers)

内存泄漏:

  • 清理事件监听器
  • 取消订阅
  • 清除计时器/间隔计时器
  • 卸载时中止待处理请求

节流与防抖:

// Debounce search input
const debouncedSearch = debounce(handleSearch, 300);

// Throttle scroll handler
const throttledScroll = throttle(handleScroll, 100);

测试策略

手动测试:

  • 使用极端数据进行测试(极长、极短、空)
  • 使用不同语言进行测试
  • 测试离线情况
  • 测试慢速连接(限制为 3G)
  • 使用屏幕阅读器进行测试
  • 测试仅使用键盘的导航
  • 在旧版浏览器中测试

自动化测试:

  • 针对边界情况的单元测试
  • 针对错误场景的集成测试
  • 针对关键路径的 E2E 测试
  • 视觉回归测试
  • 无障碍测试(axe、WAVE)

重要:加固意味着预想到意料之外的情况。真实用户会做出你从未想象过的操作。

绝不要:

  • 假设输入完美(验证所有内容)
  • 忽视国际化(面向全球进行设计)
  • 使用笼统的错误消息(“发生错误”)
  • 忘记离线场景
  • 只依赖客户端验证
  • 为文本使用固定宽度
  • 假设英文文本长度
  • 在一个组件出错时阻塞整个界面

验证加固效果

使用边缘情况进行全面测试:

  • 长文本:尝试使用长度超过 100 个字符的名称
  • 表情符号:在所有文本字段中使用表情符号
  • RTL:使用阿拉伯语或希伯来语进行测试
  • CJK:使用中文、日语或韩语进行测试
  • 网络问题:断开互联网连接、限制连接速度
  • 大型数据集:使用 1000 多个项目进行测试
  • 并发操作:快速点击提交按钮 10 次
  • 错误:强制触发 API 错误,测试所有错误状态
  • 空状态:删除所有数据,测试空状态

请记住:你要针对真实的生产环境进行加固,而不是追求演示效果的完美。要预料到用户会输入奇怪的数据、在流程中途断开连接,并以意想不到的方式使用你的产品。让每个组件都具备韧性。

评论

支持 Markdown