# Dashboard 全局设计规范（组件未覆盖场景的 Token 兜底）

> 当 `components.index.json` 没有覆盖你要生成的内容时，必须严格遵守本文件 token 约束。
>
> **组件库适配**：本文件 token（`--color-data-*`、`--radius-*`、`--spacing-*` 等）以 **TFDS** 为默认真值（未指定组件库时强制执行，见 `SKILL.md` §3）。若项目**已指定其他组件库**，则把这里的 token 映射到指定库的等价 token（数据色板↔系列色、语义色↔success/danger/warning、圆角/间距↔对应 token）；但**规则本身不放松**——杜绝黑色/非数据色冒充系列色、色彩纯净度、按维度取色等约束依然全部适用。

## 0. 快查索引

- **我缺组件要怎么降级**：看「§4 降级与兜底模板」
- **我不知道哪些能写、哪些不能写**：看「§1 Token 使用铁律」
- **我想确保图表系列色正确 / 不乱用色板**：看「§2 图表色槽与色彩纯净度」
- **我老是用了黑色或非 data 色**：看「§1 🚫 杜绝黑色与非 data 色」+「§2.2 色彩纯净度」
- **我的图表默认色和别的不一样（个别图偏色）**：看「§2.3 模板色一致性自检」
- **关联阅读**：
  - 复用/降级策略总入口：`SKILL.md` §4.2
  - 常见失败反例：`COMMON_FAILURES.md`

## 1. Token 使用铁律

- 禁止写死颜色 hex（图表 data 色槽例外：由 theme.css 定义 `--color-data-*`）
- 禁止 Tailwind 任意值：`text-[#...]`、`p-[18px]`、`rounded-[10px]`
  - **唯一豁免**：卡片内边距统一用 `DASHBOARD_CARD_PADDING_CLASS`（= `pt-4 px-[20px] pb-[20px]`，即上16/左右下20）。20px 是设计规定的卡片内边距、theme.css 无对应 token，因此允许此一处任意值；除此之外不得新增任意值间距。
- 颜色/间距/圆角/字体全部使用 `theme.css` 的 `--color-* / --spacing-* / --radius-* / --text-*` 变量（间距常用 `--spacing-3/4/6` = 12/16/24，模块与列默认 `gap-3` 即 12px）
- **🚫 杜绝黑色与非 data 色（高频违规，零容忍）**：
  - **禁止任何纯黑/近黑**：不得用 `black`、`text-black`、`#000`、`#111`、`rgba(0,0,0,..)`、`text-[#000…]` 等表达文字/图标/描边。文字一律走 `--color-foreground`（主，blueGrey-900）/ `--color-foreground-secondary`（副）/ `--color-foreground-muted`（辅助）。
  - **图表系列色：data 色槽 + 品牌色（允许，但非黑/近黑）**：系列/数据元素的颜色优先来自 `--color-data-*`（或经 `resolveColorToken` 解析）；**允许**使用品牌色（如 `--color-brand-*`）作为系列色，但**仍禁止**借用 `--color-foreground` / 灰阶文字色 / 任意 hex / 黑色或近黑色冒充系列色。简记：**可以用 data 槽和品牌色，不能用文字色/黑色/瞎写 hex**。
  - **中性/底噪也要走 token**：网格 `--color-border-chart-grid`、轴 `--color-border-chart-axis`、分割线 `--color-border-divider`、边框 `--color-border`；不要手写灰色 hex。
- **封装 UI 链路硬门禁（图表/看板）**：
  - 必须 `import "@tfdesign/dashboard/theme.css"`（或通过项目入口引入，但必须可定位到代码位置）
  - 图表必须优先使用 `@tfdesign/dashboard` 的 Smart*Chart / Preview / 模块卡，禁止直接用 Recharts/ECharts/AntV 默认直出
  - 颜色解析必须走 `token-resolver/resolveColorToken`（或仓内等价工具），业务层禁止传 hex/rgba
  - tooltip/legend 结构禁止自造，必须复用封装输出；布局禁止 `position: absolute` 固定像素摆放图表子区

## 2. 图表色槽与色彩纯净度

### 2.1 色槽来源（唯一真值）

- 系列色：`--color-data-0` … `--color-data-20`（按系列索引取；TFDS 仅有 0–20 共 21 槽，**没有 data-21**）
- 类别色：`--color-chart-categorical-0` … `--color-chart-categorical-20`
- ⭐ **模板默认色（最高优先级，所有图表"零配置"输出必须命中）**：
  - **首色** = `data-0`（**青绿 `#70E5C0`**）
  - **次色** = `data-4`（**浅蓝 `#3CCBFF`**）
  - 即默认序列优先级 = `[data-0, data-4]`，由 `getDefaultDataColorToken(idx)` 输出（见 `src/components/charts/chart-common.js`）
  - **任何 Smart\*Chart 不传 `colorToken` 时**都必须命中这两色；**模板/Preview/Section 内若硬写默认色**，也必须等于这两色（不要写 `data-1`/`data-2`/`data-5` 等非默认槽）
  - 仅当出现以下 4 种**业务豁免**才能偏离默认色：① §2.1 涨跌色段（语义强绑定）；② 用户在 props/spec 显式覆写 `colorToken`（任何 Smart*Chart 都允许覆写）；③ tone 切换（如 GaugeChart 的 red/yellow/green/blue tone）；④ 多维场景按 §2.2 第 2/3 条取同色系或遍历色板。
- 🚨 **涨跌 / 升降色（Dashboard 专属规则，以 dashboard 为准，禁止用 theme.css 的 `--color-success/--color-danger`）**：
  - **涨 / 升 / 正向** → `--status-success`（**绿 `#24CDA5`**）
  - **跌 / 降 / 负向** → `--status-danger`（**红 `#FC7E90`**）
  - **持平 / 中立** → 中性灰 `#98A2B3`
  - **为什么不能用 theme.css 语义色**：theme.css 里 `--color-success` 底层是 data-7（`#A3E6FF` 浅蓝）、`--color-danger` 是 data-5（`#B399FE` 紫），**根本不是绿红**，用它们表达涨跌会出错。涨跌必须走 dashboard 的 `--status-success/--status-danger`（与 `SmartIndicator`/`ProportionBarCard` 一致），且**禁止用 data-* 或其它色值**冒充升降色。
- 其它语义色（非涨跌场景，可用 theme.css 语义 token）：
  - 警告 → `--color-warning`
  - 总量 / 常规中立面积 → 中性槽 `--color-data-19`（`#797E99`）或 `--color-data-20`（`#E4E7EC`）

### 2.2 色彩纯净度（控制"调色盘乱用"，整页 ≥80% 面积为主色/中性）

> 目标：杜绝"图表随意遍历色板"导致的花哨与降级；同时杜绝用黑色/灰文字色冒充系列色。

1. **单维度图表（单折线/单柱）**：无论页面有多少张，**统一用模板默认首色 `--color-data-0`**（即 §2.1 默认序列首位），不要每张换色，也不要切到 `data-1`/`data-2`。
2. **多维度（≤3 维）**：**禁止**从色板头部顺序硬取（data-0/1/2…）；优先取**同色系/邻近色**组合，保证视觉协调。
3. **复杂多维（>3 维，如饼图/堆叠多类目）**：**仅此场景**才允许按 `--color-data-0…20` 顺序遍历取色。
4. **语义强绑定（绝对优先，覆写以上）**：数据带明确业务倾向时——**涨跌/升降强制用 §2.1 的 `--status-success`(绿)/`--status-danger`(红)/中立灰**；其它中立面积可用 data-19/20。
5. **禁止**：用 `--color-foreground`/灰阶文字色/任意 hex/黑色或近黑色当系列色（见 §1 杜绝项）；用 theme.css 的 `--color-success/--color-danger` 当涨跌色。**注意**：品牌色（`--color-brand-*`）可以作为系列色（前提非黑），不在禁止范围内。

### 2.3 模板色一致性自检（避免"个别图表偏色")

> **背景**：实战中常见 BulletChart / GaugeChart 等组件在源码里**硬写**了 `data-1`/`data-5` 等非默认槽，导致同一个看板里大部分图是青绿+浅蓝，唯独这两个组件变成蓝紫+紫红，**视觉上像两个不同的设计系统**。

**自检清单（生成代码前/审查时跑一遍）**：

| 位置 | 应是 | 不应是 |
|---|---|---|
| `Smart*Chart` 默认 fallback（如 `colorToken \|\| 'data-0'`） | `data-0` / `data-4` | `data-1` / `data-2` / `data-5` |
| Preview / Section 不传 `colorToken` 时 | 走 `getDefaultDataColorToken(idx)` | 自己写 `'data-1'` 等具体槽 |
| 单维图表无显式语义 | `data-0` | `data-1`、品牌蓝、自创 hex |
| GaugeChart 默认 tone（无 tone 参数） | `data-0`（青绿） | `data-1`（蓝紫） |
| BulletChart `mainColorToken` 默认 | `data-0` + `targetColorToken: data-4` | `data-1` + `data-5` |
| tokens.js 文档值 | 与默认色板首位一致 | 写成 `--color-data-1` 等老色 |

**色彩策略最佳实践（基于现有"禁止调色盘"规则的补强建议）**：

1. **"5/3/1"分配法**（替代死板的 80/20）：每个 dashboard 页面建议至多出现 **5 个不同色相**（含中性灰），其中 **3 个是数据色**（首色 data-0、辅色 data-4、强调色按业务选），**1 个是强语义升降色**（绿/红二选一为主调）。这能保证页面"有节奏但不花哨"。
2. **首色保留原则**：data-0 在整页应该是"出现频次最高的色"——KPI 趋势图、主图表序列、进度类组件全部默认它。出现一张"用 data-0 之外的非语义色"的单维图，必须有书面理由（如对比基准线、对照组）。
3. **同色系递进 vs 邻近色递进**（多维 ≤3 维场景的二选一）：
   - **同色系递进**（推荐用于"有顺序的层级"）：data-0 → data-9 → data-12（青绿→翠绿→粉紫），适合时间序列、漏斗。
   - **邻近色递进**（推荐用于"并列对照"）：data-0 → data-4 → data-2（青绿→浅蓝→金黄），适合多类目并列对比。
4. **目标线/参考线只用一种语义色**：BulletChart 的 target、KPI 的目标基准、阈值线，整页统一用 **data-4 浅蓝**（提示语义）或 `--status-danger`（告警语义），不要混用。
5. **避免"双蓝撞色"**：data-1（蓝紫 #3D71FF）和 data-4（浅蓝 #3CCBFF）色相相近，**同图同时出现会糊在一起**——选其一即可。模板默认避开 data-1，原因之一就是它与 data-4 不够区分。

**违反时的修复路径**：
- 改组件源默认值（如 [`SmartGaugeChart.jsx`](file:///Users/bytedance/Desktop/TFDS/src/components/charts/SmartGaugeChart.jsx) `progressColorToken: 'data-0'`、[`SmartBulletChart.jsx`](file:///Users/bytedance/Desktop/TFDS/src/components/charts/SmartBulletChart.jsx) `mainColorToken: 'data-0'`）
- 改 Preview 默认（如 [`GaugeChartPreview.jsx`](file:///Users/bytedance/Desktop/TFDS/src/data/systems/dashboard/components/GaugeChartPreview.jsx) `return 'data-0'`、[`BulletChartPreview.jsx`](file:///Users/bytedance/Desktop/TFDS/src/data/systems/dashboard/components/BulletChartPreview.jsx) `mainColorToken: 'data-0'`）
- 同步改 `*.tokens.js` 文档展示值（避免文档与实现脱节）

## 3. 文本与对比度

- 轴与网格属于底噪：使用 secondary / divider token
- KPI 主数值必须高对比，次级信息降级（muted）

---

## 4. 降级与兜底模板（当缺组件时怎么“安全输出”）

### 4.1 允许自绘的最小集合（只做“壳”，不造“轮子”）

- **容器**：卡片容器、分区容器、左右/上下布局容器（必须 token 化间距/圆角/背景）
- **标题与说明**：模块标题（semibold 600）、口径说明（secondary）
- **分隔与底噪**：divider、浅背景层级（禁止大阴影与渐变装饰）

### 4.2 禁止自绘的高风险集合（优先找现有组件）

- 图表（尤其是 tooltip/legend/cursor/axis 的一致性）  
- 指标卡（趋势、口径 tooltip、数字字体栈）  
- 复杂交互表格（固定列、滚动、表头语义）  

> 这些必须优先用 `@tfdesign/dashboard` 现有组件（含其内置基础组件）；否则高概率引入“抖动/漂移/不可维护”。

### 4.3 兜底输出结构（当你只能做最小实现时）

1. 仍然先给出 `pattern + recipe + scrollOwner`
2. 组件缺失的模块，用“卡片 + 标题 + 说明 + 占位内容”输出，但保持稳定高度与间距
3. 标注后续可替换为哪个 `components.index.json` 的组件 id（如果存在近似项）

### 4.4 嵌入与自适应兜底（避免 frame 过宽 / 图表截断）

- **嵌入 B 端整页组件**：在 dashboard 中嵌入 B 端整页组件（如 `StrategyListPage`）必须传 `embedded`，去掉页面级外边距、`width:100%` 撑满父容器红线（详见 `LAYOUT_RULES.md` §6、`COMMON_FAILURES.md` §10）。注意改的是 `@tfdesign/b-end` 包真值，不是 `src/data/systems/b-end/...`。
- **图表自适应兜底**：图表高度优先由容器决定（等高分组 / `flex-1` / `fillContainer`），内部用 viewBox/aspect-ratio 等比缩放填满；空间不足时按 `LAYOUT_RULES.md` §3.2 降级（隐藏坐标文字 → 等比缩小 → 端点预留安全边），不得溢出卡片内边距被截断，也不得塞死固定像素高度。

### 4.5 极端兜底：手绘原生图表的几何硬规则（仅当确无 Smart*Chart 可用时）

> 前提：优先级永远是 Smart*Chart > 最小自绘。只有索引里确实没有任何近似图表组件，才允许手绘，且仍受 §1/§2 token 与色彩约束。

- **直线折点、禁止平滑**：相邻坐标点之间用**直线段**点对点连接，产生尖锐折角；严禁贝塞尔/平滑曲线/在折点加圆角。
- **线宽统一**：线宽读取全局规范，同一看板内所有折线线宽**绝对一致**，禁止逐条动态调整。
- **Y 轴高对比映射**：计算 Y 轴位置要充分利用可用高度，让数值差异转化为**明显的上下起伏**；禁止过度压缩比例导致折线扁平化。
- **颜色仍走 token**：线/柱/点颜色只能用 `--color-data-*` 与语义色（见 §2），禁止黑色/灰文字色/任意 hex。

