@tfdesign/b-end 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI_READ_FIRST.md +131 -0
- package/LICENSE +21 -0
- package/README.md +353 -0
- package/package.json +67 -0
- package/scripts/check-tfds-contract.mjs +334 -0
- package/scripts/check-tfds-integration.mjs +263 -0
- package/scripts/postinstall-cursor-skill.mjs +382 -0
- package/scripts/setup.mjs +520 -0
- package/skills/tfds/CHECKLIST.md +205 -0
- package/skills/tfds/COMMON_FAILURES.md +238 -0
- package/skills/tfds/DESIGN_PRINCIPLES.md +477 -0
- package/skills/tfds/GLOBAL_DESIGN_RULES.md +636 -0
- package/skills/tfds/LAYOUT_RECIPES.md +140 -0
- package/skills/tfds/LAYOUT_RULES.md +1355 -0
- package/skills/tfds/PAGE_ARCHETYPES.md +201 -0
- package/skills/tfds/SKILL.md +188 -0
- package/skills/tfds/components.index.json +7305 -0
- package/skills/tfds/components.summary.json +1809 -0
- package/src/_b_end_runtime/components/AiSuggestionShared.jsx +166 -0
- package/src/_b_end_runtime/components/Avatar.jsx +325 -0
- package/src/_b_end_runtime/components/Avatar.tokens.js +76 -0
- package/src/_b_end_runtime/components/AvatarGridPreview.jsx +56 -0
- package/src/_b_end_runtime/components/AvatarGroup.jsx +80 -0
- package/src/_b_end_runtime/components/AvatarGroup.tokens.js +28 -0
- package/src/_b_end_runtime/components/Button.jsx +144 -0
- package/src/_b_end_runtime/components/Button.tokens.js +90 -0
- package/src/_b_end_runtime/components/Card.jsx +460 -0
- package/src/_b_end_runtime/components/Card.tokens.js +124 -0
- package/src/_b_end_runtime/components/CardPreview.jsx +51 -0
- package/src/_b_end_runtime/components/ChatBubble.jsx +384 -0
- package/src/_b_end_runtime/components/ChatBubble.tokens.js +60 -0
- package/src/_b_end_runtime/components/ChatBubblePreview.jsx +129 -0
- package/src/_b_end_runtime/components/ChatInput.jsx +1399 -0
- package/src/_b_end_runtime/components/ChatInput.tokens.js +75 -0
- package/src/_b_end_runtime/components/ChatMessage.jsx +2215 -0
- package/src/_b_end_runtime/components/ChatMessage.tokens.js +257 -0
- package/src/_b_end_runtime/components/ChatMessagePreview.jsx +388 -0
- package/src/_b_end_runtime/components/Checkbox.jsx +317 -0
- package/src/_b_end_runtime/components/Checkbox.tokens.js +59 -0
- package/src/_b_end_runtime/components/ConversationList.jsx +1264 -0
- package/src/_b_end_runtime/components/ConversationList.tokens.js +135 -0
- package/src/_b_end_runtime/components/ConversationListPreview.jsx +108 -0
- package/src/_b_end_runtime/components/CustomerServiceWorkspaceFrame.jsx +324 -0
- package/src/_b_end_runtime/components/CustomerServiceWorkspaceFrame.tokens.js +69 -0
- package/src/_b_end_runtime/components/DatePicker.jsx +739 -0
- package/src/_b_end_runtime/components/DatePicker.tokens.js +99 -0
- package/src/_b_end_runtime/components/Empty.jsx +141 -0
- package/src/_b_end_runtime/components/Empty.tokens.js +40 -0
- package/src/_b_end_runtime/components/Form.jsx +609 -0
- package/src/_b_end_runtime/components/Form.tokens.js +77 -0
- package/src/_b_end_runtime/components/FormFieldStack.jsx +123 -0
- package/src/_b_end_runtime/components/FormFieldStack.tokens.js +12 -0
- package/src/_b_end_runtime/components/FormTitle.jsx +119 -0
- package/src/_b_end_runtime/components/FormTitle.tokens.js +87 -0
- package/src/_b_end_runtime/components/FullScreenPage.jsx +97 -0
- package/src/_b_end_runtime/components/FullScreenPage.tokens.js +19 -0
- package/src/_b_end_runtime/components/Icon.jsx +172 -0
- package/src/_b_end_runtime/components/Icon.tokens.js +26 -0
- package/src/_b_end_runtime/components/IconGridPreview.jsx +277 -0
- package/src/_b_end_runtime/components/InfoDisplayPanel.jsx +620 -0
- package/src/_b_end_runtime/components/InfoDisplayPanel.tokens.js +71 -0
- package/src/_b_end_runtime/components/InfoDisplayPanelPreview.jsx +133 -0
- package/src/_b_end_runtime/components/Input.jsx +258 -0
- package/src/_b_end_runtime/components/Input.tokens.js +68 -0
- package/src/_b_end_runtime/components/InputNumber.jsx +242 -0
- package/src/_b_end_runtime/components/InputNumber.tokens.js +55 -0
- package/src/_b_end_runtime/components/Modal.jsx +155 -0
- package/src/_b_end_runtime/components/Modal.tokens.js +73 -0
- package/src/_b_end_runtime/components/NavBar.jsx +842 -0
- package/src/_b_end_runtime/components/NavBar.tokens.js +97 -0
- package/src/_b_end_runtime/components/NavBarPreview.jsx +11 -0
- package/src/_b_end_runtime/components/Radio.jsx +227 -0
- package/src/_b_end_runtime/components/Radio.tokens.js +59 -0
- package/src/_b_end_runtime/components/Select.jsx +766 -0
- package/src/_b_end_runtime/components/Select.tokens.js +99 -0
- package/src/_b_end_runtime/components/Sheet.jsx +132 -0
- package/src/_b_end_runtime/components/Sheet.tokens.js +61 -0
- package/src/_b_end_runtime/components/Slider.jsx +346 -0
- package/src/_b_end_runtime/components/Slider.tokens.js +47 -0
- package/src/_b_end_runtime/components/Switch.jsx +124 -0
- package/src/_b_end_runtime/components/Switch.tokens.js +38 -0
- package/src/_b_end_runtime/components/Table.jsx +1338 -0
- package/src/_b_end_runtime/components/Table.tokens.js +147 -0
- package/src/_b_end_runtime/components/TablePreview.jsx +599 -0
- package/src/_b_end_runtime/components/Tabs.jsx +149 -0
- package/src/_b_end_runtime/components/Tabs.tokens.js +102 -0
- package/src/_b_end_runtime/components/Tag.jsx +199 -0
- package/src/_b_end_runtime/components/Tag.tokens.js +171 -0
- package/src/_b_end_runtime/components/TagBar.jsx +1134 -0
- package/src/_b_end_runtime/components/TagBar.tokens.js +75 -0
- package/src/_b_end_runtime/components/TagGridPreview.jsx +23 -0
- package/src/_b_end_runtime/components/TagInput.jsx +382 -0
- package/src/_b_end_runtime/components/TagInput.tokens.js +52 -0
- package/src/_b_end_runtime/components/TextArea.jsx +363 -0
- package/src/_b_end_runtime/components/TextArea.tokens.js +65 -0
- package/src/_b_end_runtime/components/TimePicker.jsx +444 -0
- package/src/_b_end_runtime/components/TimePicker.tokens.js +77 -0
- package/src/_b_end_runtime/components/Toast.jsx +120 -0
- package/src/_b_end_runtime/components/Toast.tokens.js +146 -0
- package/src/_b_end_runtime/components/Tooltip.jsx +282 -0
- package/src/_b_end_runtime/components/Tooltip.tokens.js +48 -0
- package/src/_b_end_runtime/components/TooltipPreview.jsx +50 -0
- package/src/_b_end_runtime/components/Upload.jsx +455 -0
- package/src/_b_end_runtime/components/Upload.tokens.js +47 -0
- package/src/_b_end_runtime/components/avatar-assets/avatar-default.png +0 -0
- package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-1.png +0 -0
- package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-2.png +0 -0
- package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-3.png +0 -0
- package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-4.png +0 -0
- package/src/_b_end_runtime/components/avatar-group-assets/avatar-group-5.png +0 -0
- package/src/_b_end_runtime/components/empty-assets/administrator-1.svg +40 -0
- package/src/_b_end_runtime/components/empty-assets/administrator-2.svg +33 -0
- package/src/_b_end_runtime/components/empty-assets/construction.svg +33 -0
- package/src/_b_end_runtime/components/empty-assets/failure.svg +49 -0
- package/src/_b_end_runtime/components/empty-assets/idle.svg +34 -0
- package/src/_b_end_runtime/components/empty-assets/no-access.svg +36 -0
- package/src/_b_end_runtime/components/empty-assets/no-content.svg +77 -0
- package/src/_b_end_runtime/components/empty-assets/no-result.svg +61 -0
- package/src/_b_end_runtime/components/empty-assets/not-found.svg +46 -0
- package/src/_b_end_runtime/components/empty-assets/success.svg +38 -0
- package/src/_b_end_runtime/components/file-type-assets/batch-report.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/catcat.svg +21 -0
- package/src/_b_end_runtime/components/file-type-assets/code.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/conversation.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/document.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/feishu-card.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/feishu-sheet.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/feishu.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/image.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/index.js +105 -0
- package/src/_b_end_runtime/components/file-type-assets/knowledge.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/pdf.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/pe.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/strategy.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/table.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/webpage.png +0 -0
- package/src/_b_end_runtime/components/file-type-assets/xmind.png +0 -0
- package/src/_b_end_runtime/components/icons/icon-data.js +12496 -0
- package/src/_b_end_runtime/components/nav-bar-assets/bytehi-logo-mark.svg +21 -0
- package/src/_b_end_runtime/components/table-assets/avatar.png +0 -0
- package/src/_b_end_runtime/components/table-assets/button.png +0 -0
- package/src/_b_end_runtime/components/table-assets/icon-chevron-down.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/avatar.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/button.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/checkbox.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/icon-chevron-right.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/icon.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/semi-icons-handle.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/semi-icons-tree-triangle-right.png +0 -0
- package/src/_b_end_runtime/components/table-cell-assets/switch.png +0 -0
- package/src/_b_end_runtime/components/tagShared.js +3 -0
- package/src/_b_end_runtime/components/team-avatar-assets/chengcheng-murphy.png +0 -0
- package/src/_b_end_runtime/components/team-avatar-assets/duan-ran.png +0 -0
- package/src/_b_end_runtime/components/team-avatar-assets/guo-zhezhi.png +0 -0
- package/src/_b_end_runtime/components/team-avatar-assets/li-siru.png +0 -0
- package/src/_b_end_runtime/components/team-avatar-assets/liu-delin.png +0 -0
- package/src/_b_end_runtime/components.js +3499 -0
- package/src/_b_end_runtime/index.js +9 -0
- package/src/_b_end_runtime/page-patterns/BasePageFramePattern.jsx +395 -0
- package/src/_b_end_runtime/page-patterns/ChatConversationPattern.jsx +989 -0
- package/src/_b_end_runtime/page-patterns/ChatHomePagePattern.jsx +281 -0
- package/src/_b_end_runtime/page-patterns/CopilotPagePattern.jsx +380 -0
- package/src/_b_end_runtime/page-patterns/CustomerServiceWorkspaceFramePattern.jsx +392 -0
- package/src/_b_end_runtime/page-patterns/IMConversationPattern.jsx +590 -0
- package/src/_b_end_runtime/page-patterns/McpManagementPage.jsx +237 -0
- package/src/_b_end_runtime/page-patterns/StrategyListPage.jsx +189 -0
- package/src/_b_end_runtime/page-patterns/TabTopBarListPage.jsx +594 -0
- package/src/_b_end_runtime/page-patterns/VariableManagementPage.jsx +87 -0
- package/src/_b_end_runtime/page-patterns/pageListShared.jsx +177 -0
- package/src/_b_end_runtime/patterns.js +428 -0
- package/src/_b_end_runtime/preview-registry.jsx +4719 -0
- package/src/_b_end_runtime/teamMembers.js +56 -0
- package/src/_b_end_runtime/tokens.js +500 -0
- package/src/index.d.ts +1073 -0
- package/src/index.js +52 -0
- package/theme.css +350 -0
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
# TFDS 全局设计规范(组件库未覆盖场景的兜底约束)
|
|
2
|
+
|
|
3
|
+
> **作用域**:当 `components.index.json` 没有覆盖你要生成的内容时(例如自定义信息卡、状态条、KPI 块、装饰性区块、统计模块、面包屑、徽章组合),**必须**严格遵守本文件给出的 token 与组合规则。**禁止**自由发挥颜色 / 间距 / 字号 / 圆角 / 阴影 / 动效。
|
|
4
|
+
>
|
|
5
|
+
> **优先级**(与 SKILL.md 一致):组件索引 > SKILL.md > LAYOUT_RULES.md > 本文件 > DESIGN_PRINCIPLES.md > 模型自身审美。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 颜色 Token
|
|
10
|
+
|
|
11
|
+
### 1.1 中性色(结构色 = blueGrey 系,11 档)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
| 用途 | CSS 变量 | 实色 | 适用场景 |
|
|
15
|
+
| ---- | --------------------------------------------- | --------------------- | ------------------ |
|
|
16
|
+
| 主文字 | `var(--color-foreground)` | `#182230` | 标题、正文主信息 |
|
|
17
|
+
| 次文字 | `var(--color-foreground-secondary)` | `#475467` | 描述、辅助说明 |
|
|
18
|
+
| 弱文字 | `var(--color-foreground-muted)` | `#667085` | 时间戳、计数、placeholder |
|
|
19
|
+
| 禁用文字 | `var(--color-foreground-disabled)` | `#98A2B3` | 禁用态文字 |
|
|
20
|
+
| 反色文字 | `var(--color-foreground-inverse)` | `#FFFFFF` | 深底/品牌底上的文字 |
|
|
21
|
+
| 页面底色 | `var(--color-blueGrey-200)` | `#F2F4F7` | 整页最外层灰底 |
|
|
22
|
+
| 弱底色 | `var(--color-blueGrey-100)` | `#F9FAFB` | hover 背景、禁用背景、二级容器 |
|
|
23
|
+
| 卡片白底 | `var(--color-surface)` / `var(--color-white)` | `#FFFFFF` | 业务白卡 |
|
|
24
|
+
| 默认描边 | `var(--color-border-default)` | `#E4E7EC` | 输入框、卡片描边 |
|
|
25
|
+
| 强描边 | `var(--color-border-strong)` | `#D0D5DD` | hover/focus 描边 |
|
|
26
|
+
| 细线 | `var(--color-border-line-light)` | `rgba(22,24,35,0.08)` | 列表分隔线、表格行线 |
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
⛔ **禁止**:
|
|
30
|
+
|
|
31
|
+
- ❌ 写死十六进制:`#000`、`#333`、`#ccc`、`#fff`
|
|
32
|
+
- ❌ Tailwind 任意值:`text-[#000]`、`bg-[#fafafa]`、`border-[#e0e0e0]`
|
|
33
|
+
- ❌ Tailwind 默认 gray:`border-black`、`text-black`、`bg-gray-`*、`text-gray-`*(gray ≠ blueGrey,色相偏冷蓝)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
| ❌ Bad | ✅ Good |
|
|
37
|
+
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
38
|
+
| `<div className="text-black border-gray-300">` | `<div style={{ color: 'var(--color-foreground)', borderColor: 'var(--color-border-default)' }}>` |
|
|
39
|
+
| `<p className="text-[#666]">` | `<p style={{ color: 'var(--color-foreground-secondary)' }}>` |
|
|
40
|
+
| `<span className="bg-gray-100">` | `<span style={{ background: 'var(--color-blueGrey-100)' }}>` |
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### 1.2 品牌色(brand 系,主操作 / 主链接)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
| 角色 | 变量 | 实色 |
|
|
47
|
+
| ------------------ | ------------------------------------------------- | --------- |
|
|
48
|
+
| 品牌主色 | `var(--color-primary)` / `var(--color-brand-500)` | `#56D3BC` |
|
|
49
|
+
| 品牌强调(hover/active) | `var(--color-brand-600)` | `#32C4AC` |
|
|
50
|
+
| 品牌深色(链接、文本品牌) | `var(--color-brand-700)` | `#18B49D` |
|
|
51
|
+
| 品牌浅底(tag/标签底) | `var(--color-brand-50)` | `#EAFAF6` |
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
**品牌色仅用于**:主行动按钮(Button primary)、链接(`<Button variant="text-brand" />`)、品牌 Tag、Avatar AI 渐变。
|
|
55
|
+
|
|
56
|
+
⛔ **禁止**:用品牌色当普通分割线、装饰性边框、整页背景、图标(除了 hiai logo)。
|
|
57
|
+
|
|
58
|
+
### 1.3 语义色(状态反馈,4 档)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
| 角色 | 变量 | 用途 |
|
|
62
|
+
| --- | ---------------------- | ---------- |
|
|
63
|
+
| 成功 | `var(--color-success)` | 上线、通过、成功提示 |
|
|
64
|
+
| 警告 | `var(--color-warning)` | 风险、待办 |
|
|
65
|
+
| 危险 | `var(--color-danger)` | 删除、错误、阻塞 |
|
|
66
|
+
| 信息 | `var(--color-info)` | 中性信息 |
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
⛔ **禁止**:
|
|
70
|
+
|
|
71
|
+
- 用语义色当背景大面积铺设(除非 Toast/Alert,已有组件)
|
|
72
|
+
- 状态徽标手写:`<span className="bg-red-100 text-red-600">失败</span>` ❌ → 必须 `<Tag variant="danger">失败</Tag>` ✅
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 2. 字体 Token
|
|
77
|
+
|
|
78
|
+
### 2.1 字号(共 9 档,全部列出)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
| Token | 实际值 | Tailwind 等价 | 用途 |
|
|
82
|
+
| ------------- | --------------- | ----------- | ------------------------------ |
|
|
83
|
+
| `--text-xs` | 12px / 0.75rem | `text-xs` | 时间戳、计数、辅助说明、Tag size=s |
|
|
84
|
+
| `--text-sm` | 14px / 0.875rem | `text-sm` | **正文默认**、表单 label、按钮文案 |
|
|
85
|
+
| `--text-base` | 16px / 1rem | `text-base` | 强调正文、`FormTitle level-1`、卡片摘要 |
|
|
86
|
+
| `--text-lg` | 18px / 1.125rem | `text-lg` | 少量强调信息,非 `FormTitle` 主路径 |
|
|
87
|
+
| `--text-xl` | 20px / 1.25rem | `text-xl` | `FormTitle form`(页面总标题 / 工作台名) |
|
|
88
|
+
| `--text-2xl` | 24px / 1.5rem | `text-2xl` | 页面 hero 标题、KPI 大数 |
|
|
89
|
+
| `--text-3xl` | 30px / 1.875rem | `text-3xl` | 营销/空状态主标题 |
|
|
90
|
+
| `--text-4xl` | 36px / 2.25rem | `text-4xl` | 数据可视化大数(极少用) |
|
|
91
|
+
| `--text-5xl` | 48px / 3rem | `text-5xl` | 营销首屏 hero(B 端基本不用) |
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
⛔ **禁止**:
|
|
95
|
+
|
|
96
|
+
- ❌ 任意 px:`text-[15px]`、`text-[17px]`、`text-[22px]`
|
|
97
|
+
- ❌ 直接使用 `<h1>/<h2>/<h3>` 浏览器默认样式(会注入 `font-weight: bold` + 不可控 size)
|
|
98
|
+
- ✅ 优先:`<FormTitle />`;只有非组件化排版示意时,才显式写 `<h2 className="text-base leading-6 [font-weight:var(--font-semibold)]">`(⛔ 不要写裸 `font-semibold` / `font-bold` 类承载规范字重,见 §2.2)
|
|
99
|
+
|
|
100
|
+
### 2.2 字重(共 4 档)与显式 `font-weight`(Tailwind v4)
|
|
101
|
+
|
|
102
|
+
B 端主路径的**标题与密集区强调文案**默认以 **600(`--font-semibold`)** 为同一视觉层级;`700(--font-bold)` **仅**在个别组件 props / rules 已约定时使用(如部分 `Tag` `fontWeight="bold"`)。**与 `FormTitle` / `Form` / `ConversationList` / `Button` 等实现不一致的硬编码字重一律视为错误。**
|
|
103
|
+
|
|
104
|
+
在 **Tailwind v4** 下,`font-semibold` / `font-bold` 等语义类可能把 `--font-`* 命名空间与 **font-family** 语义搅在一起,导致字重表现不稳定。TFDS 约定:凡是必须符合设计规格的字重,在 className 中优先写 **任意属性显式绑定**:
|
|
105
|
+
|
|
106
|
+
- **600**:`[font-weight:var(--font-semibold)]`(必要时强制:`![font-weight:var(--font-semibold)]`)
|
|
107
|
+
- **700**:`[font-weight:var(--font-bold)]`
|
|
108
|
+
|
|
109
|
+
**分档速查(与当前 `@tf-designsystem/b-end` 实现一致)**
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
| 语义档 | Token | 数值 | 典型落点 |
|
|
113
|
+
| ------------- | ----------------- | --- | ---------------------------------------------------------------------------------------------- |
|
|
114
|
+
| 正文 / 描述 | `--font-normal` | 400 | `font-normal` 或组件内定 |
|
|
115
|
+
| 次级强调 | `--font-medium` | 500 | 表格数据主列、部分 Tag、说明性标签 |
|
|
116
|
+
| **默认「标题级」强调** | `--font-semibold` | 600 | `**FormTitle` 全变体**、`Form` 字段标题 / 必填星号 /「可选」、`ConversationList` 会话项标题、`Button` 全变体、`Tabs` 选中态等 |
|
|
117
|
+
| 更强一档(组件约定) | `--font-bold` | 700 | **仅**命中组件 rules / props 时(勿用来手搓替代 `FormTitle`) |
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
| Token(设计语义) | 值 | 运行时推荐 class 片段 |
|
|
122
|
+
| ----------------- | --- | ------------------------------------ |
|
|
123
|
+
| `--font-normal` | 400 | `font-normal`(正文) |
|
|
124
|
+
| `--font-medium` | 500 | `font-medium` |
|
|
125
|
+
| `--font-semibold` | 600 | `[font-weight:var(--font-semibold)]` |
|
|
126
|
+
| `--font-bold` | 700 | `[font-weight:var(--font-bold)]` |
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
⛔ **禁止**
|
|
130
|
+
|
|
131
|
+
- 在已有 `FormTitle` / `Form` / `ConversationList` 的场景,用 `<h1|h2|span className="font-bold|font-semibold">` 冒充组件字重
|
|
132
|
+
- 给 `FormTitle` 传 `className` / `style` 覆写 `font-`*(见 `components.index.json` 铁律)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
| ❌ Bad | ✅ Good |
|
|
136
|
+
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
137
|
+
| `<h2 className="font-bold text-lg">总览</h2>` | `<FormTitle variant="form" title="总览" />` |
|
|
138
|
+
| `<div className="font-bold">用户名</div>` | `<div className="font-medium">用户名</div>` |
|
|
139
|
+
| `<span className="font-semibold">小标题</span>`(在须走 TFDS 字重的业务区) | `<FormTitle variant="level-2" title="小标题" />` 或组件已规定的 `[font-weight:var(--font-semibold)]` |
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
### 2.3 行高 Token(强约束)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
| Token | 值 | 适用 |
|
|
146
|
+
| --------------------------- | ----- | ------------------------------ |
|
|
147
|
+
| `--leading-4` | 16px | 紧凑:12px 字号配 16px 行高(Tag、Badge) |
|
|
148
|
+
| `--leading-5` | 20px | 紧凑正文:14px 字号配 20px 行高 |
|
|
149
|
+
| `leading-tight`(Tailwind) | 1.25 | 标题(18-24px 字号) |
|
|
150
|
+
| `leading-normal`(Tailwind) | 1.5 | 正文段落(默认) |
|
|
151
|
+
| `leading-relaxed`(Tailwind) | 1.625 | 描述性长文本 |
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
⛔ **禁止**:
|
|
155
|
+
|
|
156
|
+
- ❌ `leading-[1.4]`、`leading-[28px]` 等任意值
|
|
157
|
+
- ❌ 段落不写行高(浏览器默认 1.2 太挤)
|
|
158
|
+
|
|
159
|
+
**行高黄金组合**:
|
|
160
|
+
|
|
161
|
+
- 12px 字号 → `leading-4`(16px)
|
|
162
|
+
- 14px 字号 → `leading-5`(20px)或 `leading-normal`
|
|
163
|
+
- 16-18px 字号 → `leading-6`(24px)或 `leading-normal`
|
|
164
|
+
- 20-24px 字号 → `leading-tight` 或 `leading-7`/`leading-8`
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 3. 间距 Token(共 13 档)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
| Token | 值 | Tailwind | 推荐用途 |
|
|
172
|
+
| --------------- | ---- | --------------- | ------------------------------ |
|
|
173
|
+
| `--spacing-0` | 0px | `gap-0` | 无间距 |
|
|
174
|
+
| `--spacing-0_5` | 2px | `gap-0.5` | 极紧凑(图标内部、徽标) |
|
|
175
|
+
| `--spacing-1` | 4px | `gap-1` | 单行 Tag 之间、icon-text 间距 |
|
|
176
|
+
| `--spacing-2` | 8px | `gap-2` | **同组元素默认值**、白卡之间 |
|
|
177
|
+
| `--spacing-3` | 12px | `gap-3` | 跨小组件间(按钮组合) |
|
|
178
|
+
| `--spacing-4` | 16px | `gap-4` | **表单字段之间**、卡内行块 |
|
|
179
|
+
| `--spacing-5` | 20px | `gap-5` | 中等分区 |
|
|
180
|
+
| `--spacing-6` | 24px | `gap-6` / `p-6` | **白卡内 padding 默认值**、Section 之间 |
|
|
181
|
+
| `--spacing-7` | 28px | `gap-7` | 较大分区(少用) |
|
|
182
|
+
| `--spacing-8` | 32px | `gap-8` | 大区块间隔 |
|
|
183
|
+
| `--spacing-10` | 40px | `gap-10` | 页头底部留白 |
|
|
184
|
+
| `--spacing-12` | 48px | `gap-12` | hero 区高度 |
|
|
185
|
+
| `--spacing-16` | 64px | `gap-16` | 大型空状态留白 |
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
⛔ **禁止任意值**:`p-[14px]`、`gap-[7px]`、`space-y-[18px]`、`mt-[10px]`。
|
|
189
|
+
✅ **取整数档**:设计稿 14px → 向上取 16px (`gap-4`),11px → 取 12px (`gap-3`)。
|
|
190
|
+
|
|
191
|
+
**白卡分区间距黄金组合**(三层各自固定,不可混用):
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
| 位置 | 值 | Tailwind | 用法 |
|
|
195
|
+
| ----------------- | ----------- | ----------------- | --------------------------------- |
|
|
196
|
+
| 灰底框架(main)→ 白卡外边缘 | **16px** | `p-4` | `main` 容器的 padding,白卡距浏览器边缘 16px |
|
|
197
|
+
| 白卡 ↔ 白卡 之间 | **8px** | `gap-2` | `main` 容器的 `gap-2` |
|
|
198
|
+
| 白卡边缘 → 卡内内容 | **24px** | `p-6` | 写在白卡 div 内部的 padding |
|
|
199
|
+
| 白卡内分区之间 | 16px 或 24px | `gap-4` / `gap-6` | 白卡内 section 之间 |
|
|
200
|
+
| 表单字段之间 | 16px | `gap-4` | |
|
|
201
|
+
| 同组按钮之间 | 8px | `gap-2` | |
|
|
202
|
+
| 跨组件之间 | 12px | `gap-3` | |
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
⚠️ **最高频误用**:把白卡内部的 `p-6`(24px)误用到 `main` 外框 padding → 白卡距浏览器边缘变成 24px,左右出现大空白,看着像居中布局。`main` 的 padding 永远只能是 `p-4`(16px)。详见 LAYOUT_RULES §1.2。
|
|
206
|
+
|
|
207
|
+
⚠️ **AI 入口页例外**:`ChatHomePagePattern` 不套“主内容白卡”,右侧 Hero / `ChatInput` / Tabs / 搜索 / 模板卡网格直接坐 `--color-blueGrey-200` 灰底;只有模板卡片自身使用 `<Card color="white" />`。
|
|
208
|
+
|
|
209
|
+
### 3.0 组件对齐与微间距默认值
|
|
210
|
+
|
|
211
|
+
这些值用于组件库没有提供完整区块时的自定义组合;先判断页面 recipe,再套下面的微间距:
|
|
212
|
+
|
|
213
|
+
| 场景 | 默认间距 / 对齐 | 说明 |
|
|
214
|
+
| --- | --- | --- |
|
|
215
|
+
| PageMetaBar 左标题 + 右操作 | `items-start justify-between gap-3` | 标题 `min-w-0 flex-1`,右侧 `shrink-0 flex-wrap gap-2` |
|
|
216
|
+
| 白卡 Header | `px-6 py-4`,标题到正文 16px | 标题用 `FormTitle`,状态 Tag 放 `titleSuffix` |
|
|
217
|
+
| 筛选栏 | 同组 `gap-2`,跨组 `gap-3`,整行可 wrap | 搜索 240px,状态 / 枚举 160-200px,控件高度 36px |
|
|
218
|
+
| 表单字段 | `gap-4` | 单列主字段默认 `w-full`,不要套筛选栏固定宽 |
|
|
219
|
+
| 卡片网格 | `gap-4` | 模板 / 入口卡片直接坐灰底时用 `Card color="white"` |
|
|
220
|
+
| 白卡内轻分组 | `gap-3` 或 `gap-4` | 父级白底时内部卡片用 `Card color="grey"` 或轻量 InlinePanel |
|
|
221
|
+
|
|
222
|
+
⛔ 禁止为了“刚好对齐”新增 10px / 14px / 18px 这类任意值;设计稿落在中间值时取最近的 token 档。
|
|
223
|
+
|
|
224
|
+
### 3.1 卡片内长内容控件的高度节奏
|
|
225
|
+
|
|
226
|
+
白卡里如果有“标题 + 长内容控件”(TextArea / JSON / 代码块 / 日志 / 列表),视觉节奏必须是:
|
|
227
|
+
|
|
228
|
+
- 标题区:自然高度,`shrink-0`,永远稳定,不被滚走
|
|
229
|
+
- 内容区:占满剩余高度,`flex-1 min-h-0`
|
|
230
|
+
- 主控件:如果承担整张卡片的主要工作区,必须撑满内容区并在控件内部滚动
|
|
231
|
+
- 普通字段:仅按 `minRows` / 自然内容高度展示,不强行撑满
|
|
232
|
+
|
|
233
|
+
**TextArea 主编辑区**分两类:
|
|
234
|
+
|
|
235
|
+
- System Prompt / Agent 指令 / 模型高级参数 JSON / 请求参数 / 代码参数 / JSON / 代码 / SQL / Markdown / 规则配置:使用 `<TextArea variant="code" fillHeight resize="none" className="flex-1 min-h-0 w-full" />`,左侧行号用于逐行定位。
|
|
236
|
+
- 普通长文本 / 工单详情 / 描述编辑:使用 `<TextArea fillHeight resize="none" className="flex-1 min-h-0 w-full" />`。
|
|
237
|
+
- 纯数值模型参数(Temperature / Top-P / Max Tokens / 阈值 / 权重):使用 `<InputNumber />`,不要误用 TextArea。
|
|
238
|
+
|
|
239
|
+
普通备注字段仍使用 `minRows={3}`。不要把这两类高度策略混用,也不要手搓原生 textarea 或行号列。
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## 4. 圆角 Token(共 9 档)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
| Token | 值 | 用途 |
|
|
247
|
+
| ----------------- | ------ | ------------------ |
|
|
248
|
+
| `--radius-none` | 0px | 无圆角(直角/分割线) |
|
|
249
|
+
| `--radius-avatar` | 3px | 方形头像专用 |
|
|
250
|
+
| `--radius-sm` | 4px | 极小元素(mini Tag、徽标) |
|
|
251
|
+
| `--radius-md` | 8px | **输入框、按钮、小卡片** |
|
|
252
|
+
| `--radius-lg` | 12px | ⭐ **白卡默认圆角**、抽屉/弹窗 |
|
|
253
|
+
| `--radius-xl` | 16px | 大尺寸卡片 |
|
|
254
|
+
| `--radius-card` | 20px | 大型展示卡(少用) |
|
|
255
|
+
| `--radius-2xl` | 24px | 营销卡片 |
|
|
256
|
+
| `--radius-full` | 9999px | 头像、胶囊按钮、Tag pill |
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
⛔ **禁止**:`rounded-[10px]`、`rounded-[14px]`、`rounded-[18px]`。圆角只能取上表 9 档。
|
|
260
|
+
✅ **白卡默认**:`rounded-[12px]`,与 `var(--radius-lg)` 等价。
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 5. 阴影 Token(基础刻度 + 业务语义)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
| Token | 用途 |
|
|
268
|
+
| ------------------ | -------------------- |
|
|
269
|
+
| `--shadow-none` | 无阴影(**白卡默认**) |
|
|
270
|
+
| `--shadow-sm` | 浮起卡片(hover 微抬起) |
|
|
271
|
+
| `--shadow-DEFAULT` | 微浮(很少用) |
|
|
272
|
+
| `--shadow-md` | 中等浮层(dropdown) |
|
|
273
|
+
| `--shadow-lg` | 弹窗、悬浮面板 |
|
|
274
|
+
| `--shadow-xl` | 大型悬浮(picker、cascade) |
|
|
275
|
+
| `--shadow-2xl` | 极少使用 |
|
|
276
|
+
| `--shadow-card` | 业务语义投影:大型展示卡 |
|
|
277
|
+
| `--shadow-list` | 业务语义投影:链接参数 / 列表块轻投影 |
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
⛔ **白卡默认无阴影**:TFDS 风格是「灰底分区 + 白卡圆角」承担层级,不靠阴影。
|
|
281
|
+
⛔ **禁止**:`shadow-[0_4px_8px_rgba(0,0,0,0.1)]`、`drop-shadow-2xl`。
|
|
282
|
+
✅ **只有浮层**(dropdown / dialog / popover / picker)才能加阴影,且由组件自带。
|
|
283
|
+
✅ **业务语义投影**(如 `shadow-card`、`shadow-list`)只在设计系统已命名的明确场景中使用,不能把任意业务块都升级成新的 shadow primitive。
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
| ❌ Bad | ✅ Good |
|
|
287
|
+
| ------------------------------------------------------- | ---------------- |
|
|
288
|
+
| `<Card className="shadow-md">` | `<Card>`(去掉阴影) |
|
|
289
|
+
| `<div className="shadow-[0_2px_8px_rgba(0,0,0,0.06)]">` | `<div>`(白卡靠灰底分层) |
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 5.5 白卡描边规则(与"无阴影"同等地位的硬约束)
|
|
295
|
+
|
|
296
|
+
> 白卡的层级感**唯一靠"灰底 vs 白卡的明度差 + 12px 圆角"**承担——加 border 会让明度差被划线覆盖,视觉权重变硬,卡片显得拥挤像旧式 admin 后台。
|
|
297
|
+
|
|
298
|
+
### 5.5.1 铁律
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
最外层大白卡容器 → 纯白底 + 12px 圆角 + 无 border + 无 shadow
|
|
302
|
+
↓
|
|
303
|
+
内部一切控件 / 子卡的描边保持原样(Input / Select / Tag / Table 行线 / 内嵌灰卡 …)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**严格区分两类边界**:
|
|
307
|
+
|
|
308
|
+
- ⛔ **禁止**给"承载工作区内容的最外层大白卡"加任何 `border` / `outline`
|
|
309
|
+
- ✅ **保留**白卡**内部**所有 TFDS 组件自带的描边(Input、Select、TagInput、Tag、Tabs line variant、Table 行分隔线、内嵌 Card color="grey" 等)——这些描边是**控件功能边界**,不是卡片层级边界
|
|
310
|
+
|
|
311
|
+
### 5.5.2 Bad / Good 对照(图 1 同款误用)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
| ❌ Bad | 后果 | ✅ Good |
|
|
315
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------- |
|
|
316
|
+
| `<div style={{ background: 'var(--color-surface)', borderRadius: 'var(--radius-lg)', border: '1px solid var(--color-border-default)' }}>` | 白卡被灰线圈死,明度差被覆盖,气息感丢失 | 去掉 `border`:`<div style={{ background: 'var(--color-surface)', borderRadius: 'var(--radius-lg)' }}>` |
|
|
317
|
+
| `<Card className="border border-border-default">` | 白卡视觉权重变硬,与下面内嵌组件描边互相干扰 | `<Card>`(去掉 className 上的 border) |
|
|
318
|
+
| `style={{ ..., outline: '1px solid var(--color-border-default)' }}` | outline 在选中状态下会和 focus ring 打架 | 去掉 outline |
|
|
319
|
+
| `borderColor: 'var(--color-border-default)'` 写在白卡 div 上 | 同上 | 删除该属性 |
|
|
320
|
+
| `className="ring-1 ring-border-default"` | ring 是描边的另一种伪装 | 去掉 ring |
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
### 5.5.3 例外(极少数)
|
|
324
|
+
|
|
325
|
+
下面四种场景**允许**有描边,但不属于"最外层大白卡":
|
|
326
|
+
|
|
327
|
+
1. **白卡内嵌的灰卡**(`Card color="grey"`)→ 由组件自带浅描边表达"次级容器",保留
|
|
328
|
+
2. **TFDS 组件自带描边**:Input / Select / TextArea / TagInput / Tabs line / Table 行线 / Tooltip → 保留
|
|
329
|
+
3. **白卡内部的"分割线"**(`borderTop` / `borderBottom`)→ 用 `var(--color-border-line-light)` 划行,不是给整张卡加 border
|
|
330
|
+
4. **浮层 Dialog / Drawer 自带的轻描边** → 由组件自带,保留
|
|
331
|
+
|
|
332
|
+
⛔ 以上 4 种之外,**任何**直接给白卡 div 加 `border` / `outline` / `ring` 都视为违规。
|
|
333
|
+
|
|
334
|
+
### 5.5.4 与"灰底外框"的边界(防止 AI 误删)
|
|
335
|
+
|
|
336
|
+
⚠️ TFDS 部分 page-pattern 在**灰底页面外框**(不是白卡!)会有一圈 `border: 1px solid var(--color-border-default)`——这是页面预览容器在 TFDS 平台内的展示边界,**和白卡描边不是一回事**:
|
|
337
|
+
|
|
338
|
+
- 灰底页面外框 → **保留** border(这一层不是白卡,是整个页面壳)
|
|
339
|
+
- 白卡(surface 白底 + 12px 圆角,承载工作区内容)→ **绝不**加 border
|
|
340
|
+
|
|
341
|
+
判别口诀:背景色是 `--color-blueGrey-200`(灰)就允许有 border;背景色是 `--color-surface`(白)就**禁止**有 border。
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## 6. 过渡 / 动效规则
|
|
346
|
+
|
|
347
|
+
⛔ **禁止**:
|
|
348
|
+
|
|
349
|
+
- ❌ `transition-all`(性能差,会触发布局重计算)
|
|
350
|
+
- ❌ 任意 duration:`duration-[450ms]`、`duration-[700ms]`
|
|
351
|
+
- ❌ 任意 easing:`ease-[cubic-bezier(...)]`
|
|
352
|
+
|
|
353
|
+
✅ **必须**:
|
|
354
|
+
|
|
355
|
+
- 只过渡需要的属性:`transition-colors`、`transition-opacity`、`transition-transform`
|
|
356
|
+
- duration 只取 3 档:
|
|
357
|
+
|
|
358
|
+
| 时长 | Tailwind | 用途 |
|
|
359
|
+
| ----- | -------------- | ----------------------- |
|
|
360
|
+
| 150ms | `duration-150` | hover/focus 微变化(颜色/透明度) |
|
|
361
|
+
| 200ms | `duration-200` | 默认(按钮、Input 状态切换) |
|
|
362
|
+
| 300ms | `duration-300` | 抽屉/弹窗进入退出 |
|
|
363
|
+
|
|
364
|
+
- easing:默认 `ease-in-out`(Tailwind 默认),缓出场景用 `ease-out`
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
| ❌ Bad | ✅ Good |
|
|
368
|
+
| -------------------------------------------------------------------------- | ------------------------------------------------------ |
|
|
369
|
+
| `className="transition-all duration-300"` | `className="transition-colors duration-200"` |
|
|
370
|
+
| `className="transition duration-[450ms] ease-[cubic-bezier(0.4,0,0.2,1)]"` | `className="transition-opacity duration-300 ease-out"` |
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 7. 焦点可达性规则(键盘可达性必须)
|
|
376
|
+
|
|
377
|
+
⛔ **禁止**:
|
|
378
|
+
|
|
379
|
+
- ❌ 裸 `outline-none` 不补 `:focus-visible` → 键盘用户失明
|
|
380
|
+
- ❌ `focus:outline-none` 不加替代焦点样式
|
|
381
|
+
|
|
382
|
+
✅ **必须**:
|
|
383
|
+
|
|
384
|
+
- 使用 TFDS 组件(Button/Input/Select 等)—— 焦点环已封装
|
|
385
|
+
- 自定义可交互元素必须保留焦点:
|
|
386
|
+
```jsx
|
|
387
|
+
<button
|
|
388
|
+
className="
|
|
389
|
+
focus:outline-none
|
|
390
|
+
focus-visible:ring-2 focus-visible:ring-offset-2
|
|
391
|
+
"
|
|
392
|
+
style={{
|
|
393
|
+
'--tw-ring-color': 'var(--color-ring)',
|
|
394
|
+
}}
|
|
395
|
+
>
|
|
396
|
+
```
|
|
397
|
+
- 焦点环颜色统一用 `var(--color-ring)`(= `--color-brand-500`)
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## 8. 文本自适应:换行优先,省略必须配 Tooltip(B 端高频问题)
|
|
402
|
+
|
|
403
|
+
> **目标**:页面文字不能被卡片、父容器或 `overflow-hidden` 静默裁切。要么完整可读地换行展示,要么有意识地省略,并能通过 TFDS `<Tooltip />` 查看全文。
|
|
404
|
+
|
|
405
|
+
### 8.1 UX 决策树(先判内容价值,再选展示方式)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
| 内容类型 | 推荐策略 | 原因 |
|
|
409
|
+
| ---------------------------------------------------- | ----------------------------------------------------------------- | ------------------------ |
|
|
410
|
+
| **用户必须立即读懂的说明**:字段说明、运行状态说明、错误原因、空状态说明,以及明确开启的白卡标题描述 | **完整展示,允许换行**:`whitespace-normal break-words` | 这类内容影响理解和操作,不能藏在 hover 里 |
|
|
411
|
+
| **短标题 + 辅助描述**:`FormTitle level-2/level-3` 右侧描述 | **默认隐藏**;有板块介绍/场景说明诉求时开启并允许换行 | 保持标题稳定,避免普通卡片标题堆叠低价值副标题 |
|
|
412
|
+
| **表格单元格 / 文件名 / 对象名 / 资源名** | **单行省略 + Tooltip 全文**:`truncate` + `<Tooltip content={fullText}>` | 行高必须稳定,全文是补充阅读 |
|
|
413
|
+
| **卡片摘要 / 消息预览 / 列表描述** | **2-3 行省略 + Tooltip 或详情入口**:`line-clamp-2/3` | 保持列表扫描效率 |
|
|
414
|
+
| **ID / URL / 模型名 / code / JSON** | **优先换行或内部滚动**:`break-words whitespace-pre-wrap`;极紧凑处才省略 + Tooltip | 这些内容常包含长英文串,不能撑爆布局 |
|
|
415
|
+
| **Tag / Badge / Button 文案** | **不换行,保持短文案**;过长必须改文案,不靠 Tooltip 承担主信息 | 控件尺寸应稳定,长句不应塞进控件 |
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
### 8.2 禁止静默裁切
|
|
419
|
+
|
|
420
|
+
⛔ **禁止**让文字被父容器“硬切掉”:
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
| ❌ Bad | 问题 | ✅ Good |
|
|
424
|
+
| ----------------------------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------- |
|
|
425
|
+
| `<span className="overflow-hidden">{desc}</span>` | 没有换行也没有省略提示,用户读不到全文 | 核心说明:`whitespace-normal break-words` |
|
|
426
|
+
| `<div className="flex overflow-hidden"><span>{desc}</span></div>` | flex 子项无 `min-w-0`,文字被卡片裁掉 | `<div className="flex min-w-0"><span className="min-w-0 break-words">...</span></div>` |
|
|
427
|
+
| `<span className="truncate">{name}</span>` 但无 Tooltip | 省略后没有完整信息路径 | `<Tooltip content={name}><span className="truncate">...</span></Tooltip>` |
|
|
428
|
+
| `FormTitle` 外层被 `overflow-hidden whitespace-nowrap` 包住 | 标题描述被强行截断 | 外层允许 `min-w-0`,不要给标题区域加 `whitespace-nowrap` |
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
### 8.3 推荐写法
|
|
432
|
+
|
|
433
|
+
**核心说明完整展示(明确开启的白卡标题描述 / 字段说明)**:
|
|
434
|
+
|
|
435
|
+
```jsx
|
|
436
|
+
<div className="min-w-0 whitespace-normal break-words text-sm text-foreground-muted">
|
|
437
|
+
所有参数控件改为 TFDS 组件,并保留原始参数结构。
|
|
438
|
+
</div>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**非核心长文本省略 + Tooltip(表格单元格 / 文件名 / 对象名)**:
|
|
442
|
+
|
|
443
|
+
```jsx
|
|
444
|
+
<Tooltip content={modelName} placement="top">
|
|
445
|
+
<span className="block max-w-full truncate">{modelName}</span>
|
|
446
|
+
</Tooltip>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**多行摘要(卡片描述 / 消息预览)**:
|
|
450
|
+
|
|
451
|
+
```jsx
|
|
452
|
+
<Tooltip content={summary} placement="top">
|
|
453
|
+
<p className="line-clamp-2 min-w-0 break-words text-sm text-foreground-secondary">
|
|
454
|
+
{summary}
|
|
455
|
+
</p>
|
|
456
|
+
</Tooltip>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
⚠️ **关键陷阱**:`truncate` / `line-clamp-N` 必须父容器有**确定宽度**或 `min-w-0` 才能生效;换行文本也必须有 `min-w-0`,否则 flex 子项会把卡片撑爆或被裁切。
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
| ❌ Bad(无效) | ✅ Good |
|
|
463
|
+
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
464
|
+
| `<div className="flex"><span className="truncate">{longText}</span></div>` | `<div className="flex min-w-0"><Tooltip content={longText}><span className="block truncate">{longText}</span></Tooltip></div>` |
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
### 8.4 标题区文字适配(禁止竖排 / 逐字换行)
|
|
468
|
+
|
|
469
|
+
标题不是普通长文本。白卡标题、面板标题、section 标题是用户识别板块语义的锚点,必须横向可读。
|
|
470
|
+
|
|
471
|
+
**硬规则**:
|
|
472
|
+
|
|
473
|
+
- 标题主文本永远不使用 `break-all` / `writing-mode` / `text-orientation` / 过窄固定宽度。
|
|
474
|
+
- `FormTitle` 描述文案默认隐藏;只有有板块介绍、场景说明、风险/空状态解释,或明确要求展示副标题时,才写 `description` + `showDescription`。
|
|
475
|
+
- 标题区最小可读宽度不低于 `120px`;低于这个宽度时,保持默认无描述或缩短标题文案。
|
|
476
|
+
- 标题右侧的 **状态 / 数量 / 身份 Tag** 属于标题语义补充,必须通过 `FormTitle titleSuffix` 紧跟主标题展示,不能放到 header 最右侧操作区。
|
|
477
|
+
- 标题右侧的 Tabs、Button、筛选入口、更多菜单才属于“操作区”,可以换行、下移或收起,不能挤压标题。
|
|
478
|
+
- `FormTitle` 主标题保持横排;开启后的 description 可以换行,但不能把 title 挤成一字一行。
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
| ❌ Bad | 问题 | ✅ Good |
|
|
482
|
+
| ----------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------- |
|
|
483
|
+
| `<div className="w-4 break-all">原始信息只读</div>` | 一字一行,读起来像乱码 | `<FormTitle variant="level-2" title="原始信息" />` |
|
|
484
|
+
| `<header className="flex nowrap">标题 + 很多 Tabs</header>` | Tabs 把标题挤窄 | 标题区 `min-w-[120px] flex-1`,操作区 `shrink-0 flex-wrap` |
|
|
485
|
+
| `<FormTitle title="Conversation" /><Tag>0 条消息</Tag>` 且 Tag 被推到最右侧 | Tag 是标题状态,不是操作按钮 | `<FormTitle title="Conversation" titleSuffix={<Tag variant="grey" size="m">0 条消息</Tag>} />` |
|
|
486
|
+
| `writing-mode: vertical-rl` | B 端卡片标题不使用竖排 | 保持横向标题,必要时缩短标题或隐藏描述 |
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## 9. 全局图标规则
|
|
492
|
+
|
|
493
|
+
- ✅ **必须**用 `<Icon name="kebab-case" />`(来自 `@tf-designsystem/b-end`)
|
|
494
|
+
- ⛔ **禁止**直接 `import { ChevronDown } from 'lucide-react'` 替代 TFDS Icon(线宽不一致)
|
|
495
|
+
- **图标尺寸**:
|
|
496
|
+
|
|
497
|
+
| 控件高度 | Icon size | 实际像素 |
|
|
498
|
+
| ----------- | --------- | ---- |
|
|
499
|
+
| 28-32px | `xs` | 12px |
|
|
500
|
+
| 36px(默认 md) | `sm` | 16px |
|
|
501
|
+
| 48px | `md` | 20px |
|
|
502
|
+
| 大型展示 | `lg` | 24px |
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## 9.5 Tabs 尺寸默认规则(与 Button 相反,必须单独记)
|
|
508
|
+
|
|
509
|
+
Tabs 是“切换视图”的控件,不是动作按钮;它在内容区需要更轻、更紧凑的节奏。
|
|
510
|
+
|
|
511
|
+
- ✅ **内容区默认 SM**:所有 4 种 Tabs 变体(`line` / `button` / `pill` / `segment`)只要出现在白卡、面板、卡片、表单分段、筛选维度、Playground 内部,默认都用 `size="sm"`,也可以直接省略 `size`(组件默认即 SM)。
|
|
512
|
+
- ✅ **Header 例外**:只有整个平台顶部 header、页面级顶导、产品级一级导航里的 Tabs,才允许根据场景使用 `size="md"` 或 `size="lg"`。
|
|
513
|
+
- ⛔ **禁止**内容区默认 `size="md"` / `size="lg"`:这会让卡内切换器视觉权重过高,挤占内容空间。
|
|
514
|
+
- ⚠️ 注意:Button 的默认尺寸仍是 MD(36px);Tabs 的默认尺寸是 SM。二者规则相反,不要混用。
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## 10. 状态徽标 / Tag 全局规则
|
|
519
|
+
|
|
520
|
+
- ✅ **任何**状态、分类、计数都必须用 `<Tag />`
|
|
521
|
+
- ⛔ **禁止**手写 `<span className="px-2 py-0.5 rounded-full bg-green-100 text-green-700">在线</span>` 假徽标
|
|
522
|
+
- 默认 `size="m"`;表格行内极紧凑场景才用 `size="s"`
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## 11. 链接(文本品牌色)规则
|
|
527
|
+
|
|
528
|
+
- ⛔ **禁止**裸 `<a className="text-blue-600 hover:underline" />`
|
|
529
|
+
- ✅ **必须**用 `<Button variant="text-brand" size="md">查看模型列表 →</Button>`
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## 12. 空状态 / 错误页 / 加载中规则
|
|
534
|
+
|
|
535
|
+
- ✅ **必须**优先使用 `EmptyState` / `NoAccessPage` / `ConstructionPage` / `Skeleton`
|
|
536
|
+
- 没有匹配 pattern 时,按以下骨架手写:
|
|
537
|
+
|
|
538
|
+
```jsx
|
|
539
|
+
<div className="flex flex-col items-center justify-center py-16 gap-4">
|
|
540
|
+
<Icon name="empty-box" size="lg" />
|
|
541
|
+
<div className="text-base font-semibold" style={{ color: 'var(--color-foreground)' }}>
|
|
542
|
+
暂无数据
|
|
543
|
+
</div>
|
|
544
|
+
<div className="text-sm" style={{ color: 'var(--color-foreground-secondary)' }}>
|
|
545
|
+
点击下方按钮新建第一条记录
|
|
546
|
+
</div>
|
|
547
|
+
<Button size="md" variant="primary">新建</Button>
|
|
548
|
+
</div>
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
**关键约束**:
|
|
552
|
+
|
|
553
|
+
- 容器:`py-16 gap-4`(垂直留白 64px、元素间 16px)
|
|
554
|
+
- 主文案:`text-base font-semibold`,颜色 `var(--color-foreground)`
|
|
555
|
+
- 副文案:`text-sm`,颜色 `var(--color-foreground-secondary)`
|
|
556
|
+
- 主行动:`<Button size="md" variant="primary" />`
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## 13. 自定义信息卡 / KPI 块(组件库未覆盖时)
|
|
561
|
+
|
|
562
|
+
如果你必须为「KPI 数字 + 描述」「带图标的功能卡」「步骤进度卡」这类非标元素手写一个区块,**严格遵守**:
|
|
563
|
+
|
|
564
|
+
```jsx
|
|
565
|
+
<div
|
|
566
|
+
style={{
|
|
567
|
+
background: 'var(--color-surface)',
|
|
568
|
+
borderRadius: 'var(--radius-lg)',
|
|
569
|
+
padding: 'var(--spacing-6)',
|
|
570
|
+
display: 'flex',
|
|
571
|
+
flexDirection: 'column',
|
|
572
|
+
gap: 'var(--spacing-2)',
|
|
573
|
+
}}
|
|
574
|
+
>
|
|
575
|
+
<div
|
|
576
|
+
style={{
|
|
577
|
+
fontSize: 'var(--text-sm)',
|
|
578
|
+
lineHeight: '20px',
|
|
579
|
+
color: 'var(--color-foreground-secondary)',
|
|
580
|
+
fontWeight: 'var(--font-medium)',
|
|
581
|
+
}}
|
|
582
|
+
>
|
|
583
|
+
总调用量
|
|
584
|
+
</div>
|
|
585
|
+
<div
|
|
586
|
+
style={{
|
|
587
|
+
fontSize: 'var(--text-2xl)',
|
|
588
|
+
lineHeight: '32px',
|
|
589
|
+
color: 'var(--color-foreground)',
|
|
590
|
+
fontWeight: 'var(--font-semibold)',
|
|
591
|
+
}}
|
|
592
|
+
>
|
|
593
|
+
1,284,392
|
|
594
|
+
</div>
|
|
595
|
+
<div
|
|
596
|
+
style={{
|
|
597
|
+
fontSize: 'var(--text-xs)',
|
|
598
|
+
lineHeight: '16px',
|
|
599
|
+
color: 'var(--color-foreground-muted)',
|
|
600
|
+
}}
|
|
601
|
+
>
|
|
602
|
+
较昨日 +12%
|
|
603
|
+
</div>
|
|
604
|
+
</div>
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
**关键约束**:
|
|
608
|
+
|
|
609
|
+
- 任何内联样式都必须走 `var(--token-...)`,禁止裸值
|
|
610
|
+
- 卡片之间永远 `gap: 8px`,卡片内 padding 永远 `24px`
|
|
611
|
+
- 卡片**不加阴影**,靠灰底+白卡的明度差自然分层
|
|
612
|
+
- 字号 / 字重 / 颜色都要走 token
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
## 14. AI 自检 Checklist(生成完整页/区块后必查)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
| 检查项 | 失败信号(grep 关键字) | 修复 |
|
|
620
|
+
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
621
|
+
| 颜色硬编码 | `#000`、`#333`、`text-black`、`bg-gray-`、`border-gray-` | 改用 `var(--color-...)` |
|
|
622
|
+
| 任意值字号 | `text-[\dpx]`、`text-[1.` | 取上表 9 档 |
|
|
623
|
+
| 错误字重 | 标题用 `font-bold` | 改 `font-semibold` |
|
|
624
|
+
| 任意值间距 | `p-[\dpx]`、`gap-[\dpx]`、`m[xytlrb]?-\[` | 取整数档 |
|
|
625
|
+
| 任意值圆角 | `rounded-[\dpx]` | 取 9 档之一 |
|
|
626
|
+
| 白卡阴影 | 白卡 / Card 含 `shadow-md`、`shadow-lg` | 去掉,靠灰底分层 |
|
|
627
|
+
| 任意值阴影 | `shadow-[` | 去掉或用 `shadow-{sm,md,lg}` |
|
|
628
|
+
| **白卡描边** | 背景为 `--color-surface` 的 div / Card 上出现 `border` / `outline` / `ring` / `borderColor` / `border-border-default` / `border border-border-` | **删除该 border**——白卡靠"灰底 vs 白卡的明度差 + 12px 圆角"承担层级,⛔ 不准加描边。仅卡内组件描边保留(详见 § 5.5) |
|
|
629
|
+
| 错误边框 | `border-black`、`border-gray-300` | 用 TFDS 组件,或 `var(--color-border-default)` |
|
|
630
|
+
| 假 Tag | `<span ... rounded-full ... bg-` | 改成 `<Tag />` |
|
|
631
|
+
| 裸链接 | `<a className="text-` | 改成 `<Button variant="text-brand" />` |
|
|
632
|
+
| 单独引入 lucide | `from 'lucide-react'` 单独图标 | 改成 `<Icon name="..." />` |
|
|
633
|
+
| 错误过渡 | `transition-all` | 改 `transition-colors` / `transition-opacity` 等 |
|
|
634
|
+
| 失明焦点 | `outline-none` 但未配 `focus-visible:ring` | 补焦点环 |
|
|
635
|
+
| 截断不生效 | `truncate` 父容器无 `min-w-0` | 父容器加 `min-w-0` |
|
|
636
|
+
| 任意 leading | `leading-[\d` | 取 token 之一 |
|