Files
next-tjwater-frontend/docs/style-design-guide.md
T
jiang 2d8506fea0
Generic Container CI/CD / test-build-publish (push) Successful in 2m9s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m39s
feat: add project-aware agent workspace
2026-10-22 18:52:18 +08:00

170 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 样式设计指南
供水前端统一以本地 shadcn/ui 为组件基础,使用 Tailwind CSS、共享变体和语义变量。Agent 相关弹窗、面板与菜单保持 shadcn/ui 设计;地图控件与其他工作台浮层使用本文规定的 Acrylic 视觉。适用于工作台、地图控件、Agent、报告、表单和弹层。
本文是唯一的样式规范。业务交互见 [Agent 交互与报告设计](agent-chat-ui-design.md),状态含义见 [状态语言](status-language.md)。本文规定统一目标;历史局部配色和样式覆盖需在后续组件修改中逐步对齐,文档合并不代表运行样式已全部迁移。
## 1. 组件基础
- 优先复用 [src/shared/ui](../src/shared/ui/) 的本地组件;缺少能力时,按需引入与现有 Radix 技术栈匹配的 shadcn/ui 源码,再做样式适配。
- shadcn/ui 提供组件结构与组合方式,Radix 提供相应的基础交互。定制外观时保留语义、键盘操作、焦点管理、禁用和加载行为。
- 业务模块组合共享组件,负责数据、权限和动作;共享组件保持通用。AI Elements 用于聊天展示组合,与 Agent 的 shadcn/ui 组件使用同一套主题变量。
- 不批量覆盖已有组件,不引入第二套 UI 或样式体系。使用 CLI 前先核对 `components.json`;配置继续指向 Vite、TypeScript、Tailwind 4、`@/shared/ui` 和 `@/shared/ui/cn`,关闭 React Server Components。
- 界面图标统一从 `lucide-react` 按名称引入,使用其默认 2px 描边,不复制图标 SVG 路径或用字符替代操作图标。常规控件图标为 16px,紧凑说明可用 12px 至 14px;图标尺寸与按钮命中区域分别设置。图标按钮提供中文可访问名称,装饰性图标使用 `aria-hidden`。
- 界面动画统一使用 Motion,React 动画组件与 Hook 从 `motion/react` 引入,覆盖入场、退出、位置与布局变化及交互过渡。尊重 `prefers-reduced-motion`,减少动态效果时关闭非必要动画;连续拖拽调宽不附加布局动画。
- 保留本地 shadcn/ui 组件自带的基础动效,避免重复叠加。`AgentPersona` 等已有 Rive 专用资源动画继续按其功能文档维护,Motion 不替代资源内部的状态机与动画。
### Agent 弹窗与面板
Agent 相关界面保持项目本地 shadcn/ui 组件的设计,包括背景、边框、圆角、阴影、排版、间距及交互状态。该规则覆盖主对话面板、手机 Agent 面板、历史对话、主题新建与管理、模型菜单、权限与问题确认、Agent 回答的展开阅读面板,以及这些界面的子弹窗和提示。
| 场景 | 组件与组合 |
|---|---|
| 历史、主题表单、独立详情与确认 | `Dialog`、`DialogTitle`、`DialogDescription`,组合 `Input`、`Button` 和列表 |
| 对话、审批、问答与展开阅读面板 | 本地 shadcn/ui 面板布局,按需组合 `Card`、`Separator`、`Tabs`、`ResizablePanelGroup` 与 AI Elements |
| 模型、主题与会话操作菜单 | `DropdownMenu` 及其菜单项、分组和分隔线 |
| 辅助说明与状态 | `Tooltip`、`HoverCard`、`Badge` 及共享状态组件 |
- 使用已配置的 shadcn/ui 主题变量:`bg-background`、`bg-card`、`bg-popover`、`text-foreground`、`text-muted-foreground`、`border-border`、`ring-ring` 等。按钮、输入和菜单项优先使用本地默认样式及 `variant`、`size`,不为 Agent 另建配色和控件外观。
- 历史和主题弹窗使用 `bg-card`,与 Agent 主对话区保持白色实体表面,标题区和列表不另铺灰色底。通过 Portal 渲染的弹窗及菜单标记 `data-agent-theme="chat"`,复用主面板的现有主题变量,避免继承工作台银灰色底板;保留本地 `Dialog` 的遮罩、边框、阴影与交互样式。
- Agent 表面不套用 `acrylic-panel`、`acrylic-panel-white`、`acrylic-control`、`glass-transient` 等地图材质类,也不以 `surface-dock`、`surface-reading` 等材质类替换 shadcn/ui 面板背景。不叠加毛玻璃、噪点、渐变高光、发光边缘或额外阴影。
- 业务适配可调整宽高、最大高度、滚动、分栏、层级和响应式布局;手机全屏历史与抽屉布局仍沿用相同的组件设计。保留组件的标题、说明、关闭、焦点、键盘和禁用行为,避免用全局 CSS 重绘 Agent 内的按钮、输入、菜单或弹窗。
- 危险操作使用明确的确认步骤和 `destructive` 按钮变体;失败保留输入与原内容。审批、提问与历史操作的业务规则由对应功能文档维护。
- Agent 打开的既有地图或业务工具仍遵循其所属模块规范。`AgentPersona` 动画资源按专用设计文档维护,周边面板与控件遵循本节。
## 2. Tailwind 定制方式
样式统一进入 [src/styles.css](../src/styles.css)。Tailwind 工具类负责布局、间距、尺寸、排版、响应式及交互状态;共享变量负责颜色和材质参数,共享变体负责重复的组件外观。
1. 先选组件,再选语义表面,最后调整布局与状态。常用差异通过组件的 `variant`、`size` 表达;局部差异通过 `className` 与 [cn](../src/shared/ui/cn.ts) 合并。
2. 使用 `bg-background`、`bg-card`、`bg-popover`、`text-foreground`、`border-border` 和 `ring-ring` 等语义工具类。`@theme inline` 将它们映射到项目变量;背景与前景成对维护。
3. 地图与工作台 Acrylic 的混合层、噪点和回退集中封装为材质类,组件内不重复拼装颜色、模糊和阴影配方,也不把整个控件设置为半透明而降低文字对比度。
4. 需要允许工具类覆盖的复合样式放入 `@layer components`;需要支持 Tailwind 变体的自定义工具使用 `@utility`。修改现有未分层规则前,先核对层叠关系及回退,不直接搬移整段样式。
5. 避免同一属性的冲突类;`cn` 处理已知 Tailwind 类的合并,不负责解决任意 CSS 的层叠。自定义材质类不应依赖 `className` 的书写先后来决定优先级,也不靠持续增加选择器权重或 `!important` 定制外观。
6. 显式颜色仅用于主题定义、图表与地图 API、资源固有颜色和必要的动态值;业务 JSX 优先引用语义变量。
```tsx
import { Button } from "@/shared/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/ui/card";
// 独立地图浮层;放入已有 Acrylic 外壳时改用内部内容表面。
<Card className="acrylic-panel w-full max-w-sm">
<CardHeader className="p-3">
<CardTitle className="text-sm">分析结果</CardTitle>
</CardHeader>
<CardContent className="surface-reading space-y-3 p-3">
<p className="text-sm text-foreground">展示已有结论与证据。</p>
<Button variant="outline" size="sm">查看依据</Button>
</CardContent>
</Card>
```
## 3. 颜色与状态
地图与工作台 Acrylic 界面的视觉方向为宝石蓝操作、银灰外壳、冷瓷阅读面和少量香槟提示。完整色阶见 [宝石蓝配色](gem-blue-palette.svg)。下表为其材质基线,实际使用通过变量引用;Agent 弹窗与面板沿用已配置的 shadcn/ui 主题变量,不从下表另建局部色板。
| 角色 | 语义变量 | 基线 |
|---|---|---|
| 主操作 | `--action-blue` | `#4263C7` |
| 主操作 hover / 按压 | `--action-blue-hover` / `--action-blue-pressed` | `#3653B0` / `#2B469C` |
| 外壳色调 | `--surface-panel` | 银霜 `#E6E9F2` |
| 常驻底板、普通控件 | `--surface-dock` / `--surface-subtle` | `#EBEEF5` |
| 正文与表单 | `--surface-reading` | 冷瓷 `#F5F7FA`,按阅读场景保持高遮蔽度 |
| 选中背景 | `--action-selection-soft` | `#DAE5FD` |
| 正文 / 辅助文字 | `--ink` / `--ink-muted` | `#232935` / `#4E5566` |
| 边框 / 分隔线 | `--surface-border` / `--surface-divider` | `#BEC2CD` / `#D5D9E1` |
| 警告与确认提示 | `--status-warning-*` | 香槟色系,小面积使用 |
状态使用 `status-tone-neutral/info/success/warning/danger` 与共享 `StatusBadge`、`StatusIcon`、`StatusDot`,同时提供文字或图标。业务状态、交互选中和数据系列颜色各自独立;`material-tone-agent` 只标记 Agent 解释或建议,原始监测值和人工资料继续使用普通阅读面。
Agent 使用 shadcn/ui 的实体表面和现有主题色,不将这种外观列为待迁移到 Acrylic 的差异。已有 Agent 专用配色、材质和控件 CSS 覆盖应在对应组件调整时收敛到本地 shadcn/ui 样式;是否完成以运行界面验收为准。
## 4. 材质与层级
本节的 Acrylic 材质规则适用于地图与其他工作台界面;Agent 弹窗与面板按前述 shadcn/ui 规则执行。Acrylic 通过半透明色调、背景模糊、混合层和细噪点建立层级,边缘高光与阴影保持克制。常驻、参与布局的业务区域使用实体底板;Mica 仅作为这一底板角色的设计参考,Web CSS 实体色不等同于原生系统 Mica。
| 表面类 | 用途 |
|---|---|
| `acrylic-navigation` | 透出地图背景的顶部导航 |
| `acrylic-panel` | 图层、图例、工况、要素详情和菜单等独立地图浮层 |
| `acrylic-panel-white` | 与 `acrylic-panel` 配合的白色变体,如项目切换对话框 |
| `acrylic-control` | 工具栏、缩放、比例尺和底图入口 |
| `glass-transient` | 活动任务浮条和地图临时通知 |
| `surface-dock` | 非 Agent 的常驻业务面板、分析成果及业务报告外壳与标题区 |
| `surface-control` | 内部按钮、筛选器和紧凑操作区 |
| `surface-well` | 低密度分组、空白支撑区和内部凹槽 |
| `surface-reading` | 消息、报告、表格、属性、证据和表单 |
一个浮动区域只由最外层承担背景模糊,内部使用内容表面。同一区域的工具面板相互替换,避免叠加 Acrylic。常驻底板可以承载独立临时浮层,标题栏按背景关系选择材质。
地图纹理可影响外壳空白区,不能穿透密集文字。透明度、模糊和阴影由全局变量及 `data-basemap-tone` 适配;具体参数以 CSS 为准,不在多份文档重复维护固定数值。入场动画与定位容器需保证背景采样正常,结束后不保留不必要的合成提示。
减少透明度偏好或不支持 `backdrop-filter` 时,切换高遮蔽度背景并关闭模糊;强制颜色模式使用系统色,关闭纹理与阴影。项目已有浅色主题是当前基线,暗色类名不代表已完成暗色验收。
地图组件继续复用 [map-control-styles.ts](../src/features/map/core/components/map-control-styles.ts):
| 共享常量 | 材质类 |
|---|---|
| `MAP_CONTROL_SURFACE_CLASS_NAME` | `acrylic-control border` |
| `MAP_TOOL_PANEL_SURFACE_CLASS_NAME` | `acrylic-panel border` |
| `MAP_FOCUS_SURFACE_CLASS_NAME` | `acrylic-panel border` |
| `MAP_READABLE_SURFACE_CLASS_NAME` | `surface-well border` |
| `MAP_READABLE_SURFACE_STRONG_CLASS_NAME` | `surface-control border` |
## 5. 排版、密度与布局
沿用 Noto Sans SC,中文正文自然换行,不额外拉开字距。编号、时间和数值使用等宽数字,标签左对齐,数值列右对齐。
| 场景 | 排版约定 |
|---|---|
| 侧栏标题、业务分组标题 | 分别为 14px、13px |
| 紧凑正文与字段标签、辅助信息 | 分别为 12px、11px |
| Agent 消息正文 | 14px,行高 24px |
| 欢迎提示与展开报告标题 | 20px,行高 28px |
| 指标值、单位 | 分别为 24px、12px,数值使用等宽数字 |
业务区间距为 12px 至 14px,Agent 消息之间保留 24px。地图与业务面板的普通控件和内部区域沿用 8px、12px 圆角,独立大面板使用共享 16px 圆角;具体值复用组件变体和地图圆角常量。Agent 弹窗、面板和表单控件沿用本地 shadcn/ui 的默认圆角、间距及尺寸变体。
地图与业务表单的主要按钮目标高度为 40px;基础 `Input` 当前默认 36px,这些业务场景通过 `h-10` 或适配后的字段组件统一。Agent 控件优先沿用 shadcn/ui 默认尺寸和 `size` 变体。紧凑控件保留至少 40px 的互不重叠命中区域,可通过周边留白适配触屏。
地图保持主工作区。浮层、导航、时间轴和正文预留各自安全区,地图背景可延伸到 56px 顶部导航背后。业务内容按“定位、状态、下一步、证据”排列,原始对象与历史按需展开;移动端单列,表格只在自己的容器内横向滚动。
Agent 与主工作区、地图与报告使用共享 `Resizable` 分栏;连续调宽不增加布局过渡。报告展开保留同一组件实例、草稿、筛选与阅读位置。具体尺寸、切换条件和任务交互由 [Agent 交互与报告设计](agent-chat-ui-design.md) 维护。
## 6. 组件与交互规则
| 用途 | 优先组件 |
|---|---|
| 操作 | `Button`,复用 `default`、`outline`、`secondary`、`ghost`、`link` 和 `destructive` 变体 |
| 输入与选择 | `Input`、`Textarea`、`InputGroup`、`FieldSelect`、`Select`、`Checkbox`、`Radio`、`DateTimeField` |
| 分组、状态、数据 | `Card`、`Separator`、共享状态组件、`Table`、`Tabs` |
| 证据与过程 | `Disclosure`、`Accordion`、`Collapsible` |
| 菜单、弹层、解释 | `DropdownMenu`、`Dialog`、`Tooltip`、`HoverCard` |
| 可调工作区 | `ResizablePanelGroup`、`ResizablePanel`、`ResizableHandle` |
`WorkbenchSection` 统一标题、说明、状态和操作;`WorkbenchNotice` 使用局部状态线;`WorkbenchEmptyState` 只说明为空原因与下一步。以分隔线、留白和浅色差组织内容,避免重复嵌套同级卡片。
每个业务区最多一个醒目的主操作。按钮覆盖默认、hover、按压、焦点、禁用和加载态;hover 仅用于支持 hover 的设备,加载时阻止重复提交并保留可读状态。地图与业务控件沿用共享按压反馈,Agent 控件保留本地 shadcn/ui 交互状态;具有专用资源交互的 `AgentPersona` 保留原版悬停,不额外缩放或变暗。
地图与业务表单字段复用 `.form-field`,聚焦只改变原有 1px 边框;组合输入由外层承担焦点边界,无边框输入使用内描边。Agent 字段保留本地 shadcn/ui 输入组件的边框、焦点和错误样式。错误通过文字、`aria-invalid` 和关联说明表达,失败后保留输入。选中与焦点不改变控件尺寸,底图选择卡片使用主题边框和勾选标记,键盘焦点使用共享内描边。
弹层保留标题、关闭入口、焦点管理及触发控件的焦点返回。表单弹窗显式将初始焦点放在首要业务字段,选择框获焦不自动展开。Esc 从内到外处理,外层尊重已消费事件;弹窗容器可承接程序焦点,业务控件仍保留可见焦点。模态遮罩阻断底层地图操作。
状态必须区分无数据、加载中、失败、无权限、未配置与结果未知;保留完整证据、修订及请求号的可读入口。演练数据明确标记,前端展示不能暗示已经完成业务执行或写入。
## 7. 验证与维护
文档修改检查引用路径、示例中的本地组件与属性、命令及 `git diff --check`。运行代码变更执行 `pnpm lint`、`pnpm typecheck`、`pnpm test`;可见 UI 变化增加聚焦的 `pnpm test:browser`,依赖、构建或运行集成变化增加 `pnpm build`。
界面验收覆盖 1280px 及以上桌面和 320px、375px 窄屏,检查长内容、按钮与命中区域、弹层边界、Tab、方向键、Esc、焦点返回及减少动态效果。普通文字与实际合成背景对比度至少 4.5:1,焦点与必要非文字状态至少 3:1,并验证强制颜色、减少透明度与模糊不可用时的回退。
Agent 界面另检查所有弹窗、面板及其子菜单是否沿用本地 shadcn/ui 设计,是否存在地图材质类、额外模糊和阴影、独立 Agent 配色或重绘基础控件的 CSS。尺寸和层级适配不能改变这些组件的视觉规范。
设计规则只在本文维护;业务协议与动作留在功能文档,历史测试结果留在交付记录,不作为当前全量验收结论。
## 官方参考
- [shadcn/ui 组件原则](https://ui.shadcn.com/docs)、[主题变量](https://ui.shadcn.com/docs/theming)、[Vite 接入](https://ui.shadcn.com/docs/installation/vite)、[CLI 配置](https://ui.shadcn.com/docs/components-json)。
- [Tailwind CSS 主题变量](https://tailwindcss.com/docs/theme)、[自定义样式与层叠](https://tailwindcss.com/docs/adding-custom-styles)。
- [Fluent Acrylic](https://learn.microsoft.com/en-us/windows/apps/design/style/acrylic)、[Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica)。