@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,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tabs — 同页内多块内容的视图切换
|
|
3
|
+
*
|
|
4
|
+
* **何时用**:详情子页签、卡片内分区、筛选维度切换(2~6 项为宜);不改变整站路由的「面板级」导航。
|
|
5
|
+
* **不用**:执行保存/取消等动作 → `Button`;单个表单字段从枚举选题 → `Select` / `Radio`;整站一级模块 → 侧栏/路由。
|
|
6
|
+
*
|
|
7
|
+
* **npm / AI 硬约束**:凡「点选切换多块互斥面板」**必须**用本组件;禁止一排 `Button` 或 `Tag` 冒充 Tabs。「分段器」= **`variant="segment"`**(灰轨白块),**不是** `Tag`。卡片内小模块切换、主工作区顶部**布局级**切换 → **默认优先** `variant="segment"`;详情子页签感 → `line`;强调块级 → `button`;顶导/浮层胶囊 → `pill`。
|
|
8
|
+
*
|
|
9
|
+
* @prop {'line'|'button'|'pill'|'segment'} [variant='line'] — line=页内主导航下划线;button/pill/segment=工具区或表单切换;segment=分段器(灰底容器+白选中块)
|
|
10
|
+
* @prop {'sm'|'md'|'lg'} [size='sm'] — 尺寸;内容展示区默认 SM,仅平台级顶部 header / 页面级导航可按场景使用 MD/LG
|
|
11
|
+
* @prop {Array} [items=null] — 标签项列表(每项含 label,可选 icon)
|
|
12
|
+
* @prop {number} [activeIndex=0] — 受控:当前选中索引
|
|
13
|
+
* @prop {number} [defaultIndex=0] — 非受控初始索引
|
|
14
|
+
* @prop {function} [onChange=null] — `(index) => void` 切换回调
|
|
15
|
+
* @prop {string} [className=''] — 根节点类名
|
|
16
|
+
*/
|
|
17
|
+
import { useState } from 'react';
|
|
18
|
+
|
|
19
|
+
/* ── 容器样式 ── */
|
|
20
|
+
const CONTAINER_BASE = 'inline-flex items-center relative w-fit';
|
|
21
|
+
|
|
22
|
+
const CONTAINER_VARIANT = {
|
|
23
|
+
line: 'gap-2 bg-transparent border-b border-b-border',
|
|
24
|
+
button: 'gap-2 bg-transparent',
|
|
25
|
+
// pill(胶囊)SM 默认与 segment(分段器)一致:整体高 36px、四周内距 4px,仅 UI 样式不同
|
|
26
|
+
// ring-inset 不占空间,避免描边撑高
|
|
27
|
+
pill: 'gap-1 p-1 bg-white/50 ring-1 ring-white ring-inset rounded-full',
|
|
28
|
+
// segment(分段器)容器内距固定 4px:白底块与灰轨四周留白一致
|
|
29
|
+
segment: 'gap-1 p-1 bg-fill rounded-md',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/* ── 标签项基础样式(所有变体共用的结构属性) ── */
|
|
33
|
+
const ITEM_BASE = [
|
|
34
|
+
'inline-flex items-center justify-center relative',
|
|
35
|
+
'border-none cursor-pointer select-none',
|
|
36
|
+
'[font-family:inherit]',
|
|
37
|
+
'leading-[20px] whitespace-nowrap',
|
|
38
|
+
'gap-2',
|
|
39
|
+
'[outline:2px_solid_transparent] outline-offset-2',
|
|
40
|
+
'[transition:color_200ms_ease,background_200ms_ease,font-weight_200ms_ease,box-shadow_200ms_ease]',
|
|
41
|
+
].join(' ');
|
|
42
|
+
|
|
43
|
+
/* ── line 变体共用的 ::after 指示器 ── */
|
|
44
|
+
const LINE_AFTER = "after:content-[''] after:absolute after:-bottom-px after:left-0 after:right-0 after:h-[3px] after:bg-brand-500 after:[transition:transform_250ms_ease]";
|
|
45
|
+
|
|
46
|
+
/* ── 标签项变体样式(default = 未选中,active = 选中) ── */
|
|
47
|
+
const ITEM_VARIANT = {
|
|
48
|
+
line: {
|
|
49
|
+
default: `text-blueGrey-600 [font-weight:var(--font-normal)] hover:text-blueGrey-700 active:text-blueGrey-800 focus-visible:outline-brand-200 ${LINE_AFTER} after:scale-x-0`,
|
|
50
|
+
active: `text-blueGrey-900 [font-weight:var(--font-semibold)] hover:text-blueGrey-900 focus-visible:outline-brand-200 ${LINE_AFTER} after:scale-x-100`,
|
|
51
|
+
},
|
|
52
|
+
button: {
|
|
53
|
+
default: 'text-blueGrey-600 [font-weight:var(--font-normal)] rounded-md hover:bg-fill hover:text-blueGrey-700 active:bg-blueGrey-200 focus-visible:outline-brand-200',
|
|
54
|
+
active: 'bg-brand-50 text-brand-700 [font-weight:var(--font-semibold)] rounded-md hover:bg-brand-100 active:bg-brand-200 focus-visible:outline-brand-200',
|
|
55
|
+
},
|
|
56
|
+
pill: {
|
|
57
|
+
default: 'text-blueGrey-700 [font-weight:var(--font-normal)] rounded-full hover:bg-fill active:bg-blueGrey-300 focus-visible:outline-blueGrey-400',
|
|
58
|
+
active: 'bg-grey-950 text-white [font-weight:var(--font-semibold)] rounded-full hover:bg-grey-900 active:bg-grey-800 focus-visible:outline-grey-400',
|
|
59
|
+
},
|
|
60
|
+
segment: {
|
|
61
|
+
default: 'text-blueGrey-600 [font-weight:var(--font-normal)] rounded-md hover:text-blueGrey-700 hover:bg-fill active:bg-white/70 focus-visible:outline-blueGrey-400',
|
|
62
|
+
active: 'bg-white text-blueGrey-900 [font-weight:var(--font-semibold)] rounded-md hover:bg-white active:bg-blueGrey-50 focus-visible:outline-blueGrey-400',
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/* ── 标签项尺寸样式(variant × size → height + padding + font-size) ── */
|
|
67
|
+
const ITEM_SIZE = {
|
|
68
|
+
line: {
|
|
69
|
+
sm: 'h-[38px] px-3 text-xs',
|
|
70
|
+
md: 'h-[46px] px-3 text-sm',
|
|
71
|
+
lg: 'h-[54px] px-4 text-sm',
|
|
72
|
+
},
|
|
73
|
+
button: {
|
|
74
|
+
sm: 'h-[32px] px-3 text-xs',
|
|
75
|
+
md: 'h-[36px] px-3 text-sm',
|
|
76
|
+
lg: 'h-[40px] px-4 text-sm',
|
|
77
|
+
},
|
|
78
|
+
pill: {
|
|
79
|
+
sm: 'h-[28px] px-4 text-xs',
|
|
80
|
+
md: 'h-[32px] px-4 text-sm',
|
|
81
|
+
lg: 'h-[36px] px-5 text-sm',
|
|
82
|
+
},
|
|
83
|
+
segment: {
|
|
84
|
+
// SM:整体高度 36px(容器 4px ×2 + item 28px)
|
|
85
|
+
sm: 'h-[28px] px-3 text-xs',
|
|
86
|
+
md: 'h-[36px] px-3 text-sm',
|
|
87
|
+
lg: 'h-[40px] px-4 text-sm',
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/* ── 图标插槽 ── */
|
|
92
|
+
const ICON_CLASS = 'flex items-center justify-center shrink-0 w-4 h-4';
|
|
93
|
+
|
|
94
|
+
export default function Tabs({
|
|
95
|
+
variant = 'line',
|
|
96
|
+
size = 'sm',
|
|
97
|
+
items = null,
|
|
98
|
+
activeIndex,
|
|
99
|
+
defaultIndex = 0,
|
|
100
|
+
onChange,
|
|
101
|
+
className = '',
|
|
102
|
+
...rest
|
|
103
|
+
}) {
|
|
104
|
+
const [internalIndex, setInternalIndex] = useState(defaultIndex);
|
|
105
|
+
const isControlled = activeIndex !== undefined;
|
|
106
|
+
const currentIndex = isControlled ? (activeIndex ?? 0) : internalIndex;
|
|
107
|
+
|
|
108
|
+
const handleClick = (index) => {
|
|
109
|
+
if (!isControlled) setInternalIndex(index);
|
|
110
|
+
onChange?.(index);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const containerCls = [
|
|
114
|
+
CONTAINER_BASE,
|
|
115
|
+
CONTAINER_VARIANT[variant],
|
|
116
|
+
className,
|
|
117
|
+
].filter(Boolean).join(' ');
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<div className={[`tfds-tabs`, containerCls].filter(Boolean).join(' ')} role="tablist" {...rest} data-tfds-component="Tabs">
|
|
121
|
+
{(items ?? []).map((item, index) => {
|
|
122
|
+
const isActive = index === currentIndex;
|
|
123
|
+
const itemCls = [
|
|
124
|
+
ITEM_BASE,
|
|
125
|
+
ITEM_VARIANT[variant][isActive ? 'active' : 'default'],
|
|
126
|
+
ITEM_SIZE[variant][size],
|
|
127
|
+
].join(' ');
|
|
128
|
+
const itemStyle = {
|
|
129
|
+
fontWeight: isActive ? 'var(--font-semibold)' : 'var(--font-normal)',
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<button
|
|
134
|
+
key={index}
|
|
135
|
+
className={itemCls}
|
|
136
|
+
style={itemStyle}
|
|
137
|
+
role="tab"
|
|
138
|
+
aria-selected={isActive}
|
|
139
|
+
tabIndex={isActive ? 0 : -1}
|
|
140
|
+
onClick={() => handleClick(index)}
|
|
141
|
+
>
|
|
142
|
+
{item.icon && <span className={ICON_CLASS}>{item.icon}</span>}
|
|
143
|
+
{item.label}
|
|
144
|
+
</button>
|
|
145
|
+
);
|
|
146
|
+
})}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tabs — TOKEN_MAP(供平台属性面板展示)
|
|
3
|
+
* 组件实现代码见 Tabs.jsx
|
|
4
|
+
*/
|
|
5
|
+
export const TABS_TOKEN_MAP = {
|
|
6
|
+
base: [
|
|
7
|
+
{ label: '默认尺寸', cssProp: 'size', value: 'SM(内容区 / 卡片内 / 表单分段 / 筛选维度默认)' },
|
|
8
|
+
{ label: '字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
|
|
9
|
+
{ label: '行高', cssProp: 'line-height', value: '20px' },
|
|
10
|
+
{ label: '图标尺寸', cssProp: 'width/height', value: '16px' },
|
|
11
|
+
{ label: '图标间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
|
|
12
|
+
],
|
|
13
|
+
variants: {
|
|
14
|
+
'line': [
|
|
15
|
+
{ label: '默认文字', cssProp: 'color', token: '--color-blueGrey-600', value: '#667085', semanticRef: 'text-tertiary' },
|
|
16
|
+
{ label: '悬浮文字', cssProp: 'color', token: '--color-blueGrey-700', value: '#475467', state: 'hover', semanticRef: 'text-secondary' },
|
|
17
|
+
{ label: '按下文字', cssProp: 'color', token: '--color-blueGrey-800', value: '#344054', state: 'active' },
|
|
18
|
+
{ label: '选中文字', cssProp: 'color', token: '--color-blueGrey-900', value: '#182230', semanticRef: 'text-primary' },
|
|
19
|
+
{ label: '选中字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 style fontWeight: var(--font-semibold),class 兜底 [font-weight:var(--font-semibold)])' },
|
|
20
|
+
{ label: '选中标线', cssProp: 'background', token: '--color-brand-500', value: '#56D3BC', semanticRef: 'status-primary' },
|
|
21
|
+
{ label: '指示高度', cssProp: 'height', value: '3px' },
|
|
22
|
+
{ label: '底线颜色', cssProp: 'border-color', token: '--color-border-default', value: '#E4E7EC', semanticRef: 'border-default' },
|
|
23
|
+
{ label: '标签间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
|
|
24
|
+
{ label: '聚焦环', cssProp: 'outline-color', token: '--color-brand-200', value: '#A8E8D7', state: 'focus' },
|
|
25
|
+
],
|
|
26
|
+
'button': [
|
|
27
|
+
{ label: '默认文字', cssProp: 'color', token: '--color-blueGrey-600', value: '#667085', semanticRef: 'text-tertiary' },
|
|
28
|
+
{ label: '悬浮文字', cssProp: 'color', token: '--color-blueGrey-700', value: '#475467', state: 'hover' },
|
|
29
|
+
{ label: '悬浮背景', cssProp: 'background', token: '--color-fill', value: 'rgba(83, 96, 143, 0.07)', state: 'hover', semanticRef: 'fill-default' },
|
|
30
|
+
{ label: '按下背景', cssProp: 'background', token: '--color-blueGrey-200', value: '#F2F4F7', state: 'active' },
|
|
31
|
+
{ label: '选中背景', cssProp: 'background', token: '--color-brand-50', value: '#EAFAF6', semanticRef: 'status-primary.bg' },
|
|
32
|
+
{ label: '选悬背景', cssProp: 'background', token: '--color-brand-100', value: '#CFF3EA', state: 'hover' },
|
|
33
|
+
{ label: '选按背景', cssProp: 'background', token: '--color-brand-200', value: '#A8E8D7', state: 'active' },
|
|
34
|
+
{ label: '选中文字', cssProp: 'color', token: '--color-brand-700', value: '#18B49D', semanticRef: 'status-primary' },
|
|
35
|
+
{ label: '选中字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 style fontWeight: var(--font-semibold),class 兜底 [font-weight:var(--font-semibold)])' },
|
|
36
|
+
{ label: '圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
|
|
37
|
+
{ label: '标签间距', cssProp: 'gap', token: '--spacing-2', value: '8px' },
|
|
38
|
+
{ label: '聚焦环', cssProp: 'outline-color', token: '--color-brand-200', value: '#A8E8D7', state: 'focus' },
|
|
39
|
+
],
|
|
40
|
+
'pill': [
|
|
41
|
+
{ label: '容器背景', cssProp: 'background', value: 'rgba(255, 255, 255, 0.5)' },
|
|
42
|
+
{ label: '容器内描边', cssProp: 'box-shadow (inset, ring-inset)', token: '--color-white', value: '#FFFFFF', semanticRef: '内描边不占布局空间,避免撑高 2px' },
|
|
43
|
+
{ label: '容器圆角', cssProp: 'border-radius', token: '--radius-full', value: '9999px' },
|
|
44
|
+
{ label: '默认文字', cssProp: 'color', token: '--color-blueGrey-700', value: '#475467', semanticRef: 'text-secondary' },
|
|
45
|
+
{ label: '悬浮背景', cssProp: 'background', token: '--color-fill', value: 'rgba(83, 96, 143, 0.07)', state: 'hover', semanticRef: 'fill-default' },
|
|
46
|
+
{ label: '按下背景', cssProp: 'background', token: '--color-blueGrey-300', value: '#E4E7EC', state: 'active' },
|
|
47
|
+
{ label: '选中背景', cssProp: 'background', token: '--color-grey-950', value: '#111116' },
|
|
48
|
+
{ label: '选悬背景', cssProp: 'background', token: '--color-grey-900', value: '#1C1C23', state: 'hover' },
|
|
49
|
+
{ label: '选按背景', cssProp: 'background', token: '--color-grey-800', value: '#2E2F38', state: 'active' },
|
|
50
|
+
{ label: '选中文字', cssProp: 'color', token: '--color-white', value: '#FFFFFF', semanticRef: 'text-inverse' },
|
|
51
|
+
{ label: '选中字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 style fontWeight: var(--font-semibold),class 兜底 [font-weight:var(--font-semibold)])' },
|
|
52
|
+
{ label: '标签间距', cssProp: 'gap', token: '--spacing-1', value: '4px' },
|
|
53
|
+
{ label: '聚焦环', cssProp: 'outline-color', token: '--color-grey-400', value: '#878892', state: 'focus' },
|
|
54
|
+
],
|
|
55
|
+
'segment': [
|
|
56
|
+
{ label: '容器背景', cssProp: 'background', token: '--color-fill', value: 'rgba(83, 96, 143, 0.07)', semanticRef: 'fill-default' },
|
|
57
|
+
{ label: '容器圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
|
|
58
|
+
{ label: '容器内距', cssProp: 'padding', token: '--spacing-1', value: '4px(SM:整体 36px = item 28px + 上下各 4px)' },
|
|
59
|
+
{ label: '默认文字', cssProp: 'color', token: '--color-blueGrey-600', value: '#667085', semanticRef: 'text-tertiary' },
|
|
60
|
+
{ label: '悬浮文字', cssProp: 'color', token: '--color-blueGrey-700', value: '#475467', state: 'hover' },
|
|
61
|
+
{ label: '悬浮背景', cssProp: 'background', token: '--color-fill', value: 'rgba(83, 96, 143, 0.07)', state: 'hover', semanticRef: 'fill-default' },
|
|
62
|
+
{ label: '按下背景', cssProp: 'background', value: 'rgba(255, 255, 255, 0.7)', state: 'active' },
|
|
63
|
+
{ label: '选中背景', cssProp: 'background', token: '--color-white', value: '#FFFFFF' },
|
|
64
|
+
{ label: '选中文字', cssProp: 'color', token: '--color-blueGrey-900', value: '#182230', semanticRef: 'text-primary' },
|
|
65
|
+
{ label: '选中字重', cssProp: 'font-weight', token: '--font-semibold', value: '600(运行时使用 style fontWeight: var(--font-semibold),class 兜底 [font-weight:var(--font-semibold)])' },
|
|
66
|
+
{ label: '选按背景', cssProp: 'background', token: '--color-blueGrey-50', value: '#FCFCFD', state: 'active' },
|
|
67
|
+
{ label: '标签圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' },
|
|
68
|
+
{ label: '标签间距', cssProp: 'gap', token: '--spacing-1', value: '4px' },
|
|
69
|
+
{ label: '聚焦环', cssProp: 'outline-color', token: '--color-blueGrey-400', value: '#D0D5DD', state: 'focus' },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
sizes: {
|
|
73
|
+
sm: [
|
|
74
|
+
{ label: '字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
|
|
75
|
+
{ label: '内距', cssProp: 'padding-inline', token: '--spacing-3', value: '12px', variants: ['line', 'button', 'segment'] },
|
|
76
|
+
{ label: '内距', cssProp: 'padding-inline', token: '--spacing-4', value: '16px', variants: ['pill'] },
|
|
77
|
+
{ label: '组件高度', cssProp: 'height', value: '38px', variants: ['line'] },
|
|
78
|
+
{ label: '组件高度', cssProp: 'height', value: '32px', variants: ['button'] },
|
|
79
|
+
{ label: '组件整体高度', cssProp: 'height', value: '36px(分段器:item 28px + 容器内距 4px×2)', variants: ['segment'] },
|
|
80
|
+
{ label: '组件整体高度', cssProp: 'height (padding 4+28+4, ring-inset 不占空间)', value: '36px', variants: ['pill'] },
|
|
81
|
+
{ label: '选项高度', cssProp: 'height (item)', value: '28px(与分段器一致)', variants: ['pill'] },
|
|
82
|
+
],
|
|
83
|
+
md: [
|
|
84
|
+
{ label: '字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
|
|
85
|
+
{ label: '内距', cssProp: 'padding-inline', token: '--spacing-3', value: '12px', variants: ['line', 'button', 'segment'] },
|
|
86
|
+
{ label: '内距', cssProp: 'padding-inline', token: '--spacing-4', value: '16px', variants: ['pill'] },
|
|
87
|
+
{ label: '组件高度', cssProp: 'height', value: '46px', variants: ['line'] },
|
|
88
|
+
{ label: '组件高度', cssProp: 'height', value: '36px', variants: ['button', 'segment'] },
|
|
89
|
+
{ label: '组件高度', cssProp: 'height (padding 6+32+6, ring-inset 不占空间)', value: '44px', variants: ['pill'] },
|
|
90
|
+
{ label: '选项高度', cssProp: 'height (item)', value: '32px', variants: ['pill'] },
|
|
91
|
+
],
|
|
92
|
+
lg: [
|
|
93
|
+
{ label: '字号', cssProp: 'font-size', token: '--text-sm', value: '14px' },
|
|
94
|
+
{ label: '内距', cssProp: 'padding-inline', token: '--spacing-4', value: '16px', variants: ['line', 'button', 'segment'] },
|
|
95
|
+
{ label: '内距', cssProp: 'padding-inline', token: '--spacing-5', value: '20px', variants: ['pill'] },
|
|
96
|
+
{ label: '组件高度', cssProp: 'height', value: '54px', variants: ['line'] },
|
|
97
|
+
{ label: '组件高度', cssProp: 'height', value: '40px', variants: ['button', 'segment'] },
|
|
98
|
+
{ label: '组件高度', cssProp: 'height (padding 6+36+6, ring-inset 不占空间)', value: '48px', variants: ['pill'] },
|
|
99
|
+
{ label: '选项高度', cssProp: 'height (item)', value: '36px', variants: ['pill'] },
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag — 标签组件(Tailwind 内联)
|
|
3
|
+
* @prop {'brand'|'red'|'orange'|'yellow'|'green'|'cyan'|'blue'|'purple'|'pink'|'teal'|'grey'|'white'|'ai'} [variant='brand'] — 颜色变体
|
|
4
|
+
* @prop {'s'|'m'|'l'} [size='m'] — 尺寸档位
|
|
5
|
+
* @prop {'md'|'square'|'full'} [radius='md'] — 圆角样式
|
|
6
|
+
* @prop {'regular'|'bold'} [fontWeight='bold'] — 字体粗细
|
|
7
|
+
* @prop {boolean} [showIcon=false] — 是否显示左侧图标
|
|
8
|
+
* @prop {string} [iconName='tag-01-stroked'] — 图标名称
|
|
9
|
+
* @prop {boolean} [closable=false] — 是否显示关闭按钮
|
|
10
|
+
* @prop {function|null} [onClose=null] — 关闭回调
|
|
11
|
+
* @prop {string} [className=''] — 附加类名
|
|
12
|
+
*
|
|
13
|
+
* 白色标签用于业务卡片、筛选标签等中性场景;
|
|
14
|
+
* `square` 圆角使用 3px,和 Avatar 方形 / Card 内置标签保持同一套细圆角语言。
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import Icon from './Icon';
|
|
18
|
+
|
|
19
|
+
/* ── 基础样式(所有变体 / 尺寸共用) ── */
|
|
20
|
+
const BASE = [
|
|
21
|
+
'inline-flex items-center justify-center',
|
|
22
|
+
'[font-family:inherit]',
|
|
23
|
+
'cursor-default select-none',
|
|
24
|
+
'transition-all duration-150 leading-none whitespace-nowrap',
|
|
25
|
+
].join(' ');
|
|
26
|
+
|
|
27
|
+
/* ── 变体 → Tailwind 类名(按色相排序) ── */
|
|
28
|
+
const VARIANT_CLASS = {
|
|
29
|
+
red: [
|
|
30
|
+
'bg-red-50 text-red-600',
|
|
31
|
+
].join(' '),
|
|
32
|
+
orange: [
|
|
33
|
+
'bg-orange-50 text-orange-600',
|
|
34
|
+
].join(' '),
|
|
35
|
+
yellow: [
|
|
36
|
+
'bg-yellow-100 text-yellow-700',
|
|
37
|
+
].join(' '),
|
|
38
|
+
green: [
|
|
39
|
+
'bg-green-50 text-green-600',
|
|
40
|
+
].join(' '),
|
|
41
|
+
cyan: [
|
|
42
|
+
'bg-cyan-50 text-cyan-600',
|
|
43
|
+
].join(' '),
|
|
44
|
+
blue: [
|
|
45
|
+
'bg-blue-50 text-blue-600',
|
|
46
|
+
].join(' '),
|
|
47
|
+
purple: [
|
|
48
|
+
'bg-purple-50 text-purple-600',
|
|
49
|
+
].join(' '),
|
|
50
|
+
pink: [
|
|
51
|
+
'bg-pink-50 text-pink-600',
|
|
52
|
+
].join(' '),
|
|
53
|
+
teal: [
|
|
54
|
+
'bg-brand-50 text-brand-800',
|
|
55
|
+
].join(' '),
|
|
56
|
+
grey: [
|
|
57
|
+
'bg-fill text-blueGrey-700',
|
|
58
|
+
].join(' '),
|
|
59
|
+
white: [
|
|
60
|
+
'bg-white text-foreground border border-border-default',
|
|
61
|
+
].join(' '),
|
|
62
|
+
brand: [
|
|
63
|
+
'bg-brand-50 text-brand-500',
|
|
64
|
+
].join(' '),
|
|
65
|
+
ai: [
|
|
66
|
+
'text-brand-500',
|
|
67
|
+
].join(' '),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/* ── 尺寸 → 间距配置(参考 Figma 截图) ── */
|
|
71
|
+
const SIZE_CONFIG = {
|
|
72
|
+
s: {
|
|
73
|
+
height: 'h-[16px]',
|
|
74
|
+
fontSize: 'text-xs',
|
|
75
|
+
paddingLeft: 'pl-1',
|
|
76
|
+
paddingRight: 'pr-1',
|
|
77
|
+
iconToTextGap: '[&>.tag-icon]:mr-1',
|
|
78
|
+
textToCloseGap: '[&>.tag-text]:mr-1',
|
|
79
|
+
},
|
|
80
|
+
m: {
|
|
81
|
+
height: 'h-[20px]',
|
|
82
|
+
fontSize: 'text-xs',
|
|
83
|
+
paddingLeft: 'pl-2',
|
|
84
|
+
paddingRight: 'pr-2',
|
|
85
|
+
iconToTextGap: '[&>.tag-icon]:mr-1',
|
|
86
|
+
textToCloseGap: '[&>.tag-text]:mr-1',
|
|
87
|
+
},
|
|
88
|
+
l: {
|
|
89
|
+
height: 'h-[24px]',
|
|
90
|
+
fontSize: 'text-xs',
|
|
91
|
+
paddingLeft: 'pl-2',
|
|
92
|
+
paddingRight: 'pr-2',
|
|
93
|
+
iconToTextGap: '[&>.tag-icon]:mr-1',
|
|
94
|
+
textToCloseGap: '[&>.tag-text]:mr-1',
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/* ── 圆角 → Tailwind 类名 ── */
|
|
99
|
+
const RADIUS_CLASS = {
|
|
100
|
+
md: 'rounded-md',
|
|
101
|
+
square: 'rounded-avatar',
|
|
102
|
+
full: 'rounded-full',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const FONT_WEIGHT_CLASS = {
|
|
106
|
+
regular: '[font-weight:400]',
|
|
107
|
+
bold: '[font-weight:var(--font-bold)]',
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const CLOSE_ICON = (
|
|
111
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
112
|
+
<path d="M9 3L3 9M3 3L9 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
113
|
+
</svg>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
export default function Tag({
|
|
117
|
+
variant = 'brand',
|
|
118
|
+
size = 'm',
|
|
119
|
+
radius = 'md',
|
|
120
|
+
fontWeight = 'bold',
|
|
121
|
+
showIcon = false,
|
|
122
|
+
iconName = 'tag-01-stroked',
|
|
123
|
+
closable = false,
|
|
124
|
+
onClose,
|
|
125
|
+
className = '',
|
|
126
|
+
style,
|
|
127
|
+
children,
|
|
128
|
+
...rest
|
|
129
|
+
}) {
|
|
130
|
+
const config = SIZE_CONFIG[size];
|
|
131
|
+
const aiStyle = variant === 'ai'
|
|
132
|
+
? {
|
|
133
|
+
background: 'var(--bg-chat-outgoing-ai)',
|
|
134
|
+
}
|
|
135
|
+
: undefined;
|
|
136
|
+
const mergedStyle = {
|
|
137
|
+
...(aiStyle || null),
|
|
138
|
+
...(style || null),
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const cls = [
|
|
142
|
+
BASE,
|
|
143
|
+
VARIANT_CLASS[variant],
|
|
144
|
+
config.height,
|
|
145
|
+
config.fontSize,
|
|
146
|
+
config.paddingLeft,
|
|
147
|
+
config.paddingRight,
|
|
148
|
+
RADIUS_CLASS[radius],
|
|
149
|
+
showIcon ? config.iconToTextGap : '',
|
|
150
|
+
closable ? config.textToCloseGap : '',
|
|
151
|
+
className,
|
|
152
|
+
].filter(Boolean).join(' ');
|
|
153
|
+
const textClassName = [
|
|
154
|
+
'tag-text whitespace-nowrap',
|
|
155
|
+
FONT_WEIGHT_CLASS[fontWeight] || FONT_WEIGHT_CLASS.bold,
|
|
156
|
+
].join(' ');
|
|
157
|
+
|
|
158
|
+
const handleClose = (e) => {
|
|
159
|
+
e.stopPropagation();
|
|
160
|
+
if (onClose) {
|
|
161
|
+
onClose();
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const iconSize = 'xs';
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<span className={[`tfds-tag`, cls].filter(Boolean).join(' ')} style={mergedStyle} {...rest} data-tfds-component="Tag">
|
|
169
|
+
{showIcon && (
|
|
170
|
+
<span className="tag-icon inline-flex items-center justify-center">
|
|
171
|
+
<Icon name={iconName} size={iconSize} />
|
|
172
|
+
</span>
|
|
173
|
+
)}
|
|
174
|
+
<span
|
|
175
|
+
className={textClassName}
|
|
176
|
+
style={variant === 'ai'
|
|
177
|
+
? {
|
|
178
|
+
background: 'var(--gradient-ai-fill-text)',
|
|
179
|
+
WebkitBackgroundClip: 'text',
|
|
180
|
+
backgroundClip: 'text',
|
|
181
|
+
color: 'transparent',
|
|
182
|
+
}
|
|
183
|
+
: undefined}
|
|
184
|
+
>
|
|
185
|
+
{children}
|
|
186
|
+
</span>
|
|
187
|
+
{closable && (
|
|
188
|
+
<button
|
|
189
|
+
type="button"
|
|
190
|
+
className="inline-flex items-center justify-center"
|
|
191
|
+
onClick={handleClose}
|
|
192
|
+
aria-label="关闭"
|
|
193
|
+
>
|
|
194
|
+
{CLOSE_ICON}
|
|
195
|
+
</button>
|
|
196
|
+
)}
|
|
197
|
+
</span>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag — TOKEN_MAP(供平台属性面板展示)
|
|
3
|
+
* 组件实现代码见 Tag.jsx
|
|
4
|
+
*
|
|
5
|
+
* 变体排序(按色相):
|
|
6
|
+
* - 暖色调:red → orange → yellow
|
|
7
|
+
* - 冷色调:green → cyan → blue → purple → pink → teal
|
|
8
|
+
* - 中性色:grey → white
|
|
9
|
+
* - 品牌色:brand(与 teal 相同)
|
|
10
|
+
* - AI:ai
|
|
11
|
+
*
|
|
12
|
+
* 颜色映射规则(严格遵循 TFDS Token 规范):
|
|
13
|
+
* - 背景色:使用 {color}-50(最浅色)
|
|
14
|
+
* - 文字色:默认使用 {color}-600(深色);teal 使用 brand-800,yellow 使用 yellow-700
|
|
15
|
+
*
|
|
16
|
+
* 边框规则:
|
|
17
|
+
* - 白色标签:显示边框,边框色为默认描边语义色
|
|
18
|
+
* - 其他标签:无边框
|
|
19
|
+
*
|
|
20
|
+
* 圆角:
|
|
21
|
+
* - md: 半圆,8px(默认)
|
|
22
|
+
* - square: 方形细圆角,3px
|
|
23
|
+
* - full: 全圆,9999px
|
|
24
|
+
*
|
|
25
|
+
* 特殊情况:
|
|
26
|
+
* - teal:使用 brand token,背景 brand-50,文字 brand-800
|
|
27
|
+
* - grey:使用 blueGrey token(最接近的灰色系)
|
|
28
|
+
* - white:纯白色背景,使用 blueGrey 作为文字和边框色
|
|
29
|
+
* - ai:使用 ai-fill-1 渐变背景,文字使用 ai-fill-text 渐变
|
|
30
|
+
*
|
|
31
|
+
* 图标配置:
|
|
32
|
+
* - 默认图标:tag-01-stroked
|
|
33
|
+
* - 图标尺寸:所有尺寸均为 12px (xs)
|
|
34
|
+
* - 图标右侧到文字的间距:4px(所有尺寸)
|
|
35
|
+
*
|
|
36
|
+
* 尺寸(参考 Figma 截图):
|
|
37
|
+
* - S: 高度 16px,字号 12px
|
|
38
|
+
* - 左侧内距:4px
|
|
39
|
+
* - 右侧内距:4px
|
|
40
|
+
* - 垂直内距:0px
|
|
41
|
+
* - 字号:12px
|
|
42
|
+
* - 图标尺寸:12px (xs)
|
|
43
|
+
* - 图标右侧到文字的间距:4px
|
|
44
|
+
* - 文字右侧到关闭按钮的间距:4px
|
|
45
|
+
* - M: 高度 20px,字号 12px
|
|
46
|
+
* - 左侧内距:4px
|
|
47
|
+
* - 右侧内距:4px
|
|
48
|
+
* - 垂直内距:0px
|
|
49
|
+
* - 字号:12px
|
|
50
|
+
* - 图标尺寸:12px (xs)
|
|
51
|
+
* - 图标右侧到文字的间距:4px
|
|
52
|
+
* - 文字右侧到关闭按钮的间距:4px
|
|
53
|
+
* - L: 高度 24px,字号 12px
|
|
54
|
+
* - 左侧内距:4px
|
|
55
|
+
* - 右侧内距:4px
|
|
56
|
+
* - 垂直内距:0px
|
|
57
|
+
* - 字号:12px
|
|
58
|
+
* - 图标尺寸:12px (xs)
|
|
59
|
+
* - 图标右侧到文字的间距:4px
|
|
60
|
+
* - 文字右侧到关闭按钮的间距:4px
|
|
61
|
+
*
|
|
62
|
+
* 字体粗细:
|
|
63
|
+
* - bold:粗体(默认),字重固定 700(--font-bold)
|
|
64
|
+
* - regular:细体,字重固定 400
|
|
65
|
+
*/
|
|
66
|
+
export const TAG_TOKEN_MAP = {
|
|
67
|
+
base: [],
|
|
68
|
+
variants: {
|
|
69
|
+
red: [
|
|
70
|
+
{ label: '背景色', cssProp: 'background', token: '--color-red-50', value: '#FEF2F1' },
|
|
71
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-red-600', value: '#D32E24' },
|
|
72
|
+
],
|
|
73
|
+
orange: [
|
|
74
|
+
{ label: '背景色', cssProp: 'background', token: '--color-orange-50', value: '#FFF5EE' },
|
|
75
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-orange-600', value: '#D17310' },
|
|
76
|
+
],
|
|
77
|
+
yellow: [
|
|
78
|
+
{ label: '背景色', cssProp: 'background', token: '--color-yellow-100', value: '#FEFACF' },
|
|
79
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-yellow-700', value: '#A5760A' },
|
|
80
|
+
],
|
|
81
|
+
green: [
|
|
82
|
+
{ label: '背景色', cssProp: 'background', token: '--color-green-50', value: '#F0FDF4' },
|
|
83
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-green-600', value: '#329538' },
|
|
84
|
+
],
|
|
85
|
+
cyan: [
|
|
86
|
+
{ label: '背景色', cssProp: 'background', token: '--color-cyan-50', value: '#EAF9FA' },
|
|
87
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-cyan-600', value: '#0E94A0' },
|
|
88
|
+
],
|
|
89
|
+
blue: [
|
|
90
|
+
{ label: '背景色', cssProp: 'background', token: '--color-blue-50', value: '#ECF6FE' },
|
|
91
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-blue-600', value: '#0B69D4' },
|
|
92
|
+
],
|
|
93
|
+
purple: [
|
|
94
|
+
{ label: '背景色', cssProp: 'background', token: '--color-purple-50', value: '#F7EAF7' },
|
|
95
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-purple-600', value: '#8B239F' },
|
|
96
|
+
],
|
|
97
|
+
pink: [
|
|
98
|
+
{ label: '背景色', cssProp: 'background', token: '--color-pink-50', value: '#FDEDF1' },
|
|
99
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-pink-600', value: '#C32165' },
|
|
100
|
+
],
|
|
101
|
+
teal: [
|
|
102
|
+
{ label: '背景色', cssProp: 'background', token: '--color-brand-50', value: '#EAFAF6' },
|
|
103
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-brand-800', value: '#129683' },
|
|
104
|
+
],
|
|
105
|
+
grey: [
|
|
106
|
+
{ label: '背景色', cssProp: 'background', token: '--color-fill', value: 'rgba(83, 96, 143, 0.07)' },
|
|
107
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-blueGrey-700', value: '#475467' },
|
|
108
|
+
],
|
|
109
|
+
white: [
|
|
110
|
+
{ label: '背景色', cssProp: 'background', value: '#FFFFFF' },
|
|
111
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-foreground', value: '#182230', semanticRef: 'text-primary' },
|
|
112
|
+
{ label: '边框宽度', cssProp: 'border-width', value: '1px' },
|
|
113
|
+
{ label: '边框色', cssProp: 'border-color', token: '--color-border-default', value: '#E4E7EC', semanticRef: 'border-default' },
|
|
114
|
+
],
|
|
115
|
+
brand: [
|
|
116
|
+
{ label: '背景色', cssProp: 'background', token: '--color-brand-50', value: '#EAFAF6' },
|
|
117
|
+
{ label: '文字颜色', cssProp: 'color', token: '--color-brand-500', value: '#56D3BC' },
|
|
118
|
+
],
|
|
119
|
+
ai: [
|
|
120
|
+
{ label: '背景色', cssProp: 'background', token: '--bg-chat-outgoing-ai', value: 'linear-gradient(90deg, rgba(230, 247, 244, 1) 0%, rgba(239, 246, 255, 1) 55%, rgba(243, 245, 255, 1) 90%, rgba(252, 243, 255, 1) 100%)', semanticRef: 'bg-chat-outgoing-ai' },
|
|
121
|
+
{ label: '文字颜色', cssProp: 'color', token: '--gradient-ai-fill-text', value: 'linear-gradient(135deg, rgba(22, 218, 203, 1) 0%, rgba(49, 134, 212, 1) 20%, rgba(111, 88, 227, 1) 70%, rgba(231, 116, 221, 1) 100%)' },
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
sizes: {
|
|
125
|
+
s: [
|
|
126
|
+
{ label: '高度', cssProp: 'height', value: '16px' },
|
|
127
|
+
{ label: '左侧内距', cssProp: 'padding-left', token: '--spacing-1', value: '4px' },
|
|
128
|
+
{ label: '右侧内距', cssProp: 'padding-right', token: '--spacing-1', value: '4px' },
|
|
129
|
+
{ label: '垂直内距', cssProp: 'padding-block', token: '--spacing-0', value: '0px' },
|
|
130
|
+
{ label: '字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
|
|
131
|
+
{ label: '图标尺寸', cssProp: 'icon-size', value: '12px (xs)' },
|
|
132
|
+
{ label: '图标右侧到文字的间距', cssProp: 'margin-right', token: '--spacing-1', value: '4px' },
|
|
133
|
+
{ label: '文字右侧到关闭按钮的间距', cssProp: 'margin-right', token: '--spacing-1', value: '4px' },
|
|
134
|
+
],
|
|
135
|
+
m: [
|
|
136
|
+
{ label: '高度', cssProp: 'height', value: '20px' },
|
|
137
|
+
{ label: '左侧内距', cssProp: 'padding-left', token: '--spacing-1', value: '4px' },
|
|
138
|
+
{ label: '右侧内距', cssProp: 'padding-right', token: '--spacing-1', value: '4px' },
|
|
139
|
+
{ label: '垂直内距', cssProp: 'padding-block', token: '--spacing-0', value: '0px' },
|
|
140
|
+
{ label: '字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
|
|
141
|
+
{ label: '图标尺寸', cssProp: 'icon-size', value: '12px (xs)' },
|
|
142
|
+
{ label: '图标右侧到文字的间距', cssProp: 'margin-right', token: '--spacing-1', value: '4px' },
|
|
143
|
+
{ label: '文字右侧到关闭按钮的间距', cssProp: 'margin-right', token: '--spacing-1', value: '4px' },
|
|
144
|
+
],
|
|
145
|
+
l: [
|
|
146
|
+
{ label: '高度', cssProp: 'height', value: '24px' },
|
|
147
|
+
{ label: '左侧内距', cssProp: 'padding-left', token: '--spacing-1', value: '4px' },
|
|
148
|
+
{ label: '右侧内距', cssProp: 'padding-right', token: '--spacing-1', value: '4px' },
|
|
149
|
+
{ label: '垂直内距', cssProp: 'padding-block', token: '--spacing-0', value: '0px' },
|
|
150
|
+
{ label: '字号', cssProp: 'font-size', token: '--text-xs', value: '12px' },
|
|
151
|
+
{ label: '图标尺寸', cssProp: 'icon-size', value: '12px (xs)' },
|
|
152
|
+
{ label: '图标右侧到文字的间距', cssProp: 'margin-right', token: '--spacing-1', value: '4px' },
|
|
153
|
+
{ label: '文字右侧到关闭按钮的间距', cssProp: 'margin-right', token: '--spacing-1', value: '4px' },
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
radii: {
|
|
157
|
+
md: [{ label: '圆角', cssProp: 'border-radius', token: '--radius-md', value: '8px' }],
|
|
158
|
+
square: [{ label: '圆角', cssProp: 'border-radius', token: '--radius-avatar', value: '3px' }],
|
|
159
|
+
full: [{ label: '圆角', cssProp: 'border-radius', token: '--radius-full', value: '9999px' }],
|
|
160
|
+
},
|
|
161
|
+
fontWeights: {
|
|
162
|
+
regular: [{ label: '字重', cssProp: 'font-weight', value: '400' }],
|
|
163
|
+
bold: [{ label: '字重', cssProp: 'font-weight', token: '--font-bold', value: '700' }],
|
|
164
|
+
},
|
|
165
|
+
icons: {
|
|
166
|
+
default: [
|
|
167
|
+
{ label: '默认图标', cssProp: 'icon-name', value: 'tag-01-stroked' },
|
|
168
|
+
{ label: '图标颜色', cssProp: 'color', value: 'inherit (继承文字颜色)' },
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
};
|