170 lines
16 KiB
Markdown
170 lines
16 KiB
Markdown
# 样式设计指南
|
||
|
||
供水前端统一以本地 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)。
|