@teamix-evo/ui 0.1.1 → 0.3.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 (295) hide show
  1. package/README.md +184 -184
  2. package/manifest.json +680 -492
  3. package/package.json +20 -10
  4. package/src/components/accordion/accordion.meta.md +5 -4
  5. package/src/components/accordion/accordion.stories.tsx +14 -9
  6. package/src/components/accordion/accordion.tsx +104 -8
  7. package/src/components/affix/affix.meta.md +20 -2
  8. package/src/components/affix/affix.stories.tsx +102 -25
  9. package/src/components/affix/affix.tsx +79 -9
  10. package/src/components/alert/alert.meta.md +44 -13
  11. package/src/components/alert/alert.stories.tsx +66 -21
  12. package/src/components/alert/alert.tsx +81 -34
  13. package/src/components/alert-dialog/alert-dialog.meta.md +61 -16
  14. package/src/components/alert-dialog/alert-dialog.stories.tsx +145 -3
  15. package/src/components/alert-dialog/alert-dialog.tsx +60 -13
  16. package/src/components/anchor/anchor.meta.md +8 -3
  17. package/src/components/anchor/anchor.stories.tsx +3 -3
  18. package/src/components/anchor/anchor.tsx +2 -2
  19. package/src/components/app/app.meta.md +9 -4
  20. package/src/components/app/app.stories.tsx +9 -7
  21. package/src/components/aspect-ratio/aspect-ratio.meta.md +4 -3
  22. package/src/components/aspect-ratio/aspect-ratio.stories.tsx +3 -3
  23. package/src/components/auto-complete/auto-complete.meta.md +14 -6
  24. package/src/components/auto-complete/auto-complete.stories.tsx +47 -4
  25. package/src/components/auto-complete/auto-complete.tsx +119 -71
  26. package/src/components/avatar/avatar.meta.md +6 -7
  27. package/src/components/avatar/avatar.stories.tsx +21 -3
  28. package/src/components/avatar/avatar.tsx +24 -23
  29. package/src/components/badge/badge.meta.md +10 -9
  30. package/src/components/badge/badge.stories.tsx +2 -2
  31. package/src/components/badge/badge.tsx +9 -15
  32. package/src/components/breadcrumb/breadcrumb.meta.md +27 -7
  33. package/src/components/breadcrumb/breadcrumb.stories.tsx +127 -4
  34. package/src/components/breadcrumb/breadcrumb.tsx +22 -8
  35. package/src/components/button/button.meta.md +258 -21
  36. package/src/components/button/button.stories.tsx +549 -41
  37. package/src/components/button/button.tsx +335 -33
  38. package/src/components/button/demo/as-child.tsx +24 -0
  39. package/src/components/button/demo/basic.tsx +8 -0
  40. package/src/components/button/demo/block.tsx +16 -0
  41. package/src/components/button/demo/loading.tsx +19 -0
  42. package/src/components/button/demo/shapes.tsx +18 -0
  43. package/src/components/button/demo/sizes.tsx +19 -0
  44. package/src/components/button/demo/variants.tsx +19 -0
  45. package/src/components/button/demo/with-icon.tsx +20 -0
  46. package/src/components/calendar/calendar.meta.md +13 -3
  47. package/src/components/calendar/calendar.stories.tsx +6 -6
  48. package/src/components/calendar/calendar.tsx +73 -8
  49. package/src/components/card/card.meta.md +27 -5
  50. package/src/components/card/card.stories.tsx +42 -3
  51. package/src/components/card/card.tsx +146 -63
  52. package/src/components/carousel/carousel.meta.md +4 -3
  53. package/src/components/carousel/carousel.stories.tsx +11 -6
  54. package/src/components/cascader/cascader.meta.md +47 -17
  55. package/src/components/cascader/cascader.stories.tsx +22 -10
  56. package/src/components/cascader/cascader.tsx +428 -85
  57. package/src/components/checkbox/checkbox.meta.md +75 -7
  58. package/src/components/checkbox/checkbox.stories.tsx +161 -3
  59. package/src/components/checkbox/checkbox.tsx +77 -9
  60. package/src/components/collapsible/collapsible.meta.md +14 -6
  61. package/src/components/collapsible/collapsible.stories.tsx +10 -2
  62. package/src/components/collapsible/collapsible.tsx +93 -6
  63. package/src/components/color-picker/color-picker.meta.md +12 -7
  64. package/src/components/color-picker/color-picker.stories.tsx +86 -7
  65. package/src/components/color-picker/color-picker.tsx +20 -9
  66. package/src/components/command/command.meta.md +29 -13
  67. package/src/components/command/command.stories.tsx +4 -4
  68. package/src/components/command/command.tsx +19 -8
  69. package/src/components/context-menu/context-menu.meta.md +11 -8
  70. package/src/components/context-menu/context-menu.stories.tsx +11 -3
  71. package/src/components/context-menu/context-menu.tsx +21 -8
  72. package/src/components/data-table/data-table.meta.md +6 -5
  73. package/src/components/data-table/data-table.stories.tsx +13 -6
  74. package/src/components/data-table/data-table.tsx +2 -2
  75. package/src/components/date-picker/date-picker.meta.md +88 -19
  76. package/src/components/date-picker/date-picker.stories.tsx +55 -5
  77. package/src/components/date-picker/date-picker.tsx +1489 -91
  78. package/src/components/descriptions/descriptions.meta.md +10 -5
  79. package/src/components/descriptions/descriptions.stories.tsx +3 -3
  80. package/src/components/descriptions/descriptions.tsx +22 -14
  81. package/src/components/dialog/dialog.meta.md +76 -13
  82. package/src/components/dialog/dialog.stories.tsx +182 -20
  83. package/src/components/dialog/dialog.tsx +67 -15
  84. package/src/components/dialog/imperative.tsx +252 -0
  85. package/src/components/drawer/drawer.meta.md +33 -34
  86. package/src/components/drawer/drawer.stories.tsx +29 -12
  87. package/src/components/drawer/drawer.tsx +22 -113
  88. package/src/components/dropdown-menu/dropdown-menu.meta.md +78 -10
  89. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +88 -2
  90. package/src/components/dropdown-menu/dropdown-menu.tsx +24 -10
  91. package/src/components/ellipsis/ellipsis.meta.md +87 -0
  92. package/src/components/ellipsis/ellipsis.stories.tsx +72 -0
  93. package/src/components/ellipsis/ellipsis.tsx +153 -0
  94. package/src/components/empty/empty.meta.md +9 -4
  95. package/src/components/empty/empty.stories.tsx +4 -4
  96. package/src/components/empty/empty.tsx +10 -3
  97. package/src/components/field/field.meta.md +47 -9
  98. package/src/components/field/field.stories.tsx +385 -5
  99. package/src/components/field/field.tsx +263 -35
  100. package/src/components/filter-bar/filter-bar.meta.md +92 -0
  101. package/src/components/filter-bar/filter-bar.stories.tsx +1083 -0
  102. package/src/components/filter-bar/filter-bar.tsx +568 -0
  103. package/src/components/flex/flex.meta.md +54 -6
  104. package/src/components/flex/flex.stories.tsx +107 -20
  105. package/src/components/flex/flex.tsx +27 -4
  106. package/src/components/float-button/float-button.meta.md +8 -3
  107. package/src/components/float-button/float-button.stories.tsx +9 -7
  108. package/src/components/float-button/float-button.tsx +1 -1
  109. package/src/components/form/form.meta.md +39 -17
  110. package/src/components/form/form.stories.tsx +350 -3
  111. package/src/components/form/form.tsx +101 -35
  112. package/src/components/grid/grid.meta.md +7 -2
  113. package/src/components/grid/grid.stories.tsx +6 -4
  114. package/src/components/hover-card/hover-card.meta.md +20 -9
  115. package/src/components/hover-card/hover-card.stories.tsx +34 -5
  116. package/src/components/hover-card/hover-card.tsx +51 -13
  117. package/src/components/icon/DEVELOPMENT.md +809 -0
  118. package/src/components/icon/icon.meta.md +170 -0
  119. package/src/components/icon/icon.stories.tsx +344 -0
  120. package/src/components/icon/icon.tsx +248 -0
  121. package/src/components/image/image.meta.md +9 -4
  122. package/src/components/image/image.stories.tsx +3 -3
  123. package/src/components/image/image.tsx +6 -4
  124. package/src/components/input/demo/basic.tsx +12 -0
  125. package/src/components/input/demo/clearable.tsx +21 -0
  126. package/src/components/input/demo/show-count.tsx +18 -0
  127. package/src/components/input/demo/sizes.tsx +15 -0
  128. package/src/components/input/input.meta.md +39 -33
  129. package/src/components/input/input.stories.tsx +62 -35
  130. package/src/components/input/input.tsx +97 -98
  131. package/src/components/input-group/input-group.meta.md +54 -22
  132. package/src/components/input-group/input-group.stories.tsx +49 -16
  133. package/src/components/input-group/input-group.tsx +44 -8
  134. package/src/components/input-number/input-number.meta.md +64 -7
  135. package/src/components/input-number/input-number.stories.tsx +46 -8
  136. package/src/components/input-number/input-number.tsx +99 -26
  137. package/src/components/input-otp/input-otp.meta.md +4 -3
  138. package/src/components/input-otp/input-otp.stories.tsx +3 -3
  139. package/src/components/input-otp/input-otp.tsx +1 -1
  140. package/src/components/item/item.meta.md +8 -3
  141. package/src/components/item/item.stories.tsx +8 -5
  142. package/src/components/item/item.tsx +7 -6
  143. package/src/components/kbd/kbd.meta.md +13 -4
  144. package/src/components/kbd/kbd.stories.tsx +4 -4
  145. package/src/components/kbd/kbd.tsx +10 -5
  146. package/src/components/label/label.meta.md +18 -10
  147. package/src/components/label/label.stories.tsx +64 -6
  148. package/src/components/label/label.tsx +91 -19
  149. package/src/components/masonry/masonry.meta.md +8 -3
  150. package/src/components/masonry/masonry.stories.tsx +7 -5
  151. package/src/components/masonry/masonry.tsx +1 -0
  152. package/src/components/mentions/mentions.meta.md +36 -6
  153. package/src/components/mentions/mentions.stories.tsx +120 -6
  154. package/src/components/mentions/mentions.tsx +11 -5
  155. package/src/components/menubar/menubar.meta.md +30 -12
  156. package/src/components/menubar/menubar.stories.tsx +62 -2
  157. package/src/components/menubar/menubar.tsx +9 -9
  158. package/src/components/native-select/native-select.meta.md +8 -3
  159. package/src/components/native-select/native-select.stories.tsx +8 -5
  160. package/src/components/native-select/native-select.tsx +1 -1
  161. package/src/components/navigation-menu/navigation-menu.meta.md +19 -9
  162. package/src/components/navigation-menu/navigation-menu.stories.tsx +112 -9
  163. package/src/components/navigation-menu/navigation-menu.tsx +8 -4
  164. package/src/components/notification/notification.meta.md +52 -10
  165. package/src/components/notification/notification.stories.tsx +11 -9
  166. package/src/components/notification/notification.tsx +36 -21
  167. package/src/components/page-header/DEVELOPMENT.md +842 -0
  168. package/src/components/page-header/page-header.meta.md +208 -0
  169. package/src/components/page-header/page-header.stories.tsx +421 -0
  170. package/src/components/page-header/page-header.tsx +281 -0
  171. package/src/components/pagination/pagination.meta.md +140 -37
  172. package/src/components/pagination/pagination.stories.tsx +232 -10
  173. package/src/components/pagination/pagination.tsx +355 -63
  174. package/src/components/popconfirm/popconfirm.meta.md +9 -4
  175. package/src/components/popconfirm/popconfirm.stories.tsx +3 -4
  176. package/src/components/popconfirm/popconfirm.tsx +2 -2
  177. package/src/components/popover/popover.meta.md +62 -5
  178. package/src/components/popover/popover.stories.tsx +83 -7
  179. package/src/components/popover/popover.tsx +77 -28
  180. package/src/components/progress/progress.meta.md +38 -6
  181. package/src/components/progress/progress.stories.tsx +3 -3
  182. package/src/components/progress/progress.tsx +24 -16
  183. package/src/components/radio-group/radio-group.meta.md +79 -7
  184. package/src/components/radio-group/radio-group.stories.tsx +39 -3
  185. package/src/components/radio-group/radio-group.tsx +149 -18
  186. package/src/components/rate/rate.meta.md +35 -4
  187. package/src/components/rate/rate.stories.tsx +13 -5
  188. package/src/components/rate/rate.tsx +37 -10
  189. package/src/components/resizable/resizable.meta.md +7 -4
  190. package/src/components/resizable/resizable.stories.tsx +6 -6
  191. package/src/components/resizable/resizable.tsx +1 -1
  192. package/src/components/result/result.meta.md +7 -2
  193. package/src/components/result/result.stories.tsx +4 -8
  194. package/src/components/result/result.tsx +24 -15
  195. package/src/components/scroll-area/scroll-area.meta.md +4 -3
  196. package/src/components/scroll-area/scroll-area.stories.tsx +12 -4
  197. package/src/components/scroll-area/scroll-area.tsx +3 -3
  198. package/src/components/segmented/segmented.meta.md +7 -4
  199. package/src/components/segmented/segmented.stories.tsx +37 -8
  200. package/src/components/segmented/segmented.tsx +15 -7
  201. package/src/components/select/select.meta.md +197 -52
  202. package/src/components/select/select.stories.tsx +238 -63
  203. package/src/components/select/select.tsx +718 -171
  204. package/src/components/separator/separator.meta.md +4 -3
  205. package/src/components/separator/separator.stories.tsx +3 -3
  206. package/src/components/separator/separator.tsx +3 -7
  207. package/src/components/sheet/sheet.meta.md +32 -16
  208. package/src/components/sheet/sheet.stories.tsx +116 -10
  209. package/src/components/sheet/sheet.tsx +116 -29
  210. package/src/components/sidebar/sidebar.meta.md +37 -18
  211. package/src/components/sidebar/sidebar.stories.tsx +701 -29
  212. package/src/components/sidebar/sidebar.tsx +615 -142
  213. package/src/components/skeleton/skeleton.meta.md +4 -5
  214. package/src/components/skeleton/skeleton.stories.tsx +4 -4
  215. package/src/components/skeleton/skeleton.tsx +7 -7
  216. package/src/components/slider/slider.meta.md +57 -5
  217. package/src/components/slider/slider.stories.tsx +58 -6
  218. package/src/components/slider/slider.tsx +154 -13
  219. package/src/components/sonner/sonner.meta.md +58 -7
  220. package/src/components/sonner/sonner.stories.tsx +78 -5
  221. package/src/components/sonner/sonner.tsx +137 -8
  222. package/src/components/spinner/spinner.meta.md +62 -13
  223. package/src/components/spinner/spinner.stories.tsx +66 -14
  224. package/src/components/spinner/spinner.tsx +111 -9
  225. package/src/components/statistic/statistic.meta.md +7 -2
  226. package/src/components/statistic/statistic.stories.tsx +3 -7
  227. package/src/components/statistic/statistic.tsx +5 -6
  228. package/src/components/steps/steps.meta.md +18 -4
  229. package/src/components/steps/steps.stories.tsx +43 -3
  230. package/src/components/steps/steps.tsx +15 -12
  231. package/src/components/switch/switch.meta.md +51 -5
  232. package/src/components/switch/switch.stories.tsx +6 -6
  233. package/src/components/switch/switch.tsx +109 -41
  234. package/src/components/table/table.meta.md +17 -6
  235. package/src/components/table/table.stories.tsx +10 -5
  236. package/src/components/table/table.tsx +4 -4
  237. package/src/components/tabs/tabs.meta.md +38 -25
  238. package/src/components/tabs/tabs.stories.tsx +111 -25
  239. package/src/components/tabs/tabs.tsx +125 -54
  240. package/src/components/tag/tag.meta.md +105 -40
  241. package/src/components/tag/tag.stories.tsx +189 -16
  242. package/src/components/tag/tag.tsx +222 -21
  243. package/src/components/textarea/textarea.meta.md +35 -19
  244. package/src/components/textarea/textarea.stories.tsx +32 -6
  245. package/src/components/textarea/textarea.tsx +33 -9
  246. package/src/components/time-picker/time-picker.meta.md +124 -32
  247. package/src/components/time-picker/time-picker.stories.tsx +85 -15
  248. package/src/components/time-picker/time-picker.tsx +913 -61
  249. package/src/components/timeline/timeline.meta.md +14 -6
  250. package/src/components/timeline/timeline.stories.tsx +37 -7
  251. package/src/components/timeline/timeline.tsx +35 -14
  252. package/src/components/toggle/toggle.meta.md +5 -4
  253. package/src/components/toggle/toggle.stories.tsx +4 -4
  254. package/src/components/toggle/toggle.tsx +4 -3
  255. package/src/components/toggle-group/toggle-group.meta.md +5 -4
  256. package/src/components/toggle-group/toggle-group.stories.tsx +3 -3
  257. package/src/components/toggle-group/toggle-group.tsx +2 -2
  258. package/src/components/tooltip/tooltip.meta.md +55 -5
  259. package/src/components/tooltip/tooltip.stories.tsx +42 -5
  260. package/src/components/tooltip/tooltip.tsx +81 -21
  261. package/src/components/tour/tour.meta.md +9 -4
  262. package/src/components/tour/tour.stories.tsx +3 -3
  263. package/src/components/tour/tour.tsx +4 -4
  264. package/src/components/transfer/transfer.meta.md +11 -6
  265. package/src/components/transfer/transfer.stories.tsx +4 -8
  266. package/src/components/transfer/transfer.tsx +28 -21
  267. package/src/components/tree/tree.meta.md +63 -5
  268. package/src/components/tree/tree.stories.tsx +31 -12
  269. package/src/components/tree/tree.tsx +9 -8
  270. package/src/components/tree-select/tree-select.meta.md +59 -8
  271. package/src/components/tree-select/tree-select.stories.tsx +3 -3
  272. package/src/components/tree-select/tree-select.tsx +42 -7
  273. package/src/components/typography/typography.meta.md +61 -14
  274. package/src/components/typography/typography.stories.tsx +12 -11
  275. package/src/components/typography/typography.tsx +43 -28
  276. package/src/components/upload/upload.meta.md +49 -4
  277. package/src/components/upload/upload.stories.tsx +72 -12
  278. package/src/components/upload/upload.tsx +170 -37
  279. package/src/components/watermark/watermark.meta.md +7 -2
  280. package/src/components/watermark/watermark.stories.tsx +101 -9
  281. package/src/components/watermark/watermark.tsx +1 -0
  282. package/src/hooks/use-breakpoint.ts +117 -0
  283. package/src/hooks/use-debounce-callback.ts +52 -0
  284. package/src/hooks/use-mobile.ts +23 -0
  285. package/src/stories/theme-tokens.stories.tsx +747 -0
  286. package/src/utils/trigger-input.ts +53 -0
  287. package/src/components/button-group/button-group.meta.md +0 -92
  288. package/src/components/button-group/button-group.stories.tsx +0 -90
  289. package/src/components/button-group/button-group.tsx +0 -75
  290. package/src/components/combobox/combobox.meta.md +0 -93
  291. package/src/components/combobox/combobox.stories.tsx +0 -55
  292. package/src/components/combobox/combobox.tsx +0 -130
  293. package/src/components/space/space.meta.md +0 -94
  294. package/src/components/space/space.stories.tsx +0 -94
  295. package/src/components/space/space.tsx +0 -106
@@ -5,7 +5,47 @@ import { Loader2 } from 'lucide-react';
5
5
  import { cn } from '@/utils/cn';
6
6
 
7
7
  export interface SwitchProps
8
- extends React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> {
8
+ extends Omit<
9
+ React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>,
10
+ | 'checked'
11
+ | 'defaultChecked'
12
+ | 'onCheckedChange'
13
+ | 'disabled'
14
+ | 'required'
15
+ | 'name'
16
+ | 'value'
17
+ | 'id'
18
+ > {
19
+ /**
20
+ * 受控选中状态(等价 antd `checked`)。
21
+ * 与 `defaultChecked` 二选一,不同时传。
22
+ */
23
+ checked?: boolean;
24
+ /**
25
+ * 非受控初始选中态(等价 antd `defaultChecked`)。
26
+ * @default false
27
+ */
28
+ defaultChecked?: boolean;
29
+ /**
30
+ * 选中状态变化回调 — Radix 命名,等价 antd `onChange(checked)`。
31
+ */
32
+ onCheckedChange?: (checked: boolean) => void;
33
+ /**
34
+ * 禁用整个 Switch(灰化 + 不响应交互)。`loading` 也会自动禁用。
35
+ * @default false
36
+ */
37
+ disabled?: boolean;
38
+ /**
39
+ * 表单必填 — 设置 HTML 原生 `required`,表单层校验依赖此值。
40
+ * @default false
41
+ */
42
+ required?: boolean;
43
+ /** 表单字段名(原生 `<input name>`,提交表单时使用)。 */
44
+ name?: string;
45
+ /** 表单字段值(选中时随表单提交)。 */
46
+ value?: string;
47
+ /** id 属性,配合 `<label htmlFor>` 关联标签。 */
48
+ id?: string;
9
49
  /**
10
50
  * 加载态 — 自动 `disabled`,thumb 上叠加自旋 spinner(antd 并集)。
11
51
  * @default false
@@ -16,10 +56,11 @@ export interface SwitchProps
16
56
  /** 未选中态显示的内文(antd `unCheckedChildren` 并集)。 */
17
57
  unCheckedChildren?: React.ReactNode;
18
58
  /**
19
- * 尺寸。
20
- * @default "default"
59
+ * 尺寸。`md` 与 `default` 完全等价,后者作为向后兼容别名保留;新代码请优先
60
+ * 使用 `md`,与 Button / Input / Checkbox / Radio 等表单原子组件的 size enum 一致。
61
+ * @default "md"
21
62
  */
22
- size?: 'sm' | 'default';
63
+ size?: 'sm' | 'md' | 'default';
23
64
  }
24
65
 
25
66
  const Switch = React.forwardRef<
@@ -32,66 +73,93 @@ const Switch = React.forwardRef<
32
73
  loading = false,
33
74
  checkedChildren,
34
75
  unCheckedChildren,
35
- size = 'default',
76
+ size = 'md',
36
77
  disabled,
37
78
  ...props
38
79
  },
39
80
  ref,
40
81
  ) => {
41
82
  const isSm = size === 'sm';
83
+ const hasInner = checkedChildren != null || unCheckedChildren != null;
84
+ // sm:外框 16x28(h-4 w-7)、thumb 12x12(size-3)、偏移 12px
85
+ // default:外框 20x36(h-5 w-9)、thumb 16x16(size-4)、偏移 16px
86
+ const thumbSize = isSm ? 'size-3' : 'size-4';
87
+ const spinnerSize = isSm ? 'size-2.5' : 'size-3';
88
+ const renderThumb = (extra?: string) => (
89
+ <SwitchPrimitive.Thumb
90
+ className={cn(
91
+ 'pointer-events-none flex shrink-0 items-center justify-center rounded-full bg-background shadow-lg ring-0',
92
+ thumbSize,
93
+ extra,
94
+ )}
95
+ >
96
+ {loading ? (
97
+ <Loader2
98
+ className={cn(
99
+ 'animate-spin text-muted-foreground motion-reduce:animate-none',
100
+ spinnerSize,
101
+ )}
102
+ aria-hidden="true"
103
+ />
104
+ ) : null}
105
+ </SwitchPrimitive.Thumb>
106
+ );
107
+
42
108
  return (
43
109
  <SwitchPrimitive.Root
44
110
  ref={ref}
45
111
  disabled={disabled || loading}
46
112
  className={cn(
47
- 'peer relative inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
48
- isSm ? 'h-5 w-9' : 'h-6 w-11',
113
+ 'peer group inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
114
+ hasInner
115
+ ? cn(
116
+ // 内文模式:高度固定,宽度按 thumb + 文字 + gap + padding 自适应
117
+ isSm ? 'h-4 min-w-7 gap-1' : 'h-5 min-w-9 gap-1',
118
+ )
119
+ : cn(isSm ? 'h-4 w-7' : 'h-5 w-9'),
49
120
  className,
50
121
  )}
51
122
  {...props}
52
123
  >
53
- {/* Inner labels (checkedChildren / unCheckedChildren) */}
54
- {checkedChildren != null || unCheckedChildren != null ? (
124
+ {hasInner ? (
55
125
  <>
126
+ {/* thumb 与文字以 flex order 互换位置 */}
127
+ {renderThumb('order-1 group-data-[state=checked]:order-2')}
56
128
  <span
57
129
  className={cn(
58
- 'pointer-events-none absolute select-none text-[10px] font-medium leading-none text-primary-foreground transition-opacity peer-data-[state=unchecked]:opacity-0',
59
- isSm ? 'left-1.5' : 'left-2',
130
+ 'pointer-events-none select-none font-medium leading-none',
131
+ isSm ? '' : 'text-xs',
132
+ 'order-2 group-data-[state=checked]:order-1',
133
+ 'group-data-[state=checked]:text-primary-foreground',
134
+ 'group-data-[state=unchecked]:text-muted-foreground',
135
+ // 文字外侧 padding(远离 thumb 的一侧)—— thumb 侧不加 padding,与其他 switch 一致紧贴边缘
136
+ isSm
137
+ ? 'group-data-[state=unchecked]:pr-1 group-data-[state=checked]:pl-1'
138
+ : 'group-data-[state=unchecked]:pr-1 group-data-[state=checked]:pl-1',
60
139
  )}
140
+ // sm 内文使用 10px 字号 — Tailwind 默认刻度最小 text-xs(12px)在 h-4(16-4=12 内高)容器中会超出。
141
+ // 主动选 inline style 而非 Tailwind arbitrary value(`text-[10px]`),避免 `no-arbitrary-tw-value` lint 告警。
142
+ style={isSm ? { fontSize: '10px' } : undefined}
61
143
  aria-hidden="true"
62
144
  >
63
- {checkedChildren}
64
- </span>
65
- <span
66
- className={cn(
67
- 'pointer-events-none absolute select-none text-[10px] font-medium leading-none text-muted-foreground transition-opacity peer-data-[state=checked]:opacity-0',
68
- isSm ? 'right-1.5' : 'right-2',
69
- )}
70
- aria-hidden="true"
71
- >
72
- {unCheckedChildren}
145
+ <span className="group-data-[state=unchecked]:hidden">
146
+ {checkedChildren}
147
+ </span>
148
+ <span className="group-data-[state=checked]:hidden">
149
+ {unCheckedChildren}
150
+ </span>
73
151
  </span>
74
152
  </>
75
- ) : null}
76
-
77
- <SwitchPrimitive.Thumb
78
- className={cn(
79
- 'pointer-events-none flex items-center justify-center rounded-full bg-background shadow-lg ring-0 transition-transform',
80
- isSm
81
- ? 'size-4 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0'
82
- : 'size-5 data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
83
- )}
84
- >
85
- {loading ? (
86
- <Loader2
87
- className={cn(
88
- 'animate-spin text-muted-foreground motion-reduce:animate-none',
89
- isSm ? 'size-3' : 'size-3.5',
90
- )}
91
- aria-hidden="true"
92
- />
93
- ) : null}
94
- </SwitchPrimitive.Thumb>
153
+ ) : (
154
+ renderThumb(
155
+ cn(
156
+ 'transition-transform',
157
+ isSm
158
+ ? 'data-[state=checked]:translate-x-3 data-[state=unchecked]:translate-x-0'
159
+ : 'data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0',
160
+ ),
161
+ )
162
+ )}
95
163
  </SwitchPrimitive.Root>
96
164
  );
97
165
  },
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  id: table
3
3
  name: Table
4
+ displayName: 表格
4
5
  type: component
5
6
  category: data-display
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # Table
11
+ # Table 表格
11
12
 
12
13
  基础表格 — 原生 HTML 元素薄包装。**仅视觉与可访问性骨架**(列宽 / 边框 / hover / 选中态);**无排序 / 筛选 / 分页 / 数据流**(那是 `DataTable` 的范畴)。
13
14
 
@@ -63,7 +64,13 @@ _无 — 本组件不依赖任何 npm 包。_
63
64
 
64
65
  ```tsx
65
66
  import {
66
- Table, TableHeader, TableBody, TableHead, TableRow, TableCell, TableCaption,
67
+ Table,
68
+ TableHeader,
69
+ TableBody,
70
+ TableHead,
71
+ TableRow,
72
+ TableCell,
73
+ TableCaption,
67
74
  } from '@/components/ui/table';
68
75
  import { Badge } from '@/components/ui/badge';
69
76
 
@@ -80,16 +87,20 @@ import { Badge } from '@/components/ui/badge';
80
87
  <TableBody>
81
88
  <TableRow>
82
89
  <TableCell className="font-medium">INV001</TableCell>
83
- <TableCell><Badge variant="success">已支付</Badge></TableCell>
90
+ <TableCell>
91
+ <Badge variant="success">已支付</Badge>
92
+ </TableCell>
84
93
  <TableCell>信用卡</TableCell>
85
94
  <TableCell className="text-right">¥250.00</TableCell>
86
95
  </TableRow>
87
96
  <TableRow data-state="selected">
88
97
  <TableCell className="font-medium">INV002</TableCell>
89
- <TableCell><Badge>待支付</Badge></TableCell>
98
+ <TableCell>
99
+ <Badge>待支付</Badge>
100
+ </TableCell>
90
101
  <TableCell>转账</TableCell>
91
102
  <TableCell className="text-right">¥150.00</TableCell>
92
103
  </TableRow>
93
104
  </TableBody>
94
- </Table>
105
+ </Table>;
95
106
  ```
@@ -1,4 +1,4 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import {
3
3
  Table,
4
4
  TableHeader,
@@ -15,6 +15,14 @@ const meta: Meta<typeof Table> = {
15
15
  title: '数据展示 · Data Display/Table',
16
16
  component: Table,
17
17
  tags: ['autodocs'],
18
+ parameters: {
19
+ docs: {
20
+ description: {
21
+ component:
22
+ '基础表格 — 原生 HTML 元素薄包装,仅提供视觉与可访问性骨架(列宽 / 边框 / hover / 选中态)。无排序 / 筛选 / 分页 / 数据流,复杂场景请用 `DataTable`。',
23
+ },
24
+ },
25
+ },
18
26
  };
19
27
 
20
28
  export default meta;
@@ -63,10 +71,7 @@ export const Default: Story = {
63
71
  <TableRow>
64
72
  <TableCell colSpan={3}>合计</TableCell>
65
73
  <TableCell className="text-right tabular-nums">
66
- ¥
67
- {invoices
68
- .reduce((sum, x) => sum + x.amount, 0)
69
- .toFixed(2)}
74
+ ¥{invoices.reduce((sum, x) => sum + x.amount, 0).toFixed(2)}
70
75
  </TableCell>
71
76
  </TableRow>
72
77
  </TableFooter>
@@ -9,7 +9,7 @@ const Table = React.forwardRef<
9
9
  <div className="relative w-full overflow-auto">
10
10
  <table
11
11
  ref={ref}
12
- className={cn('w-full caption-bottom text-sm', className)}
12
+ className={cn('w-full caption-bottom text-xs', className)}
13
13
  {...props}
14
14
  />
15
15
  </div>
@@ -43,7 +43,7 @@ const TableFooter = React.forwardRef<
43
43
  <tfoot
44
44
  ref={ref}
45
45
  className={cn(
46
- 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',
46
+ 'border-t border-t-border bg-muted/50 font-medium [&>tr]:last:border-b-0',
47
47
  className,
48
48
  )}
49
49
  {...props}
@@ -58,7 +58,7 @@ const TableRow = React.forwardRef<
58
58
  <tr
59
59
  ref={ref}
60
60
  className={cn(
61
- 'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
61
+ 'border-b border-b-border transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
62
62
  className,
63
63
  )}
64
64
  {...props}
@@ -102,7 +102,7 @@ const TableCaption = React.forwardRef<
102
102
  >(({ className, ...props }, ref) => (
103
103
  <caption
104
104
  ref={ref}
105
- className={cn('mt-4 text-sm text-muted-foreground', className)}
105
+ className={cn('mt-4 text-xs text-muted-foreground', className)}
106
106
  {...props}
107
107
  />
108
108
  ));
@@ -1,22 +1,24 @@
1
1
  ---
2
2
  id: tabs
3
3
  name: Tabs
4
+ displayName: 标签页
4
5
  type: component
5
- category: navigation
6
+ category: data-display
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # Tabs
11
+ # Tabs 标签页
11
12
 
12
- 标签页 — Radix Tabs + antd `type` (line/card) + `tabBarExtraContent`(`extra`) 并集。
13
- 两种风格切换:`type="card"`(shadcn 默认胶囊),`type="line"`(antd 默认下划线)。
13
+ 标签页 — Radix Tabs + antd `type`/`size`/`tabBarExtraContent` 并集,并吸收 `Segmented` 的胶囊视觉。
14
+ 两种风格切换:`variant="line"`(默认,antd 下划线),`variant="capsule"`(muted 底容器 + 选中白底 shadow,可替代 Segmented 的视图切换语义)。
14
15
 
15
16
  ## When to use
16
17
 
17
18
  - 平级内容切换(详情页的 Overview / Logs / Settings 多视图)
18
19
  - 表单分组(基本信息 / 高级配置)
19
20
  - 工具栏顶部多视图
21
+ - **`variant="capsule"`**:紧凑互斥单选(视图切换 / 时间区间 / 主题档),取代旧 Segmented 用法
20
22
 
21
23
  ## When NOT to use
22
24
 
@@ -26,13 +28,14 @@ package: "@teamix-evo/ui"
26
28
 
27
29
  ## Props
28
30
 
29
- > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。下表是 `TabsList` 的 props;`Tabs`(Root)透传 Radix `value / defaultValue / onValueChange / orientation / activationMode`。
31
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。下表是 `TabsList` 的 props;`Tabs`(Root)透传 Radix `value / defaultValue / onValueChange / orientation / activationMode`;`TabsTrigger` 也接受 `variant` / `size` 用于显式覆盖来自 List 的上下文(罕用)。
30
32
 
31
33
  <!-- auto:props:begin -->
32
34
  | 名称 | 类型 | 默认值 | 必填 | 说明 |
33
35
  | --- | --- | --- | --- | --- |
34
- | `type` | `'line' \| 'card'` | `"card"` | – | 视觉风格(antd `type` 并集)。`card` shadcn 默认胶囊;`line` antd 默认下划线。 |
35
- | `extra` | `React.ReactNode` | | – | 右侧附加内容(antd `tabBarExtraContent` 并集);仅 `type="line"` 显式支持(布局灵活)用法:把节点放进来即可,组件用 `flex justify-between` 自动撑开。 |
36
+ | `variant` | `TabsVariant` | `"line"` | – | 视觉风格(shadcn ∪ antd 并集 + 吸收 Segmented)。 - `line`:下划线风格(antd 默认),适合页面级主导航 / 大区块切换。 - `capsule`:胶囊风格(取代旧 `card`,吸收 Segmented),muted 底色 + 选中项白底 shadow,适合紧凑互斥单选(视图切换、时间区间)。 |
37
+ | `size` | `TabsSize` | `"md"` | – | 尺寸(antd `size` 并集)。三档统一驱动 trigger 的字号与 padding。 |
38
+ | `extra` | `React.ReactNode` | – | – | 右侧附加内容(antd `tabBarExtraContent` 并集);仅 `variant="line"` 显式支持(布局灵活)。 用法:把节点放进来即可,组件用 `flex justify-between` 自动撑开。 |
36
39
  <!-- auto:props:end -->
37
40
 
38
41
  ## 依赖
@@ -57,13 +60,15 @@ pnpm add @radix-ui/react-tabs@^1.1.0 class-variance-authority@^0.7.0
57
60
  ```
58
61
  <!-- auto:deps:end -->
59
62
 
60
- > 子组件:`Tabs` / `TabsList` / `TabsTrigger` / `TabsContent`。
63
+ > 子组件:`Tabs` / `TabsList` / `TabsTrigger` / `TabsContent`。`variant` / `size` 在 `TabsList` 上声明一次,会通过 context 透传给所有 `TabsTrigger`。
61
64
 
62
65
  ## AI 生成纪律
63
66
 
64
- - **`type="card"` 默认**:用于嵌入卡片内 / 紧凑场景(shadcn 胶囊视觉)
65
- - **`type="line"` 用于页面级**:大区块切换、主导航(antd 风格)
66
- - **`extra` `type="line"` 视觉对齐**:右侧附加按钮(刷新 / 新建)
67
+ - **`variant="line"` 是默认**:页面级主导航 / 大区块切换的首选(antd 视觉)
68
+ - **`variant="capsule"` 取代 Segmented**:紧凑互斥单选场景(视图切换 / 时间区间 / 主题档)直接用 capsule Tabs,**不要再新增 Segmented**(详见同名组件 meta)
69
+ - **选中态颜色固定**:line 选中文字走 `text-foreground`,capsule 选中项 `bg-background + shadow-sm + text-foreground` —— **禁止用 `bg-primary` 之类填充**(那是按钮态,不是选项态)
70
+ - **size 三档**:`sm`(text-xs / 紧凑 padding)/ `md`(text-sm,默认)/ `lg`(text-base);列表页头部建议 `md`,详情页内嵌可用 `sm`
71
+ - **`extra` 仅 `variant="line"` 视觉对齐**:右侧附加按钮(刷新 / 新建);capsule 没有右侧条带空间
67
72
  - **value 必稳定**:切换 tab 间不改变 value 字符串
68
73
  - **orientation="vertical"** 罕用,改用 Sidebar 模式
69
74
 
@@ -72,27 +77,35 @@ pnpm add @radix-ui/react-tabs@^1.1.0 class-variance-authority@^0.7.0
72
77
  ```tsx
73
78
  import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
74
79
  import { Button } from '@/components/ui/button';
75
- import { RefreshCw } from 'lucide-react';
80
+ import { LayoutGrid, List, RefreshCw } from 'lucide-react';
76
81
 
77
- // shadcn 胶囊风格
78
- <Tabs defaultValue="overview" className="w-96">
82
+ // 默认 line 下划线风格
83
+ <Tabs defaultValue="all" className="w-96">
79
84
  <TabsList>
80
- <TabsTrigger value="overview">概览</TabsTrigger>
81
- <TabsTrigger value="logs">日志</TabsTrigger>
82
- <TabsTrigger value="settings">设置</TabsTrigger>
85
+ <TabsTrigger value="all">全部</TabsTrigger>
86
+ <TabsTrigger value="active">活跃</TabsTrigger>
87
+ <TabsTrigger value="archived">已归档</TabsTrigger>
83
88
  </TabsList>
84
- <TabsContent value="overview">...</TabsContent>
85
- <TabsContent value="logs">...</TabsContent>
86
- <TabsContent value="settings">...</TabsContent>
89
+ <TabsContent value="all">全部内容</TabsContent>
87
90
  </Tabs>
88
91
 
89
- // antd 下划线风格 + extra
92
+ // 胶囊风格(吸收 Segmented):视图切换
93
+ <Tabs defaultValue="grid" className="w-fit">
94
+ <TabsList variant="capsule" size="sm">
95
+ <TabsTrigger value="grid">
96
+ <LayoutGrid className="size-4" /> 网格
97
+ </TabsTrigger>
98
+ <TabsTrigger value="list">
99
+ <List className="size-4" /> 列表
100
+ </TabsTrigger>
101
+ </TabsList>
102
+ </Tabs>
103
+
104
+ // 下划线 + 右侧 extra
90
105
  <Tabs defaultValue="all">
91
- <TabsList type="line" extra={<Button size="sm" icon={<RefreshCw />}>刷新</Button>}>
106
+ <TabsList variant="line" extra={<Button size="sm" variant="outline" icon={<RefreshCw />}>刷新</Button>}>
92
107
  <TabsTrigger value="all">全部</TabsTrigger>
93
108
  <TabsTrigger value="active">活跃</TabsTrigger>
94
- <TabsTrigger value="archived">已归档</TabsTrigger>
95
109
  </TabsList>
96
- <TabsContent value="all">...</TabsContent>
97
110
  </Tabs>
98
111
  ```
@@ -1,59 +1,143 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
2
- import { RefreshCw } from 'lucide-react';
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Calendar, LayoutGrid, List, RefreshCw } from 'lucide-react';
3
3
  import { Tabs, TabsList, TabsTrigger, TabsContent } from './tabs';
4
4
  import { Button } from '@/components/button/button';
5
5
 
6
6
  const meta: Meta<typeof TabsList> = {
7
- title: '导航 · Navigation/Tabs',
7
+ title: '数据展示 · Data Display/Tabs',
8
8
  component: TabsList,
9
9
  tags: ['autodocs'],
10
+ parameters: {
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'Tabs 标签页 —— 在多个平级视图之间切换。基于 Radix Tabs 实现 + shadcn ∪ antd 能力并集,并吸收 `Segmented` 的胶囊视觉:`variant`(`line` 下划线 / `capsule` 胶囊,后者取代旧 `card`)、`size`(对齐 antd `size`)、`extra`(对齐 antd `tabBarExtraContent`)、`asChild` 由 Radix 提供。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/tokens`,无 mock。',
15
+ },
16
+ },
17
+ },
10
18
  argTypes: {
11
- type: { control: 'inline-radio', options: ['card', 'line'] },
19
+ variant: { control: 'inline-radio', options: ['line', 'capsule'] },
20
+ size: { control: 'inline-radio', options: ['sm', 'md', 'lg'] },
12
21
  },
13
- args: { type: 'card' },
22
+ args: { variant: 'line', size: 'md' },
14
23
  };
15
24
 
16
25
  export default meta;
17
26
  type Story = StoryObj<typeof TabsList>;
18
27
 
19
- export const Card: Story = {
20
- args: { type: 'card' },
28
+ /**
29
+ * 默认 line(下划线)风格 —— antd 主导航的标准形态。
30
+ */
31
+ export const Line: Story = {
32
+ args: { variant: 'line' },
21
33
  render: (args) => (
22
- <Tabs defaultValue="overview" className="w-96">
34
+ <Tabs defaultValue="all" className="w-[480px]">
23
35
  <TabsList {...args}>
24
- <TabsTrigger value="overview">概览</TabsTrigger>
25
- <TabsTrigger value="logs">日志</TabsTrigger>
26
- <TabsTrigger value="settings">设置</TabsTrigger>
36
+ <TabsTrigger value="all">全部</TabsTrigger>
37
+ <TabsTrigger value="active">活跃</TabsTrigger>
38
+ <TabsTrigger value="archived">已归档</TabsTrigger>
27
39
  </TabsList>
28
- <TabsContent value="overview">概览内容</TabsContent>
29
- <TabsContent value="logs">日志内容</TabsContent>
30
- <TabsContent value="settings">设置内容</TabsContent>
40
+ <TabsContent value="all" className="text-sm text-muted-foreground">
41
+ 全部内容...
42
+ </TabsContent>
43
+ <TabsContent value="active" className="text-sm text-muted-foreground">
44
+ 活跃内容...
45
+ </TabsContent>
46
+ <TabsContent value="archived" className="text-sm text-muted-foreground">
47
+ 已归档内容...
48
+ </TabsContent>
31
49
  </Tabs>
32
50
  ),
33
51
  };
34
52
 
35
- export const Line: Story = {
36
- args: { type: 'line' },
53
+ /**
54
+ * 胶囊风格(吸收 Segmented)—— muted 底色容器 + 选中项白底 shadow,
55
+ * 适合视图切换、时间区间这类紧凑互斥单选场景。
56
+ */
57
+ export const Capsule: Story = {
58
+ args: { variant: 'capsule' },
37
59
  render: (args) => (
38
- <Tabs defaultValue="all" className="w-96">
60
+ <Tabs defaultValue="week" className="w-fit">
39
61
  <TabsList {...args}>
40
- <TabsTrigger value="all">全部</TabsTrigger>
41
- <TabsTrigger value="active">活跃</TabsTrigger>
42
- <TabsTrigger value="archived">已归档</TabsTrigger>
62
+ <TabsTrigger value="day">日</TabsTrigger>
63
+ <TabsTrigger value="week">周</TabsTrigger>
64
+ <TabsTrigger value="month">月</TabsTrigger>
65
+ </TabsList>
66
+ </Tabs>
67
+ ),
68
+ };
69
+
70
+ /**
71
+ * Capsule 配 icon —— 视图切换的最常见用法,完全替代 Segmented + icon。
72
+ */
73
+ export const CapsuleWithIcons: Story = {
74
+ parameters: { controls: { disable: true } },
75
+ render: () => (
76
+ <Tabs defaultValue="grid" className="w-fit">
77
+ <TabsList variant="capsule">
78
+ <TabsTrigger value="grid">
79
+ <LayoutGrid className="size-4" />
80
+ 网格
81
+ </TabsTrigger>
82
+ <TabsTrigger value="list">
83
+ <List className="size-4" />
84
+ 列表
85
+ </TabsTrigger>
86
+ <TabsTrigger value="cal">
87
+ <Calendar className="size-4" />
88
+ 日历
89
+ </TabsTrigger>
43
90
  </TabsList>
44
- <TabsContent value="all">全部内容</TabsContent>
45
- <TabsContent value="active">活跃内容</TabsContent>
46
- <TabsContent value="archived">已归档</TabsContent>
47
91
  </Tabs>
48
92
  ),
49
93
  };
50
94
 
95
+ /**
96
+ * 三档尺寸 × 两种风格 —— 用于尺寸调试。
97
+ */
98
+ export const Sizes: Story = {
99
+ parameters: { controls: { disable: true } },
100
+ render: () => (
101
+ <div className="flex flex-col gap-6">
102
+ <div className="flex flex-col gap-2">
103
+ <span className="text-xs text-muted-foreground">line · sm / md / lg</span>
104
+ {(['sm', 'md', 'lg'] as const).map((s) => (
105
+ <Tabs key={s} defaultValue="a" className="w-[360px]">
106
+ <TabsList variant="line" size={s}>
107
+ <TabsTrigger value="a">概览</TabsTrigger>
108
+ <TabsTrigger value="b">日志</TabsTrigger>
109
+ <TabsTrigger value="c">设置</TabsTrigger>
110
+ </TabsList>
111
+ </Tabs>
112
+ ))}
113
+ </div>
114
+ <div className="flex flex-col items-start gap-2">
115
+ <span className="text-xs text-muted-foreground">
116
+ capsule · sm / md / lg
117
+ </span>
118
+ {(['sm', 'md', 'lg'] as const).map((s) => (
119
+ <Tabs key={s} defaultValue="a" className="w-fit">
120
+ <TabsList variant="capsule" size={s}>
121
+ <TabsTrigger value="a">日</TabsTrigger>
122
+ <TabsTrigger value="b">周</TabsTrigger>
123
+ <TabsTrigger value="c">月</TabsTrigger>
124
+ </TabsList>
125
+ </Tabs>
126
+ ))}
127
+ </div>
128
+ </div>
129
+ ),
130
+ };
131
+
132
+ /**
133
+ * line 风格右侧 extra —— antd `tabBarExtraContent` 并集。
134
+ */
51
135
  export const WithExtra: Story = {
52
136
  parameters: { controls: { disable: true } },
53
137
  render: () => (
54
138
  <Tabs defaultValue="all" className="w-[480px]">
55
139
  <TabsList
56
- type="line"
140
+ variant="line"
57
141
  extra={
58
142
  <Button size="sm" variant="outline" icon={<RefreshCw />}>
59
143
  刷新
@@ -64,7 +148,9 @@ export const WithExtra: Story = {
64
148
  <TabsTrigger value="active">活跃</TabsTrigger>
65
149
  <TabsTrigger value="archived">已归档</TabsTrigger>
66
150
  </TabsList>
67
- <TabsContent value="all">全部内容...</TabsContent>
151
+ <TabsContent value="all" className="text-sm text-muted-foreground">
152
+ 全部内容...
153
+ </TabsContent>
68
154
  </Tabs>
69
155
  ),
70
156
  };