16 KiB
样式设计指南
供水前端统一以本地 shadcn/ui 为组件基础,使用 Tailwind CSS、共享变体和语义变量。Agent 相关弹窗、面板与菜单保持 shadcn/ui 设计;地图控件与其他工作台浮层使用本文规定的 Acrylic 视觉。适用于工作台、地图控件、Agent、报告、表单和弹层。
本文是唯一的样式规范。业务交互见 Agent 交互与报告设计,状态含义见 状态语言。本文规定统一目标;历史局部配色和样式覆盖需在后续组件修改中逐步对齐,文档合并不代表运行样式已全部迁移。
1. 组件基础
- 优先复用 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。Tailwind 工具类负责布局、间距、尺寸、排版、响应式及交互状态;共享变量负责颜色和材质参数,共享变体负责重复的组件外观。
- 先选组件,再选语义表面,最后调整布局与状态。常用差异通过组件的
variant、size表达;局部差异通过className与 cn 合并。 - 使用
bg-background、bg-card、bg-popover、text-foreground、border-border和ring-ring等语义工具类。@theme inline将它们映射到项目变量;背景与前景成对维护。 - 地图与工作台 Acrylic 的混合层、噪点和回退集中封装为材质类,组件内不重复拼装颜色、模糊和阴影配方,也不把整个控件设置为半透明而降低文字对比度。
- 需要允许工具类覆盖的复合样式放入
@layer components;需要支持 Tailwind 变体的自定义工具使用@utility。修改现有未分层规则前,先核对层叠关系及回退,不直接搬移整段样式。 - 避免同一属性的冲突类;
cn处理已知 Tailwind 类的合并,不负责解决任意 CSS 的层叠。自定义材质类不应依赖className的书写先后来决定优先级,也不靠持续增加选择器权重或!important定制外观。 - 显式颜色仅用于主题定义、图表与地图 API、资源固有颜色和必要的动态值;业务 JSX 优先引用语义变量。
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 界面的视觉方向为宝石蓝操作、银灰外壳、冷瓷阅读面和少量香槟提示。完整色阶见 宝石蓝配色。下表为其材质基线,实际使用通过变量引用;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:
| 共享常量 | 材质类 |
|---|---|
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 交互与报告设计 维护。
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。尺寸和层级适配不能改变这些组件的视觉规范。
设计规则只在本文维护;业务协议与动作留在功能文档,历史测试结果留在交付记录,不作为当前全量验收结论。