构建 Design System 按钮需要多长时间?前后对比
Source: Dev.to
“设计系统文档在哪里?”
如果你曾参与政府或企业项目,你一定听过这句话。然后你打开一份200页的 PDF,寻找颜色代码,复制间距数值,争论边框圆角是 4 px 还是 8 px……仅仅为了一个按钮就耗费半天。
今天我将向你展示实际代码——使用组件库前后的对比。
案例 1:构建按钮
前置:从设计系统 PDF 实现
// 步骤 1:在设计指南中查找颜色值(10 分钟)
// Primary: #0A5ECA, Hover: #0852B2, Active: #064794...
// 步骤 2:编写 CSS(30 分钟)
.btn-primary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
min-width: 80px;
height: 48px;
padding: 0 20px;
border-radius: 6px;
font-size: 16px;
font-weight: 500;
background-color: #0A5ECA;
color: #FFFFFF;
border: none;
cursor: pointer;
transition: background-color 0.2s;
}
.btn-primary:hover { background-color: #0852B2; }
.btn-primary:active { background-color: #064794; }
.btn-primary:disabled{
opacity: 0.5;
cursor: not-allowed;
}
.btn-primary:focus-visible{
outline: 2px solid #0A5ECA;
outline-offset: 2px;
}
// 步骤 3:编写组件(20 分钟)
function Button({ children, ...props }) {
return (
<button {...props}>{children}</button>
);
}
// 步骤 4:添加变体?(1 小时)
// secondary, tertiary, danger… 查找每种颜色,添加 CSS
// 步骤 5:添加尺寸?(30 分钟)
// xs, sm, md, lg, xl… 计算高度、内边距、字体大小
// 总耗时:2‑3 小时
// 下一个项目?重新开始。
之后:使用 HANUI
npx hanui add button
import { Button } from '@/components/ui/button';
// 完成。立即使用。
<Button>Default Button</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="danger">Delete</Button>
<Button isLoading>Saving…</Button>
<Button icon={<SearchIcon />}>Search</Button>
耗时: 10 秒
8 种变体,6 种尺寸,加载状态,图标支持 — 全部已包含。可访问性(aria-busy、aria-disabled、焦点环)会自动应用。
案例 2:表单字段
之前:手动实现
function FormField({ label, error, helperText, required, children }) {
const id = useId();
const errorId = `${id}-error`;
const helperId = `${id}-helper`;
return (
<div>
<label htmlFor={id}>
{label}
{required && <span>*</span>}
</label>
{/* How do I pass id, aria-describedby to children? */}
{/* cloneElement? Context? */}
{children}
{error && (
<p id={errorId}>{error}</p>
)}
{helperText && (
<p id={helperId}>{helperText}</p>
)}
</div>
);
}
// aria-describedby 关联?
// 输入错误样式?
// 错误图标?
// 屏幕阅读器支持?
// … 复杂度不断提升
之后:使用 HANUI
npx hanui add form-field input
import {
FormField,
FormLabel,
FormError,
FormHelperText,
} from '@/components/ui/form-field';
import { Input } from '@/components/ui/input';
<FormField>
<FormLabel>Email</FormLabel>
<Input type="email" />
<FormError>Invalid email format</FormError>
</FormField>
<FormField>
<FormLabel>Username</FormLabel>
<Input type="text" />
<FormHelperText>Username is available</FormHelperText>
</FormField>
Context 会自动连接 id 与 ARIA 属性。错误/成功图标会自动显示。role="alert" 与 aria-live="polite" 会被应用。
案例 3:Header + Mega Menu
从头构建需要 数天。
之前:考虑以下所有因素
- 响应式(移动端汉堡菜单)
- Mega‑menu 下拉菜单
- 键盘导航(Tab、方向键、Esc)
- 焦点捕获
- 滚动行为(粘性/隐藏)
- WAI‑ARIA 模式
老实说,正确实现它需要 一周。
之后:使用 HANUI
npx hanui add header
import { HeaderWithMegaMenu } from '@/components/ui/header';
// Use <HeaderWithMegaMenu /> directly – mega menu, mobile support,
// keyboard navigation, scroll behavior are all included.
实际比较
| 任务 | 手动 | 使用库 |
|---|---|---|
| 按钮(含变体) | 2‑3 小时 | 10 秒 |
| 表单字段(可访问) | 3‑4 小时 | 10 秒 |
| 页眉 + 大型菜单 | 3‑5 天 | 10 秒 |
| 选择框(搜索,多选) | 1‑2 天 | 10 秒 |
| 模态框(焦点捕获) | 半天 | 10 秒 |
手动构建时常被忽视的事项
aria-describedby关联aria-expanded、aria-haspopup- 焦点管理
- 使用 Escape 键关闭
- 屏幕阅读器提示
隐藏的成本
真正的手动实现问题不仅仅是时间。
1. 不一致性
/* Developer A */
.btn { border-radius: 4px; }
/* Developer B */
.button { border-radius: 6px; }
/* Developer C */
.cus { border-radius: 5px; }
当每个团队成员从 PDF 中复制粘贴数值时,细微的差异会悄然出现,导致 UI 零散并增加额外的维护负担。
使用像 HANUI 这样的组件库可以消除猜测,确保可访问性,并让你在几秒钟内而不是几天内交付功能。
tom-btn {
border-radius: 8px;
}
2. 缺失的可访问性
忙碌时,ARIA 属性会被忽略。“稍后再加”最终会变成“审计未通过”。
3. 维护噩梦
设计系统更新?需要手动在所有项目中更新所有组件。
摘要
| 方法 | 所需时间 |
|---|---|
| 从头构建设计系统组件 | 几小时到几天 |
| 使用成熟的组件库 | 几秒钟 |
如果您在做韩国政府项目,HANUI 提供符合 KRDS 的 React 组件,开箱即用。
npx hanui init
npx hanui add button input select form-field header modal
5 分钟即可完成设置。其余时间专注于业务逻辑。
GitHub:
文档
