@teamix-evo/ui 0.5.0 → 0.6.0

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.
Files changed (63) hide show
  1. package/package.json +19 -17
  2. package/src/components/alert/index.tsx +1 -1
  3. package/src/components/alert-dialog/index.tsx +17 -24
  4. package/src/components/alert-dialog/meta.md +102 -8
  5. package/src/components/alert-dialog/stories.tsx +117 -7
  6. package/src/components/avatar/index.tsx +1 -1
  7. package/src/components/badge/index.tsx +1 -1
  8. package/src/components/button/index.tsx +3 -31
  9. package/src/components/button/meta.md +24 -13
  10. package/src/components/button/stories.tsx +24 -12
  11. package/src/components/button-group/meta.md +6 -9
  12. package/src/components/button-group/stories.tsx +2 -6
  13. package/src/components/calendar/index.tsx +12 -7
  14. package/src/components/cascader-select/index.tsx +1 -1
  15. package/src/components/checkbox/index.tsx +1 -1
  16. package/src/components/combobox/index.tsx +54 -10
  17. package/src/components/combobox/meta.md +3 -5
  18. package/src/components/combobox/stories.tsx +104 -25
  19. package/src/components/data-table/index.tsx +10 -5
  20. package/src/components/data-table/stories.tsx +4 -1
  21. package/src/components/date-picker/index.tsx +25 -2
  22. package/src/components/field/index.tsx +1 -1
  23. package/src/components/filter-bar/index.tsx +1 -1
  24. package/src/components/float-button/meta.md +3 -15
  25. package/src/components/icon/index.tsx +3 -4
  26. package/src/components/icon/meta.md +1 -2
  27. package/src/components/input/index.tsx +11 -3
  28. package/src/components/input-group/index.tsx +33 -23
  29. package/src/components/input-group/meta.md +15 -0
  30. package/src/components/input-group/stories.tsx +14 -0
  31. package/src/components/input-ip/index.tsx +1 -1
  32. package/src/components/input-number/index.tsx +5 -5
  33. package/src/components/item/meta.md +10 -42
  34. package/src/components/item/stories.tsx +12 -44
  35. package/src/components/radio-group/index.tsx +1 -1
  36. package/src/components/rate/index.tsx +3 -3
  37. package/src/components/select/index.tsx +2 -2
  38. package/src/components/skeleton/index.tsx +1 -1
  39. package/src/components/skeleton/meta.md +6 -6
  40. package/src/components/skeleton/stories.tsx +8 -8
  41. package/src/components/slider/index.tsx +27 -1
  42. package/src/components/sonner/index.tsx +43 -40
  43. package/src/components/sonner/meta.md +84 -68
  44. package/src/components/sonner/stories.tsx +122 -83
  45. package/src/components/spinner/index.tsx +170 -0
  46. package/src/components/spinner/meta.md +27 -1
  47. package/src/components/spinner/stories.tsx +23 -0
  48. package/src/components/steps/index.tsx +5 -1
  49. package/src/components/switch/index.tsx +1 -1
  50. package/src/components/table/index.tsx +6 -2
  51. package/src/components/tag/index.tsx +14 -0
  52. package/src/components/tag/meta.md +1 -0
  53. package/src/components/tag/stories.tsx +13 -0
  54. package/src/components/textarea/index.tsx +1 -1
  55. package/src/components/textarea/stories.tsx +1 -1
  56. package/src/components/time-picker/index.tsx +3 -1
  57. package/src/components/toggle/index.tsx +1 -1
  58. package/src/components/tooltip/index.tsx +5 -1
  59. package/src/components/tooltip/meta.md +13 -28
  60. package/src/components/tooltip/stories.tsx +11 -28
  61. package/src/components/transfer/index.tsx +12 -10
  62. package/src/components/tree-select/index.tsx +1 -1
  63. package/LICENSE +0 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamix-evo/ui",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Source-injected UI components for Teamix Evo (shadcn-based, antd capabilities)",
5
5
  "type": "module",
6
6
  "files": [
@@ -9,6 +9,19 @@
9
9
  "src",
10
10
  "README.md"
11
11
  ],
12
+ "scripts": {
13
+ "validate": "tsx scripts/validate-entries.ts",
14
+ "gen:meta": "tsx scripts/generate-meta.ts",
15
+ "test": "echo 'validate only' && pnpm validate",
16
+ "typecheck": "tsc --noEmit",
17
+ "lint": "eslint .",
18
+ "build": "echo 'pure resource package, no build needed'",
19
+ "gen:theme-overrides": "tsx .storybook/gen-theme-overrides.ts",
20
+ "storybook": "pnpm gen:theme-overrides && tsx .storybook/gen-theme-overrides.ts --watch & storybook dev -p 6006",
21
+ "build-storybook": "pnpm gen:theme-overrides && storybook build",
22
+ "compare": "tsx compare/start.ts",
23
+ "compare:matrix": "tsx compare/scripts/extract-styles-matrix.ts && tsx compare/scripts/generate-style-mapping.ts"
24
+ },
12
25
  "peerDependencies": {
13
26
  "react": ">=18",
14
27
  "react-dom": ">=18"
@@ -20,6 +33,9 @@
20
33
  "@storybook/react-vite": "^10.4.1",
21
34
  "@tailwindcss/vite": "^4",
22
35
  "@tanstack/react-table": "^8",
36
+ "@teamix-evo/eslint-config": "workspace:*",
37
+ "@teamix-evo/registry": "workspace:*",
38
+ "@teamix-evo/tokens": "workspace:^",
23
39
  "@types/node": "^20.0.0",
24
40
  "@types/react": "^18.3.0",
25
41
  "@types/react-dom": "^18.3.0",
@@ -50,10 +66,7 @@
50
66
  "vaul": "^1",
51
67
  "vite": "^5.4.0",
52
68
  "vite-tsconfig-paths": "^6.1.1",
53
- "zod": "^3",
54
- "@teamix-evo/eslint-config": "0.2.3",
55
- "@teamix-evo/tokens": "^0.7.0",
56
- "@teamix-evo/registry": "0.7.0"
69
+ "zod": "^3"
57
70
  },
58
71
  "publishConfig": {
59
72
  "access": "public",
@@ -66,16 +79,5 @@
66
79
  "@dnd-kit/utilities": "^3",
67
80
  "@tanstack/react-virtual": "^3.13.26",
68
81
  "react-colorful": "^5.7.0"
69
- },
70
- "scripts": {
71
- "validate": "tsx scripts/validate-entries.ts",
72
- "gen:meta": "tsx scripts/generate-meta.ts",
73
- "test": "echo 'validate only' && pnpm validate",
74
- "typecheck": "tsc --noEmit",
75
- "lint": "eslint .",
76
- "build": "echo 'pure resource package, no build needed'",
77
- "gen:theme-overrides": "tsx .storybook/gen-theme-overrides.ts",
78
- "storybook": "pnpm gen:theme-overrides && storybook dev -p 6006",
79
- "build-storybook": "pnpm gen:theme-overrides && storybook build"
80
82
  }
81
- }
83
+ }
@@ -122,7 +122,7 @@ function Alert({
122
122
  <span
123
123
  data-slot="alert-icon"
124
124
  className={cn(
125
- 'inline-flex shrink-0',
125
+ 'inline-flex shrink-0 group-has-data-[slot=alert-title]/alert:mt-0.5',
126
126
  ICON_TONE_CLASS[resolvedVariant],
127
127
  )}
128
128
  >
@@ -2,14 +2,14 @@
2
2
  * 确认对话框 AlertDialog
3
3
  *
4
4
  * 模态确认弹窗,要求用户对破坏性 / 不可撤销操作进行显式确认,基于 Radix AlertDialog 原语。
5
- * 与 Dialog 共享 size scale 与视觉规范(圆角 / padding / 分隔线),区别在于强制焦点陷阱、
5
+ * 与 Dialog 共享 size scale 与视觉规范(圆角 / padding),区别在于强制焦点陷阱、
6
6
  * 按钮二选一语义、不允许通过外部点击关闭。
7
7
  *
8
8
  * 视觉规范:
9
9
  * - 外层容器圆角走主题默认(`rounded-md`),自身不带 padding,由 Header / Body / Footer 各自控制
10
- * - Header 区:`pt-3 pr-14 pb-3 pl-5`,底部 1px 分隔线默认 `border-border`(紧凑模式居中、宽屏模式左对齐)
11
- * - Body 区:`px-5 pt-4 pb-5`,默认字号 14px、颜色 muted-foreground
12
- * - Footer 区:`px-5 py-4`,顶部分隔线默认透明
10
+ * - Header 区:`px-5 pt-5`,icon + 标题同行居中对齐(gap-2),无分隔线
11
+ * - Body 区:`pr-5 pl-11 pt-3`,左侧与 Title 对齐(跳过 icon + gap)
12
+ * - Footer 区:`px-5 pt-4 pb-5`,无分隔线,右对齐
13
13
  *
14
14
  * @when
15
15
  * - 删除操作的二次确认
@@ -113,9 +113,8 @@ function AlertDialogContent({
113
113
  /**
114
114
  * AlertDialog Header 容器。
115
115
  *
116
- * 视觉规范:`pt-3 pr-14 pb-3 pl-5`,底部 1px 分隔线默认 `border-border`,可通过
117
- * `className="border-transparent"` 关闭。默认居中布局(紧凑确认弹窗惯例);当 size>=md
118
- * 自动切换为左对齐 + media 横置布局。
116
+ * 视觉规范:左对齐、图标与标题同行、无底部分隔线。
117
+ * AlertDialogMedia 时自动切换为 icon + title 单行布局。
119
118
  */
120
119
  function AlertDialogHeader({
121
120
  className,
@@ -124,10 +123,7 @@ function AlertDialogHeader({
124
123
  return (
125
124
  <div
126
125
  data-slot="alert-dialog-header"
127
- className={cn(
128
- 'grid grid-rows-[auto_1fr] place-items-center gap-1.5 border-b border-border pt-3 pr-14 pb-3 pl-5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=md]/alert-dialog-content:place-items-start sm:group-data-[size=md]/alert-dialog-content:text-left sm:group-data-[size=md]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr] sm:group-data-[size=lg]/alert-dialog-content:place-items-start sm:group-data-[size=lg]/alert-dialog-content:text-left sm:group-data-[size=lg]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr] sm:group-data-[size=xl]/alert-dialog-content:place-items-start sm:group-data-[size=xl]/alert-dialog-content:text-left sm:group-data-[size=xl]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]',
129
- className,
130
- )}
126
+ className={cn('flex items-center gap-2 px-5 pt-5', className)}
131
127
  {...props}
132
128
  />
133
129
  );
@@ -136,14 +132,14 @@ function AlertDialogHeader({
136
132
  /**
137
133
  * AlertDialog 内容区(Body)。
138
134
  *
139
- * 视觉规范:`px-5 pt-4 pb-5`,默认字号 14px、颜色 muted-foreground。
135
+ * 视觉规范:`pr-5 pl-11 pt-3`,左侧与 Title 对齐(跳过 icon + gap)。
140
136
  * 用于在 Header / Footer 之外承载补充说明、列表等正文内容。
141
137
  */
142
138
  function AlertDialogBody({ className, ...props }: React.ComponentProps<'div'>) {
143
139
  return (
144
140
  <div
145
141
  data-slot="alert-dialog-body"
146
- className={cn('px-5 pt-4 pb-5 text-sm text-muted-foreground', className)}
142
+ className={cn('pr-5 pl-11 pt-3', className)}
147
143
  {...props}
148
144
  />
149
145
  );
@@ -152,8 +148,8 @@ function AlertDialogBody({ className, ...props }: React.ComponentProps<'div'>) {
152
148
  /**
153
149
  * Footer 容器。
154
150
  *
155
- * 视觉规范:`px-5 py-4`,顶部分隔线默认透明。
156
- * sm size 紧凑模式下按钮均分两列;其他 size 在 sm 断点以上水平右对齐。
151
+ * 视觉规范:`px-5 pt-4 pb-5`,无顶部分隔线。
152
+ * 移动端纵向堆叠(flex-col-reverse),桌面端水平右对齐。
157
153
  */
158
154
  function AlertDialogFooter({
159
155
  className,
@@ -163,7 +159,7 @@ function AlertDialogFooter({
163
159
  <div
164
160
  data-slot="alert-dialog-footer"
165
161
  className={cn(
166
- 'flex flex-col-reverse gap-2 border-t border-transparent px-5 py-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end',
162
+ 'flex flex-col-reverse gap-2 px-5 pt-4 pb-5 sm:flex-row sm:justify-end',
167
163
  className,
168
164
  )}
169
165
  {...props}
@@ -172,9 +168,9 @@ function AlertDialogFooter({
172
168
  }
173
169
 
174
170
  /**
175
- * 标题前的图标 / 媒体槽,用于 destructive / warning 视觉强化。
171
+ * 标题前的图标 / 媒体槽,用于 destructive / warning / info 视觉强化。
176
172
  *
177
- * 紧凑模式(size=sm)下置顶居中;宽屏模式(size>=md)下置于标题左侧。
173
+ * 无背景容器,图标与标题垂直居中对齐。
178
174
  */
179
175
  function AlertDialogMedia({
180
176
  className,
@@ -184,7 +180,7 @@ function AlertDialogMedia({
184
180
  <div
185
181
  data-slot="alert-dialog-media"
186
182
  className={cn(
187
- "mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=md]/alert-dialog-content:row-span-2 sm:group-data-[size=lg]/alert-dialog-content:row-span-2 sm:group-data-[size=xl]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
183
+ "inline-flex shrink-0 items-center justify-center *:[svg:not([class*='size-'])]:size-4",
188
184
  className,
189
185
  )}
190
186
  {...props}
@@ -199,10 +195,7 @@ function AlertDialogTitle({
199
195
  return (
200
196
  <AlertDialogPrimitive.Title
201
197
  data-slot="alert-dialog-title"
202
- className={cn(
203
- 'text-sm leading-5 font-medium text-foreground sm:group-data-[size=md]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2 sm:group-data-[size=lg]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2 sm:group-data-[size=xl]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2',
204
- className,
205
- )}
198
+ className={cn('text-sm font-semibold text-foreground', className)}
206
199
  {...props}
207
200
  />
208
201
  );
@@ -216,7 +209,7 @@ function AlertDialogDescription({
216
209
  <AlertDialogPrimitive.Description
217
210
  data-slot="alert-dialog-description"
218
211
  className={cn(
219
- 'text-sm text-balance text-muted-foreground md:text-pretty *:[a]:text-primary *:[a]:hover:text-primary/80',
212
+ 'text-xs leading-normal text-balance text-muted-foreground md:text-pretty *:[a]:text-primary *:[a]:hover:text-primary/80',
220
213
  className,
221
214
  )}
222
215
  {...props}
@@ -6,13 +6,13 @@
6
6
 
7
7
  确认对话框 AlertDialog
8
8
  模态确认弹窗,要求用户对破坏性 / 不可撤销操作进行显式确认,基于 Radix AlertDialog 原语。
9
- 与 Dialog 共享 size scale 与视觉规范(圆角 / padding / 分隔线),区别在于强制焦点陷阱、
9
+ 与 Dialog 共享 size scale 与视觉规范(圆角 / padding),区别在于强制焦点陷阱、
10
10
  按钮二选一语义、不允许通过外部点击关闭。
11
11
  视觉规范:
12
12
  - 外层容器圆角走主题默认(`rounded-md`),自身不带 padding,由 Header / Body / Footer 各自控制
13
- - Header 区:`pt-3 pr-14 pb-3 pl-5`,底部 1px 分隔线默认 `border-border`(紧凑模式居中、宽屏模式左对齐)
14
- - Body 区:`px-5 pt-4 pb-5`,默认字号 14px、颜色 muted-foreground
15
- - Footer 区:`px-5 py-4`,顶部分隔线默认透明
13
+ - Header 区:`px-5 pt-5`,icon + 标题同行居中对齐(gap-2),无分隔线
14
+ - Body 区:`pr-5 pl-11 pt-3`,左侧与 Title 对齐(跳过 icon + gap)
15
+ - Footer 区:`px-5 pt-4 pb-5`,无分隔线,右对齐
16
16
 
17
17
  ## 使用场景
18
18
 
@@ -43,11 +43,16 @@
43
43
  </AlertDialogTrigger>
44
44
  <AlertDialogContent size={size}>
45
45
  <AlertDialogHeader>
46
+ <AlertDialogMedia>
47
+ <InfoFilledIcon className="text-info" />
48
+ </AlertDialogMedia>
46
49
  <AlertDialogTitle>确认操作?</AlertDialogTitle>
50
+ </AlertDialogHeader>
51
+ <AlertDialogBody>
47
52
  <AlertDialogDescription>
48
- 当前 size={size}。sm 紧凑居中,md/lg 切换为左对齐 + media 横置。
53
+ 当前 size={size}。图标与标题同行,描述文字在 body 区。
49
54
  </AlertDialogDescription>
50
- </AlertDialogHeader>
55
+ </AlertDialogBody>
51
56
  <AlertDialogFooter>
52
57
  <AlertDialogCancel>取消</AlertDialogCancel>
53
58
  <AlertDialogAction>确认</AlertDialogAction>
@@ -70,13 +75,15 @@
70
75
  <AlertDialogContent size="md">
71
76
  <AlertDialogHeader>
72
77
  <AlertDialogMedia>
73
- <TriangleAlertIcon className="text-warning" />
78
+ <WarningFilledIcon className="text-warning" />
74
79
  </AlertDialogMedia>
75
80
  <AlertDialogTitle>操作确认</AlertDialogTitle>
81
+ </AlertDialogHeader>
82
+ <AlertDialogBody>
76
83
  <AlertDialogDescription>
77
84
  你确定要执行此操作吗?该操作将影响所有相关配置,请谨慎操作。
78
85
  </AlertDialogDescription>
79
- </AlertDialogHeader>
86
+ </AlertDialogBody>
80
87
  <AlertDialogFooter>
81
88
  <AlertDialogCancel>取消</AlertDialogCancel>
82
89
  <AlertDialogAction>确认</AlertDialogAction>
@@ -84,3 +91,90 @@
84
91
  </AlertDialogContent>
85
92
  </AlertDialog>
86
93
  ```
94
+
95
+ ### Success
96
+
97
+ 成功提示 — 操作完成后的确认。
98
+
99
+ ```tsx
100
+ <AlertDialog>
101
+ <AlertDialogTrigger asChild>
102
+ <Button>提交</Button>
103
+ </AlertDialogTrigger>
104
+ <AlertDialogContent>
105
+ <AlertDialogHeader>
106
+ <AlertDialogMedia>
107
+ <SuccessFilledIcon className="text-success" />
108
+ </AlertDialogMedia>
109
+ <AlertDialogTitle>提交成功</AlertDialogTitle>
110
+ </AlertDialogHeader>
111
+ <AlertDialogBody>
112
+ <AlertDialogDescription>
113
+ 你的申请已成功提交,审核结果将在 1-3 个工作日内通知。
114
+ </AlertDialogDescription>
115
+ </AlertDialogBody>
116
+ <AlertDialogFooter>
117
+ <AlertDialogAction>知道了</AlertDialogAction>
118
+ </AlertDialogFooter>
119
+ </AlertDialogContent>
120
+ </AlertDialog>
121
+ ```
122
+
123
+ ### Notice
124
+
125
+ 通知提示 — 普通信息告知。
126
+
127
+ ```tsx
128
+ <AlertDialog>
129
+ <AlertDialogTrigger asChild>
130
+ <Button variant="outline">查看通知</Button>
131
+ </AlertDialogTrigger>
132
+ <AlertDialogContent>
133
+ <AlertDialogHeader>
134
+ <AlertDialogMedia>
135
+ <InfoFilledIcon className="text-info" />
136
+ </AlertDialogMedia>
137
+ <AlertDialogTitle>系统升级通知</AlertDialogTitle>
138
+ </AlertDialogHeader>
139
+ <AlertDialogBody>
140
+ <AlertDialogDescription>
141
+ 系统将于今晚 22:00 进行维护升级,预计持续 2
142
+ 小时,届时服务将暂时不可用。
143
+ </AlertDialogDescription>
144
+ </AlertDialogBody>
145
+ <AlertDialogFooter>
146
+ <AlertDialogCancel>稍后再说</AlertDialogCancel>
147
+ <AlertDialogAction>我知道了</AlertDialogAction>
148
+ </AlertDialogFooter>
149
+ </AlertDialogContent>
150
+ </AlertDialog>
151
+ ```
152
+
153
+ ### Warning
154
+
155
+ 警告提示 — 高风险操作前的确认。
156
+
157
+ ```tsx
158
+ <AlertDialog>
159
+ <AlertDialogTrigger asChild>
160
+ <Button variant="outline">重置配置</Button>
161
+ </AlertDialogTrigger>
162
+ <AlertDialogContent>
163
+ <AlertDialogHeader>
164
+ <AlertDialogMedia>
165
+ <WarningFilledIcon className="text-warning" />
166
+ </AlertDialogMedia>
167
+ <AlertDialogTitle>确认重置?</AlertDialogTitle>
168
+ </AlertDialogHeader>
169
+ <AlertDialogBody>
170
+ <AlertDialogDescription>
171
+ 重置后所有自定义配置将恢复为默认值,已保存的预设方案不受影响。
172
+ </AlertDialogDescription>
173
+ </AlertDialogBody>
174
+ <AlertDialogFooter>
175
+ <AlertDialogCancel>取消</AlertDialogCancel>
176
+ <AlertDialogAction>确认重置</AlertDialogAction>
177
+ </AlertDialogFooter>
178
+ </AlertDialogContent>
179
+ </AlertDialog>
180
+ ```
@@ -3,6 +3,7 @@ import * as React from 'react';
3
3
  import {
4
4
  AlertDialog,
5
5
  AlertDialogAction,
6
+ AlertDialogBody,
6
7
  AlertDialogCancel,
7
8
  AlertDialogContent,
8
9
  AlertDialogDescription,
@@ -13,7 +14,12 @@ import {
13
14
  AlertDialogTrigger,
14
15
  } from './index';
15
16
  import { Button } from '@/components/button';
16
- import { TriangleAlertIcon } from 'lucide-react';
17
+ import {
18
+ ErrorFilledIcon,
19
+ InfoFilledIcon,
20
+ SuccessFilledIcon,
21
+ WarningFilledIcon,
22
+ } from '@/components/icon';
17
23
 
18
24
  const meta = {
19
25
  title: '反馈 · Feedback/AlertDialog 确认对话框',
@@ -43,11 +49,16 @@ export const Default: Story = {
43
49
  </AlertDialogTrigger>
44
50
  <AlertDialogContent>
45
51
  <AlertDialogHeader>
52
+ <AlertDialogMedia>
53
+ <ErrorFilledIcon className="text-destructive" />
54
+ </AlertDialogMedia>
46
55
  <AlertDialogTitle>确认删除?</AlertDialogTitle>
56
+ </AlertDialogHeader>
57
+ <AlertDialogBody>
47
58
  <AlertDialogDescription>
48
59
  此操作不可撤销,将永久删除该账户和所有相关数据。
49
60
  </AlertDialogDescription>
50
- </AlertDialogHeader>
61
+ </AlertDialogBody>
51
62
  <AlertDialogFooter>
52
63
  <AlertDialogCancel>取消</AlertDialogCancel>
53
64
  <AlertDialogAction variant="destructive">确认删除</AlertDialogAction>
@@ -69,11 +80,16 @@ export const Sizes: Story = {
69
80
  </AlertDialogTrigger>
70
81
  <AlertDialogContent size={size}>
71
82
  <AlertDialogHeader>
83
+ <AlertDialogMedia>
84
+ <InfoFilledIcon className="text-info" />
85
+ </AlertDialogMedia>
72
86
  <AlertDialogTitle>确认操作?</AlertDialogTitle>
87
+ </AlertDialogHeader>
88
+ <AlertDialogBody>
73
89
  <AlertDialogDescription>
74
- 当前 size={size}。sm 紧凑居中,md/lg 切换为左对齐 + media 横置。
90
+ 当前 size={size}。图标与标题同行,描述文字在 body 区。
75
91
  </AlertDialogDescription>
76
- </AlertDialogHeader>
92
+ </AlertDialogBody>
77
93
  <AlertDialogFooter>
78
94
  <AlertDialogCancel>取消</AlertDialogCancel>
79
95
  <AlertDialogAction>确认</AlertDialogAction>
@@ -96,13 +112,15 @@ export const WithMedia: Story = {
96
112
  <AlertDialogContent size="md">
97
113
  <AlertDialogHeader>
98
114
  <AlertDialogMedia>
99
- <TriangleAlertIcon className="text-warning" />
115
+ <WarningFilledIcon className="text-warning" />
100
116
  </AlertDialogMedia>
101
117
  <AlertDialogTitle>操作确认</AlertDialogTitle>
118
+ </AlertDialogHeader>
119
+ <AlertDialogBody>
102
120
  <AlertDialogDescription>
103
121
  你确定要执行此操作吗?该操作将影响所有相关配置,请谨慎操作。
104
122
  </AlertDialogDescription>
105
- </AlertDialogHeader>
123
+ </AlertDialogBody>
106
124
  <AlertDialogFooter>
107
125
  <AlertDialogCancel>取消</AlertDialogCancel>
108
126
  <AlertDialogAction>确认</AlertDialogAction>
@@ -112,6 +130,93 @@ export const WithMedia: Story = {
112
130
  ),
113
131
  };
114
132
 
133
+ /** 成功提示 — 操作完成后的确认。 */
134
+ export const Success: Story = {
135
+ name: '成功提示',
136
+ render: () => (
137
+ <AlertDialog>
138
+ <AlertDialogTrigger asChild>
139
+ <Button>提交</Button>
140
+ </AlertDialogTrigger>
141
+ <AlertDialogContent>
142
+ <AlertDialogHeader>
143
+ <AlertDialogMedia>
144
+ <SuccessFilledIcon className="text-success" />
145
+ </AlertDialogMedia>
146
+ <AlertDialogTitle>提交成功</AlertDialogTitle>
147
+ </AlertDialogHeader>
148
+ <AlertDialogBody>
149
+ <AlertDialogDescription>
150
+ 你的申请已成功提交,审核结果将在 1-3 个工作日内通知。
151
+ </AlertDialogDescription>
152
+ </AlertDialogBody>
153
+ <AlertDialogFooter>
154
+ <AlertDialogAction>知道了</AlertDialogAction>
155
+ </AlertDialogFooter>
156
+ </AlertDialogContent>
157
+ </AlertDialog>
158
+ ),
159
+ };
160
+
161
+ /** 通知提示 — 普通信息告知。 */
162
+ export const Notice: Story = {
163
+ name: '通知提示',
164
+ render: () => (
165
+ <AlertDialog>
166
+ <AlertDialogTrigger asChild>
167
+ <Button variant="outline">查看通知</Button>
168
+ </AlertDialogTrigger>
169
+ <AlertDialogContent>
170
+ <AlertDialogHeader>
171
+ <AlertDialogMedia>
172
+ <InfoFilledIcon className="text-info" />
173
+ </AlertDialogMedia>
174
+ <AlertDialogTitle>系统升级通知</AlertDialogTitle>
175
+ </AlertDialogHeader>
176
+ <AlertDialogBody>
177
+ <AlertDialogDescription>
178
+ 系统将于今晚 22:00 进行维护升级,预计持续 2
179
+ 小时,届时服务将暂时不可用。
180
+ </AlertDialogDescription>
181
+ </AlertDialogBody>
182
+ <AlertDialogFooter>
183
+ <AlertDialogCancel>稍后再说</AlertDialogCancel>
184
+ <AlertDialogAction>我知道了</AlertDialogAction>
185
+ </AlertDialogFooter>
186
+ </AlertDialogContent>
187
+ </AlertDialog>
188
+ ),
189
+ };
190
+
191
+ /** 警告提示 — 高风险操作前的确认。 */
192
+ export const Warning: Story = {
193
+ name: '警告提示',
194
+ render: () => (
195
+ <AlertDialog>
196
+ <AlertDialogTrigger asChild>
197
+ <Button variant="outline">重置配置</Button>
198
+ </AlertDialogTrigger>
199
+ <AlertDialogContent>
200
+ <AlertDialogHeader>
201
+ <AlertDialogMedia>
202
+ <WarningFilledIcon className="text-warning" />
203
+ </AlertDialogMedia>
204
+ <AlertDialogTitle>确认重置?</AlertDialogTitle>
205
+ </AlertDialogHeader>
206
+ <AlertDialogBody>
207
+ <AlertDialogDescription>
208
+ 重置后所有自定义配置将恢复为默认值,已保存的预设方案不受影响。
209
+ </AlertDialogDescription>
210
+ </AlertDialogBody>
211
+ <AlertDialogFooter>
212
+ <AlertDialogCancel>取消</AlertDialogCancel>
213
+ <AlertDialogAction>确认重置</AlertDialogAction>
214
+ </AlertDialogFooter>
215
+ </AlertDialogContent>
216
+ </AlertDialog>
217
+ ),
218
+ };
219
+
115
220
  /** 异步确认 — onAction 返回 Promise,loading 期间禁止关闭。 */
116
221
  export const Async: Story = {
117
222
  name: '异步确认',
@@ -139,11 +244,16 @@ export const Async: Story = {
139
244
  </AlertDialogTrigger>
140
245
  <AlertDialogContent>
141
246
  <AlertDialogHeader>
247
+ <AlertDialogMedia>
248
+ <ErrorFilledIcon className="text-destructive" />
249
+ </AlertDialogMedia>
142
250
  <AlertDialogTitle>确认删除?</AlertDialogTitle>
251
+ </AlertDialogHeader>
252
+ <AlertDialogBody>
143
253
  <AlertDialogDescription>
144
254
  onAction 返回 Promise,loading 期间无法关闭对话框。
145
255
  </AlertDialogDescription>
146
- </AlertDialogHeader>
256
+ </AlertDialogBody>
147
257
  <AlertDialogFooter>
148
258
  <AlertDialogCancel disabled={loading}>取消</AlertDialogCancel>
149
259
  <Button
@@ -89,7 +89,7 @@ function AvatarFallback({
89
89
  <AvatarPrimitive.Fallback
90
90
  data-slot="avatar-fallback"
91
91
  className={cn(
92
- 'flex size-full items-center justify-center bg-muted text-muted-foreground',
92
+ 'flex size-full items-center justify-center bg-border text-muted-foreground',
93
93
  'group-data-[shape=circle]/avatar:rounded-full group-data-[shape=square]/avatar:rounded-md',
94
94
  'group-data-[size=sm]/avatar:text-xs group-data-[size=default]/avatar:text-xs group-data-[size=lg]/avatar:text-sm',
95
95
  '[&>svg]:size-1/2',
@@ -24,7 +24,7 @@ import { cn } from '@/lib/utils';
24
24
 
25
25
  // ─── Label cva(与 v1 完全一致,保证向后兼容) ──────────────────────────
26
26
  const badgeVariants = cva(
27
- 'group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 [&>svg]:pointer-events-none [&>svg]:size-3!',
27
+ 'group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-ring/20 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 [&>svg]:pointer-events-none [&>svg]:size-3!',
28
28
  {
29
29
  variants: {
30
30
  variant: {
@@ -19,7 +19,7 @@ import { Spinner } from '@/components/spinner';
19
19
  // ─── Button cva ─────────────────────────────────────────────────────────────
20
20
  //
21
21
  // 视觉由 token 驱动,组件只用语义 utility:
22
- // - 圆角 `rounded-md`:opentrek=8px / uni-manager=2px
22
+ // - 圆角 `rounded-md`:走 --radius-md(opentrek=8px / uni-manager=2px),各变体 theme.css 驱动
23
23
  // - focus ring `ring-ring`:opentrek=品牌色 halo / uni-manager=transparent
24
24
  // - shadow:组件不写,uni-manager 通过 theme.css scoped CSS [data-slot='button'] 注入
25
25
 
@@ -39,15 +39,9 @@ const buttonVariants = cva(
39
39
  dashed:
40
40
  'border border-dashed border-input bg-card hover:bg-muted hover:text-foreground aria-expanded:bg-muted',
41
41
  ghost:
42
- 'hover:bg-accent hover:text-accent-foreground aria-expanded:bg-accent aria-expanded:text-accent-foreground',
42
+ 'hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground',
43
43
  link: 'text-primary hover:text-primary-hover',
44
44
  },
45
- // 语义色 — 与 variant 双 prop 组合
46
- color: {
47
- default: '',
48
- primary: '',
49
- destructive: '',
50
- },
51
45
  size: {
52
46
  sm: 'h-6 gap-1 px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*=size-])]:size-3',
53
47
  default:
@@ -69,24 +63,6 @@ const buttonVariants = cva(
69
63
  },
70
64
  },
71
65
  compoundVariants: [
72
- // ─── color × variant ─────────────────────────────────────────────
73
- {
74
- variant: 'outline',
75
- color: 'destructive',
76
- className:
77
- 'border-destructive text-destructive hover:bg-destructive/10 hover:text-destructive',
78
- },
79
- {
80
- variant: 'ghost',
81
- color: 'destructive',
82
- className:
83
- 'text-destructive hover:bg-destructive/10 hover:text-destructive',
84
- },
85
- {
86
- variant: 'link',
87
- color: 'destructive',
88
- className: 'text-destructive hover:text-destructive-hover',
89
- },
90
66
  // ─── ghost / link padding 收紧 ─────────────────────────────────────
91
67
  { variant: 'ghost', size: 'sm', className: 'px-1' },
92
68
  { variant: 'ghost', size: 'default', className: 'px-1' },
@@ -97,7 +73,6 @@ const buttonVariants = cva(
97
73
  ],
98
74
  defaultVariants: {
99
75
  variant: 'default',
100
- color: 'default',
101
76
  size: 'default',
102
77
  shape: 'default',
103
78
  block: false,
@@ -115,6 +90,7 @@ export type ButtonVariant =
115
90
  | 'dashed'
116
91
  | 'ghost'
117
92
  | 'link';
93
+ /** @deprecated 已移除,保留类型避免破坏性变更 */
118
94
  export type ButtonColor = 'default' | 'primary' | 'destructive';
119
95
  export type ButtonSize =
120
96
  | 'sm'
@@ -132,8 +108,6 @@ export interface ButtonProps
132
108
  VariantProps<typeof buttonVariants> {
133
109
  /** 视觉风格。 @default default */
134
110
  variant?: ButtonVariant;
135
- /** 语义色,与 variant 双 prop 组合。 @default default */
136
- color?: ButtonColor;
137
111
  /** 尺寸。 @default default */
138
112
  size?: ButtonSize;
139
113
  /** 形状。circle/square 为等宽等高,适合纯图标。 @default default */
@@ -151,7 +125,6 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
151
125
  {
152
126
  className,
153
127
  variant,
154
- color,
155
128
  size,
156
129
  shape,
157
130
  block,
@@ -176,7 +149,6 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
176
149
  className={cn(
177
150
  buttonVariants({
178
151
  variant,
179
- color,
180
152
  size,
181
153
  shape,
182
154
  block,