Paperclip UI 设计系统指南,用于构建一致、可复用的前端 组件。在创建新的 UI 组件、修改现有组件、向前端添加页面或功能、设计 UI 元素,或需要理解设计语言和约定时使用。涵盖:组件创建、设计令牌、排版、状态/优先级系统、组合模式以及 /design-guide 展示页面。始终将此技能与 frontend-design 技能(视觉质量)和 web-design-guidelines 技能(Web 最佳实践)结合使用。
Paperclip 设计指南
Paperclip 的 UI 是专业级的控制面板——密集、键盘驱动、默认深色主题。每个像素都物有所值。
始终与以下技能一起使用: frontend-design(视觉打磨)和 web-design-guidelines(Web 最佳实践)。
1. 设计原则
- 密集但可扫描。 无需点击即可展示最多信息。空白用于分隔,而非填充。
- 键盘优先。 全局快捷键(Cmd+K, C, [, ])。高级用户很少使用鼠标。
- 上下文相关,而非模态。 内联编辑优于对话框。下拉菜单优于页面导航。
- 默认深色主题。 中性灰色(OKLCH),非纯黑。强调色仅用于状态/优先级。文本是主要视觉元素。
- 组件驱动。 优先使用可复用组件来捕获样式约定。在正确的抽象层次构建——既不过于细粒度,也不过于庞大。
2. 技术栈
- React 19 + TypeScript + Vite
- Tailwind CSS v4 配合 CSS 变量(OKLCH 色彩空间)
- shadcn/ui(new-york 风格,中性基础,启用 CSS 变量)
- Radix UI 原语(可访问性、焦点管理)
- Lucide React 图标(16px 导航,14px 内联)
- class-variance-authority(CVA)用于组件变体
- clsx + tailwind-merge 通过
cn()工具函数
配置:ui/components.json(别名:@/components、@/components/ui、@/lib、@/hooks)
3. 设计令牌
所有令牌在 ui/src/index.css 中定义为 CSS 变量。浅色和深色主题均使用 OKLCH。
颜色
使用语义化令牌名称,切勿使用原始颜色值:
| 令牌 | 用途 |
|---|---|
--background / --foreground |
页面背景和主要文本 |
--card / --card-foreground |
卡片表面 |
--primary / --primary-foreground |
主要操作、强调 |
--secondary / --secondary-foreground |
次要表面 |
--muted / --muted-foreground |
弱化文本、标签 |
--accent / --accent-foreground |
悬停状态、活动导航项 |
--destructive |
破坏性操作 |
--border |
所有边框 |
--ring |
焦点环 |
--sidebar-* |
侧边栏特定变体 |
--chart-1 至 --chart-5 |
数据可视化 |
圆角
单个 --radius 变量(0.625rem)及其派生尺寸:
rounded-sm— 小输入框、药丸形状rounded-md— 按钮、输入框、小组件rounded-lg— 卡片、对话框rounded-xl— 卡片容器、大组件rounded-full— 徽章、头像、状态点
阴影
最小阴影:shadow-xs(轮廓按钮)、shadow-sm(卡片)。无厚重阴影。
4. 排版比例
使用以下精确模式——不要发明新样式:
| 模式 | 类名 | 用途 |
|---|---|---|
| 页面标题 | text-xl font-bold |
页面顶部 |
| 章节标题 | text-lg font-semibold |
主要章节 |
| 章节标题 | text-sm font-semibold text-muted-foreground uppercase tracking-wide |
设计指南中的章节标题、侧边栏 |
| 卡片标题 | text-sm font-medium 或 text-sm font-semibold |
卡片标题、列表项标题 |
| 正文 | text-sm |
默认正文文本 |
| 弱化文本 | text-sm text-muted-foreground |
描述、次要文本 |
| 小标签 | text-xs text-muted-foreground |
元数据、时间戳、属性标签 |
| 等宽标识符 | text-xs font-mono text-muted-foreground |
问题键(PAP-001)、CSS 变量 |
| 大数字 | text-2xl font-bold |
仪表盘指标值 |
| 代码/日志 | font-mono text-xs |
日志输出、代码片段 |
5. 状态与优先级系统
状态颜色(所有实体一致)
定义在 StatusBadge.tsx 和 StatusIcon.tsx 中:
| 状态 | 颜色 | 实体类型 |
|---|---|---|
| active, achieved, completed, succeeded, approved, done | 绿色系 | 代理、目标、问题、审批 |
| running | 青色 | 代理 |
| paused | 橙色 | 代理 |
| idle, pending | 黄色 | 代理、审批 |
| failed, error, rejected, blocked | 红色系 | 运行、代理、审批、问题 |
| archived, planned, backlog, cancelled | 中性灰色 | 各种 |
| todo | 蓝色 | 问题 |
| in_progress | 靛蓝 | 问题 |
| in_review | 紫色 | 问题 |
优先级图标
定义在 PriorityIcon.tsx 中:critical(红色/AlertTriangle)、high(橙色/ArrowUp)、medium(黄色/Minus)、low(蓝色/ArrowDown)。
代理状态点
内联彩色点:running(青色,animate-pulse)、active(绿色)、paused(黄色)、error(红色)、offline(中性)。
6. 组件层次结构
三个层级:
- shadcn/ui 原语(
ui/src/components/ui/)—— Button、Card、Input、Badge、Dialog、Tabs 等。不要直接修改这些组件;通过组合扩展。 - 自定义复合组件(
ui/src/components/)—— StatusBadge、EntityRow、MetricCard 等。这些组件捕获 Paperclip 特定的设计语言。 - 页面组件(
ui/src/pages/)—— 将原语和复合组件组合成完整视图。
参见 references/component-index.md 获取完整组件清单及使用指南。
何时创建新组件
在以下情况下创建可复用组件:
- 同一视觉模式出现在 2 个或更多位置
- 该模式具有交互行为(状态更改、内联编辑)
- 该模式编码了领域逻辑(状态颜色、优先级图标)
不要为以下情况创建组件:
- 仅用于单个页面的一次性布局
- 简单的 className 组合(直接使用 Tailwind)
- 不增加语义价值的薄包装
7. 组合模式
这些模式描述了组件如何协同工作。它们可能不是独立的组件,但必须在整个应用中一致使用。
带状态和优先级的实体行
问题和类似实体的标准列表项:
<EntityRow
leading={<><StatusIcon status="in_progress" /><PriorityIcon priority="high" /></>}
identifier="PAP-001"
title="实现认证流程"
subtitle="分配给 Agent Alpha"
trailing={<StatusBadge status="in_progress" />}
onClick={() => {}}
/>
leading 插槽始终为:先 StatusIcon,后 PriorityIcon。trailing 插槽:StatusBadge 或时间戳。
分组列表
按状态标题分组的问题 + 实体行:
<div className="flex items-center gap-2 px-4 py-2 bg-muted/50 rounded-t-md">
<StatusIcon status="in_progress" />
<span className="text-sm font-medium">进行中</span>
<span className="text-xs text-muted-foreground ml-1">2</span>
</div>
<div className="border border-border rounded-b-md">
<EntityRow ... />
<EntityRow ... />
</div>
属性行
属性面板中的键值对:
<div className="flex items-center justify-between py-1.5">
<span className="text-xs text-muted-foreground">状态</span>
<StatusBadge status="active" />
</div>
标签始终为 text-xs text-muted-foreground,值在右侧。包裹在带有 space-y-1 的容器中。
指标卡片网格
响应式网格中的仪表盘指标:
<div className="grid md:grid-cols-2 xl:grid-cols-4 gap-4">
<MetricCard icon={Bot} value={12} label="活跃代理" description="本周 +3" />
...
</div>
进度条(预算)
按阈值着色:绿色(<60%)、黄色(60-85%)、红色(>85%):
<div className="w-full h-2 bg-muted rounded-full overflow-hidden">
<div className="h-full rounded-full bg-green-400" style={{ width: `${pct}%` }} />
</div>
评论线程
作者头部(姓名 + 时间戳)后跟正文,位于带边框的卡片中,使用 space-y-3。下方添加评论文本框和按钮。
成本表格
标准 <table>,使用 text-xs,表头行使用 bg-accent/20,数值使用 font-mono。
日志查看器
bg-neutral-950 rounded-lg p-3 font-mono text-xs 容器。按级别着色行:默认(前景色)、WARN(yellow-400)、ERROR(red-400)、SYS(blue-300)。流式传输时包含实时指示点。
8. 交互模式
悬停状态
- 实体行:
hover:bg-accent/50 - 导航项:
hover:bg-accent/50 hover:text-accent-foreground - 活动导航:
bg-accent text-accent-foreground
焦点
focus-visible:ring-ring focus-visible:ring-[3px]——标准 Tailwind focus-visible 环。
禁用
disabled:opacity-50 disabled:pointer-events-none
内联编辑
使用 InlineEditor 组件——点击文本进行编辑,Enter 保存,Escape 取消。
弹出选择器
StatusIcon 和 PriorityIcon 使用 Radix Popover 进行内联选择。任何可点击的属性打开选择器时遵循此模式。
9. 布局系统
在 Layout.tsx 中定义的三区域布局:
┌──────────┬──────────────────────────────┬──────────────────────┐
│ 侧边栏 │ 面包屑栏 │ │
│ (w-60) ├──────────────────────────────┤ 属性面板 │
│ │ 主内容 (flex-1) │ (w-80, 可选) │
└──────────┴──────────────────────────────┴──────────────────────┘
- 侧边栏:
w-60,可折叠,包含 CompanySwitcher 和 SidebarSections - 属性面板:
w-80,在详情视图中显示,在列表中隐藏 - 主内容:可滚动,
flex-1
10. /design-guide 页面
位置: ui/src/pages/DesignGuide.tsx
路由: /design-guide
这是应用中每个组件和模式的实时展示。它是外观的真相来源。
规则
- 当你添加新的可复用组件时,必须将其添加到设计指南页面。 展示所有变体、尺寸和状态。
- 当你修改现有组件的 API 时,更新其设计指南部分。
- 当你添加新的组合模式时,添加一个部分进行演示。
- 遵循现有结构:使用
<Section title="...">包装器,并用<SubSection>进行分组。 - 保持部分逻辑顺序:基础(颜色、排版)优先,然后是原语,接着是复合组件,最后是模式。
添加新部分
<Section title="我的新组件">
<SubSection title="变体">
{/* 展示所有变体 */}
</SubSection>
<SubSection title="尺寸">
{/* 展示所有尺寸 */}
</SubSection>
<SubSection title="状态">
{/* 展示交互/禁用状态 */}
</SubSection>
</Section>
11. 组件索引
参见 references/component-index.md 获取完整组件清单。
当你创建新的可复用组件时:
- 将其添加到组件索引参考文件中
- 将其添加到 /design-guide 页面
- 遵循现有的命名和文件约定
12. 文件约定
- shadcn 原语:
ui/src/components/ui/{component}.tsx——小写,kebab-case - 自定义组件:
ui/src/components/{ComponentName}.tsx——PascalCase - 页面:
ui/src/pages/{PageName}.tsx——PascalCase - 工具函数:
ui/src/lib/{name}.ts - 钩子:
ui/src/hooks/{useName}.ts - API 模块:
ui/src/api/{entity}.ts - 上下文提供者:
ui/src/context/{Name}Context.tsx
所有组件使用 cn() 来自 @/lib/utils 进行 className 合并。所有具有多个视觉变体的组件使用 CVA 定义变体。
13. 常见错误避免
- 使用原始十六进制/rgb 颜色而非 CSS 变量令牌
- 创建临时排版样式而非使用既定比例
- 硬编码状态颜色而非使用 StatusBadge/StatusIcon
- 构建一次性样式元素而存在可复用组件
- 添加组件但不更新设计指南页面
- 使用
shadow-md或更重——保持阴影最小(仅 xs, sm) - 使用
rounded-2xl或更大——最大为rounded-xl(药丸形状使用rounded-full) - 忘记深色模式——始终使用语义令牌,切勿硬编码浅色/深色值






