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

16 KiB
Raw Permalink Blame History

样式设计指南

供水前端统一以本地 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 工具类负责布局、间距、尺寸、排版、响应式及交互状态;共享变量负责颜色和材质参数,共享变体负责重复的组件外观。

  1. 先选组件,再选语义表面,最后调整布局与状态。常用差异通过组件的 variant、size 表达;局部差异通过 className 与 cn 合并。
  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 优先引用语义变量。
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。尺寸和层级适配不能改变这些组件的视觉规范。

设计规则只在本文维护;业务协议与动作留在功能文档,历史测试结果留在交付记录,不作为当前全量验收结论。

官方参考