8000 docs: 统一组件库规范为简体中文并建立 ui-patterns 模式库 by qqqqqf-q · Pull Request #43 · felinics/ui · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,083 changes: 197 additions & 886 deletions AGENTS.md

Large diffs are not rendered by default.

124 changes: 0 additions & 124 deletions DESIGN.md

This file was deleted.

14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ workspace resolves it by path with zero build/publish step.
| Path | What it is |
|---|---|
| `src/` | Components + `style.css` (interaction contracts, radius/text/z/alpha token scales) |
| `AGENTS.md` | The atom-level design-token law. Read it before touching any component. |
| `skills/web/` | Page-level design-language skill (AI agent skill) |
| `skills/ui-owners/` | Spacing-owner vocabulary skill (AI agent skill) |
| `AGENTS.md` | The atom-level design-token and foundations contract. Read it before touching any component. |
| `skills/ui-owners/` | Component and layout-primitive vocabulary skill (AI agent skill) |
| `skills/ui-patterns/` | Cross-component interaction and page-pattern library (AI agent skill) |
| `showcase/` | The module's own living reference — a custom spec-driven component showcase (`pnpm dev`) |

## Consuming as a submodule
Expand Down Expand Up @@ -61,11 +61,3 @@ adapts call sites.
`scripts/check-ui-contract.mjs` enforces the token law over these sources;
PRs here are only guard-checked when a host bumps its pointer. Parameterizing
the guard and moving it into this repo's CI is a planned follow-up.
- **Owner components still live in the host** (`apps/web/src/components/`):
SettingsRow, FieldStack, PageShell, etc. The `ui-owners` skill
documents them, so a brand-new host that doesn't share the same page
structure won't get them from this repo yet. Promoting them into `src/` is
a planned follow-up.
- **`skills/web/reference.md`** is a host-specific page map — host
knowledge that travels here for now; splitting portable design language
from host-specific references is a planned follow-up.
201 changes: 34 additions & 167 deletions showcase/AGENTS.md

Large diffs are not rendered by default.

753 changes: 193 additions & 560 deletions skills/ui-owners/SKILL.md

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions skills/ui-patterns/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: ui-patterns
description: 在设计、编写、重构或审查任何包含表单、弹窗表单、自动/手动保存、Toast 提示、加载骨架与空状态、统计数值块、首屏 99/1 渐进披露、ActionCard 二级弹窗、列表与详情切换、页面外壳与分割线、窄屏缩放与滚动容器、实时状态自刷新或危险删除确认的前端界面时必读。本 skill 是 @felinic/ui 的跨组件交互与场景规范库(UI Patterns),按主题拆分为 6 篇独立参考文件,按需读取对应篇章。
---

# UI Patterns — 跨组件交互与场景规范

## 定位与职责边界

前端基建分为四个正交维度,各管一层,不重复说明:

| 维度 | 所在位置 | 解决的问题 |
|---|---|---|
| **工程总纲与宿主架构** | 主仓 `.agents/skills/memoh-frontend-rules/` | 22 条工程与体验承诺(U1–U10 / M1–M8 / D1–D4)、`apps/web` 路由/Store/流式架构与重构流程 |
| **Foundations(基础 Token)** | `packages/ui/AGENTS.md` | 颜色、交互叠色梯、圆角、三类边框、阴影、z 梯、字号与图标阶梯、rem 缩放定律 |
| **Components(组件与原语)** | `packages/ui/skills/ui-owners/SKILL.md` | 单个原子组件与布局原语字典:有哪些组件、各自管什么间距、怎么选型 |
| **UI Patterns(本库)** | `packages/ui/skills/ui-patterns/` | **多个组件组合完成一个用户场景时的交互、布局与文案规则**(对应 `showcase` 侧栏的 `Patterns` 板块) |

当遇到“对话框该用多宽、必填项标不标星号、什么时候用自动保存什么时候放保存按钮、空状态该画实线还是无框、高级设置该原地展开还是弹新窗口”这类跨组件问题时,查本库对应的 Pattern 文件。

## 场景路由索引(按任务按需读取)

不要一次性读取全部参考文件;根据当前任务涉及的界面场景,只读取对应的那几篇:

| Pattern 文件 | 覆盖的场景与规则 | 何时读取 |
|---|---|---|
| [`references/forms.md`](references/forms.md) | **表单与弹窗表单**:新建任务标准表单解剖、弹窗表单统一 `md`(448px / `MEMOH-126`)、13px 标签与 6px 间距、必填与选填标记策略、提交时校验(失焦不闪红)、多步流与视图切换的焦点自动落位、按钮尺寸阶梯与 `Select` 触发器禁套 `Button` | 编写或修改任何页面表单、弹窗表单、登录/引导多步输入流或选择控件 |
| [`references/saving-and-notifications.md`](references/saving-and-notifications.md) | **保存模型、通知反馈与界面文案**:静默自动保存 vs 标题栏/卡片底栏手动保存(防放错位置产生多余分割线)、禁止常驻“已保存”游离碎片、4s 默认 Toast vs 带 Action 长驻 Toast、Label ≠ Placeholder 三语防重、嵌套层级不复读、写用户结果不写底层术语、报错三要素公式 | 涉及设置保存、表单提交反馈、Toast 提示、错误横幅或新增/修改任何 `en`/`zh`/`ja` 界面文案 |
| [`references/loading-and-empty-states.md`](references/loading-and-empty-states.md) | **加载、空状态与统计数值块**:四级加载阶梯、加载骨架与真实内容同形防跳动、`isPending` vs `isLoading`、200ms 延迟防闪、未采样值显 `—` 不伪造 `0`、卡片内无框空状态 vs 独立列表实线空状态(禁虚线空状态)、常驻区块留框 vs 条件区块隐藏、统计磁贴排布(禁纵向细线与卡内塞网格) | 编写任何异步数据加载、列表/表格空状态、概览统计数字块或占位符 |
| [`references/progressive-disclosure.md`](references/progressive-disclosure.md) | **渐进披露与多视图弹窗**:首屏 99/1 法则(首屏只答运行是否正常,1% 深层操作收进具名入口)、`ActionCard` → 单一任务弹窗骨架、弹窗头部两种形态(居左工作台 vs `DialogViewHeader` 列表管理动态居中)、弹窗内列表↔表单切换与 `AutoHeight`、页内折叠(More options / Advanced)的两种固定皮肤与“按关注点而非字段数划分”边界 | 设计设置页首屏层级、添加“高级设置/更多选项”、编写带二级入口的页面或包含列表↔表单切换的弹窗 |
| [`references/layout-and-navigation.md`](references/layout-and-navigation.md) | **页面外壳、分割线、导航与缩放**:`PageShell` 对齐契约与间距阶梯表、单层卡片原则(禁卡套卡与双描边图标块)、卡片内缩细线 vs 容器满宽分割线(禁 wrapper `div` 带底边叠双线)、列表↔详情推拉切换与进出步数对称、窄屏重排与 `@container` 容器查询、随文图标 `em` 缩放与单行 `truncate`、滚动归属与 `[scrollbar-gutter:stable]` 防抖、深色模式零裸色自检 | 搭建新页面或 Tab 外壳、放置分割线、实现列表进详情导航、处理窄屏/字号放大/滚动条抖动或检查深色模式 |
| [`references/degraded-and-destructive.md`](references/degraded-and-destructive.md) | **实时状态、异常降级、危险操作与全局诊断表**:可见性守卫静默自刷新(不甩手动刷新按钮)、相对时间更新提示、同一状态单处渲染、媒体表面不透明遮罩、穷举全部中间态并以真实首帧(`@playing`)门控、数据库缓存与运行时 404 对账、危险与生命周期操作沉底确认、无限列表虚拟化、AI 默认审美陷阱与脏→净全局诊断表 | 编写实时监控/远程桌面/容器状态页、处理网络异常或资源丢失、放置停止/重置/删除等高风险操作,或在重构前做页面全面诊断 |
86 changes: 86 additions & 0 deletions skills/ui-patterns/references/degraded-and-destructive.md
8000
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# 实时状态面板、降级对账、危险操作与反模式清单

涵盖实时状态面板自刷新与首帧门控、运行时 404 对账、危险操作沉底、无限列表虚拟化、AI 默认审美陷阱表与脏→净全局速查表。

## 目录

- [实时状态面板:静默自刷新、单一状态与真实首帧门控](#实时状态面板静默自刷新单一状态与真实首帧门控), L:14
- [运行时真实状态与缓存对账](#运行时真实状态与缓存对账), L:33
- [危险操作与生命周期操作归位](#危险操作与生命周期操作归位), L:38
- [无限增长列表必须虚拟化](#无限增长列表必须虚拟化), L:46
- [AI 默认审美陷阱清单(严禁带入本系统)](#ai-默认审美陷阱清单严禁带入本系统), L:50
- [脏模式 → 干净写法全局速查表](#脏模式--干净写法全局速查表), L:67

## 实时状态面板:静默自刷新、单一状态与真实首帧门控

展示实时运行态的界面(如容器资源占用、远程桌面画面、会话活动流)遵守以下规则(提炼自 `bot-container.vue` 与 `bot-desktop.vue`):

1. **可见时静默自刷新,不把刷新责任甩给用户**:
- 状态与预览界面通过实时流或可见性守卫轮询(监听 `document.visibilityState`,隐藏时暂停、切回时立即拉取、组件卸载时清除定时器)自己保持最新,静默更新时不闪加载态、不弹 Toast,遇到瞬时网络抖动保留上一次有效数据。
- **不要在实时面板上常驻一个手动“刷新(Refresh)”按钮**:常驻刷新按钮等于承认页面自己不会保鲜,还会引出各页按钮带不带图标、用不用 `sm` 的不一致。手动刷新仅限极少数开销巨大、必须由用户明确决定才触发的重型重算。
2. **更新时间用相对时间,不用跳动的绝对时间戳**:
- 显示“刚刚更新 / 5 分钟前更新”(复用 `utils/date-time.ts` 的多语言相对时间格式化),只回答用户关心的“数据新不新”;严禁显示每秒跳动的 `2026/06/16 20:04:11` 日志式时间戳。
3. **同一个状态或进度在全屏只渲染一处**:
- 严禁在画面中央放一张“准备中”进度卡,同时又在底部画一条重复的进度条。两个位置展示同一状态必然产生视觉噪音与状态不同步。
4. **遮盖黑色媒体/视频画面的封面必须完全不透明(`bg-background`)**:
- 视频或远程桌面底框通常是纯黑的,如果上方的“正在准备”遮罩写成了半透明 `bg-background/95`,圆角边缘会透出底下的黑边显得脏乱。用来遮挡未就绪画面的封面一律用实色 `bg-background`。
5. **把后端布尔标志提炼为单一人类状态,不在画面旁摆满状态点矩阵**:
- 不要把后端返回的 `enabled / running / desktop / browser / toolkit` 五六个布尔值原样画成一排圆点矩阵摆在实时画面旁边;实时视图本身已经能看出正在连接、安装中、正常或无法访问,正常时保持安静,仅在需要用户介入处理时展示一条明确的问题提示。
6. **穷举全部中间态,并以“真实首帧到达”而非“传输层连通”作为就绪门控**:
- 实时媒体面不止有“加载中”和“运行中”两个状态,动笔前必须列出全部中间态:**未启动(idle)· 正在连接(connecting)· 已连接但首帧未到达 · 断线重连中(reconnecting)· 无法访问(can't-reach)**。每个中间态都在画面正中央给出可见的旋转图标与单行说明(不要塞在容易被 4:3 高画面顶出视口的底栏角落)。
- **WebRTC / 视频流必须等真实画面帧渲染(`<video @playing>` 置位 `videoReady`,销毁时重置)才切掉加载遮罩**:传输层 `connected` 标志往往在第一帧画面解码前就变绿,直接绑 `connected` 会让用户面对一块像死机一样的纯黑框。

## 运行时真实状态与缓存对账

- 当页面采用“数据库记录优先”展示资源状态(如容器实例信息),但向底层运行时发起的实时查询返回**明确的 404(资源已彻底不存在)**时,必须将该状态对账收敛为“缺失(missing)”,引导界面进入“创建 / 重建”流程。
- 严禁吞掉明确的 404 错误继续把已消失的容器渲染为“健康运行中”,导致用户点任何操作(看指标、建快照、启停)都弹出自相矛盾的“未找到资源”报错。瞬时网络超时则容忍并保留上次记录;二级弹窗内的辅助拉取静默加载,不向主页面抛顶层错误。

## 危险操作与生命周期操作归位

1. **停止、重建、删除等重量级操作绝不放进页面标题栏(`PageShell #actions`)**:
- 页面右上角 `#actions` 会被认知为整页的主推进动作(如“保存”或列表页的“新建”);把 `Stop`、`Recreate`、`Delete` 放在标题栏会严重失衡,把低频运维动作塞进首屏扫视区。
- **沉底归入专属操作区**:把启停、重建、删除等操作统一收进页面底部的独立分组卡片中。若卡片内同时包含常规运维动作(启动/停止)与危险动作(删除),分组标题命名为中性的 **“操作(Actions)”**,而不叫“危险区域(Danger zone)”;仅含纯破坏性操作时才命名危险区域。
2. **操作行不写复读动词的空洞警告词**:
- 在底部操作行里,左侧直接写动作名,右侧放按钮(危险操作用实心红 `<Button variant="destructive">`)。不要在行描述里写“暂停或恢复运行时”这种复述标题的废话,也不要在行上堆砌“此操作不可撤销,请谨慎操作”的套话——真正的风险说明和“是否保留数据”的选项放在点击后弹出的确认框(行内用 `ConfirmPopover`,重型删除用 `ConfirmDeleteDialog`)里,在用户真正做决定的那一刻呈现。

## 无限增长列表必须虚拟化

会话列表、最近记录、模型选择器、带搜索的长下拉框等条目数可能随使用无限增长的列表,一律复用仓库现成的虚拟滚动实现,严禁对无上限数组直接裸写 `v-for`。

## AI 默认审美陷阱清单(严禁带入本系统)

未受约束的模型在写前端时会本能地抓起以下“AI 模板套路”,每一条都直接破坏本系统的平静白卡语言,一律禁止:

| 模型本能抓起的套路 | 为什么破坏本系统 | 本系统的正确做法 |
|---|---|---|
| 每个标题上方或卡片内先摆一个带底框的圆角图标 | 卡套卡 + 图标滥用 | 标题就是纯文字,不加装饰图标 |
| 蓝紫渐变背景、霓虹发光描边、渐变色大字 | 系统 90% 是黑白灰,无渐变、无发光 | 纯色语义 Token + 炭黑主按钮 |
| 等宽等高、每张带“图标+标题+描述”的三列特性卡片墙 | 营销落地页套路,常伴随卡套卡 | 顶部独立统计磁贴(`MetricReadout`)或 `SettingsSection` 行列表 |
| 毛玻璃(`backdrop-blur`)、彩色半透明玻璃卡、到处加 `shadow-md` | 本系统默认全平,阴影仅限 4 个浮层 Token | 实色 `bg-card` + 单根 1px `border-border` 细边,无阴影 |
| 所有文字和块全部水平居中 | 营销页习惯,破坏阅读对齐线 | 在 `max-w-3xl` 外壳内统一左对齐 |
| 把每个按钮都设成实心主按钮 | 摧毁视觉主次层级 | 每屏最多一个炭黑主按钮,其余用 `outline` 或 `ghost` |
| 在块左侧画一条 4px 彩色粗竖线做强调 | 破坏统一的单根 1px 细线语言 | 统一用 `CalloutBanner` 或单根细边,靠文字/图标色表达语义 |
| 弹性过冲(bounce)缓动、页面初次打开时的阶梯依次浮现动画 | 动效过度炫技、拖慢首屏响应 | 首屏直出无入场动画,交互使用固定时长档位与 `ease-out` |
| 到处用等宽字体(`font-mono`)装“技术感” | 破坏排版层级 | 普通文本一律用 `--font-sans` 与 `--text-*` 阶梯,仅真实代码/ID/终端用等宽 |
| 动不动就新开一个模态弹窗装普通设置 | 懒惰容器 | 首选页内 `SettingsRow` 或原地折叠;独立深层任务才用聚焦弹窗 |

## 脏模式 → 干净写法全局速查表

重构老页面(如对照经典反例 `bot-tool-approval.vue`)或提交自检时,按此表逐项清理:

| 脏写法(见到即删) | 正确写法 |
|---|---|
| `bg-muted/40`、`bg-background/70`、`bg-success/5` 烤死底色或手写透明度 | 继承 `bg-card`,需要软底色用 `--muted-soft` / `--destructive-soft` 等 Token |
| `border-border/50`、控件上写 `border-input` / `border-border` | 容器用 `border-border`;控件只用 `--field-edge-*` 或 `--border-hairline` |
| `text-[11px]`、`font-[550]`、`text-foreground/80` | 用 `--text-*` 字号阶梯、`normal/medium/semibold` 三档字重、零色度叠色梯 |
| `<Switch class="scale-90">` 用缩放改控件大小 | 用组件真实的 `size` prop,严禁 `scale-*` 缩放控件 |
| `focus-visible:ring-success/30` 彩色焦点环 | 键盘焦点只用中灰 `--ring`;输入框聚焦原位换 `--field-edge-solid` |
| `opacity-50 grayscale` 禁用态 | 全系统统一 `opacity-40` |
| 吸顶半透明模糊顶栏 `bg-background/95 backdrop-blur` | 标准 `<PageShell>` 标题栏 |
| 卡片内用满宽 `border-b` 或把 `border-b` 写在 `v-if` 包装 `div` 上 | 卡片内行用内缩 `mx-4 ... last:border-b-0`(`SettingsRow`),包装 `div` 不带边框 |
| 在 `SettingsSection` 白卡内给 `<Empty>` 加虚线框或灰底图标块 | 白卡内 `<Empty class="py-12">` 无边框无图标;独立列表外层 `<Empty>` 用实线 `border` |
| 在已带边框的卡片行内放自带 `border` 的 `ItemMedia variant="icon"` | 前导图标只用透明尺寸盒,卡片细线是唯一描边 |
| 把手动保存的 `SettingsSection #footer` 抄到根级设置页 | 根级设置页保存放 `PageShell #actions`;二级详情页才放 `#footer` |
| 用 `<Button variant="outline">` 充当 `Select` / `Combobox` 触发器 | 用 `SelectTrigger` 或 `selectTriggerClass`,避免宽下拉框按压抽动 |
| 弹窗底栏或主操作按钮用 `size="sm"` | 底栏与主操作一律用默认高度 `h-9` |
| 同一标题词在“页面标题 → 分组标题 → 行标签”连念三遍 | 单行分组直接省略 `SettingsSection` 的 `title` |
Loading
Loading
0