@teamix-evo/ui 0.2.0 → 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 (282) hide show
  1. package/README.md +184 -184
  2. package/manifest.json +680 -492
  3. package/package.json +15 -9
  4. package/src/components/accordion/accordion.meta.md +5 -9
  5. package/src/components/accordion/accordion.stories.tsx +3 -3
  6. package/src/components/accordion/accordion.tsx +104 -8
  7. package/src/components/affix/affix.meta.md +21 -12
  8. package/src/components/affix/affix.stories.tsx +101 -26
  9. package/src/components/affix/affix.tsx +79 -9
  10. package/src/components/alert/alert.meta.md +52 -26
  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 +48 -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 +10 -14
  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 +10 -14
  20. package/src/components/app/app.stories.tsx +6 -6
  21. package/src/components/aspect-ratio/aspect-ratio.meta.md +4 -8
  22. package/src/components/aspect-ratio/aspect-ratio.stories.tsx +3 -3
  23. package/src/components/auto-complete/auto-complete.meta.md +19 -20
  24. package/src/components/auto-complete/auto-complete.stories.tsx +44 -3
  25. package/src/components/auto-complete/auto-complete.tsx +119 -71
  26. package/src/components/avatar/avatar.meta.md +9 -22
  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 +14 -18
  30. package/src/components/badge/badge.stories.tsx +2 -2
  31. package/src/components/badge/badge.tsx +2 -2
  32. package/src/components/breadcrumb/breadcrumb.meta.md +29 -20
  33. package/src/components/breadcrumb/breadcrumb.stories.tsx +120 -5
  34. package/src/components/breadcrumb/breadcrumb.tsx +22 -8
  35. package/src/components/button/button.meta.md +261 -29
  36. package/src/components/button/button.stories.tsx +549 -41
  37. package/src/components/button/button.tsx +335 -33
  38. package/src/components/calendar/calendar.meta.md +19 -14
  39. package/src/components/calendar/calendar.stories.tsx +5 -5
  40. package/src/components/calendar/calendar.tsx +73 -8
  41. package/src/components/card/card.meta.md +31 -34
  42. package/src/components/card/card.stories.tsx +34 -3
  43. package/src/components/card/card.tsx +146 -63
  44. package/src/components/carousel/carousel.meta.md +10 -14
  45. package/src/components/carousel/carousel.stories.tsx +1 -1
  46. package/src/components/cascader/cascader.meta.md +43 -22
  47. package/src/components/cascader/cascader.stories.tsx +13 -2
  48. package/src/components/cascader/cascader.tsx +427 -84
  49. package/src/components/checkbox/checkbox.meta.md +74 -24
  50. package/src/components/checkbox/checkbox.stories.tsx +160 -2
  51. package/src/components/checkbox/checkbox.tsx +77 -9
  52. package/src/components/collapsible/collapsible.meta.md +7 -6
  53. package/src/components/collapsible/collapsible.stories.tsx +2 -2
  54. package/src/components/collapsible/collapsible.tsx +93 -6
  55. package/src/components/color-picker/color-picker.meta.md +16 -20
  56. package/src/components/color-picker/color-picker.stories.tsx +86 -7
  57. package/src/components/color-picker/color-picker.tsx +19 -9
  58. package/src/components/command/command.meta.md +7 -11
  59. package/src/components/command/command.stories.tsx +4 -4
  60. package/src/components/command/command.tsx +18 -7
  61. package/src/components/context-menu/context-menu.meta.md +5 -25
  62. package/src/components/context-menu/context-menu.stories.tsx +4 -4
  63. package/src/components/context-menu/context-menu.tsx +21 -8
  64. package/src/components/data-table/data-table.meta.md +14 -18
  65. package/src/components/data-table/data-table.stories.tsx +1 -1
  66. package/src/components/data-table/data-table.tsx +2 -2
  67. package/src/components/date-picker/date-picker.meta.md +90 -41
  68. package/src/components/date-picker/date-picker.stories.tsx +55 -5
  69. package/src/components/date-picker/date-picker.tsx +1489 -91
  70. package/src/components/descriptions/descriptions.meta.md +12 -16
  71. package/src/components/descriptions/descriptions.stories.tsx +2 -2
  72. package/src/components/descriptions/descriptions.tsx +22 -14
  73. package/src/components/dialog/dialog.meta.md +67 -17
  74. package/src/components/dialog/dialog.stories.tsx +182 -20
  75. package/src/components/dialog/dialog.tsx +67 -15
  76. package/src/components/dialog/imperative.tsx +252 -0
  77. package/src/components/drawer/drawer.meta.md +27 -39
  78. package/src/components/drawer/drawer.stories.tsx +29 -12
  79. package/src/components/drawer/drawer.tsx +22 -114
  80. package/src/components/dropdown-menu/dropdown-menu.meta.md +64 -24
  81. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +81 -3
  82. package/src/components/dropdown-menu/dropdown-menu.tsx +24 -10
  83. package/src/components/ellipsis/ellipsis.meta.md +87 -0
  84. package/src/components/ellipsis/ellipsis.stories.tsx +72 -0
  85. package/src/components/ellipsis/ellipsis.tsx +153 -0
  86. package/src/components/empty/empty.meta.md +10 -14
  87. package/src/components/empty/empty.stories.tsx +3 -3
  88. package/src/components/empty/empty.tsx +10 -3
  89. package/src/components/field/field.meta.md +46 -25
  90. package/src/components/field/field.stories.tsx +380 -3
  91. package/src/components/field/field.tsx +263 -35
  92. package/src/components/filter-bar/filter-bar.meta.md +92 -0
  93. package/src/components/filter-bar/filter-bar.stories.tsx +1083 -0
  94. package/src/components/filter-bar/filter-bar.tsx +568 -0
  95. package/src/components/flex/flex.meta.md +59 -20
  96. package/src/components/flex/flex.stories.tsx +65 -10
  97. package/src/components/flex/flex.tsx +27 -4
  98. package/src/components/float-button/float-button.meta.md +10 -29
  99. package/src/components/float-button/float-button.stories.tsx +6 -6
  100. package/src/components/form/form.meta.md +31 -52
  101. package/src/components/form/form.stories.tsx +350 -3
  102. package/src/components/form/form.tsx +101 -35
  103. package/src/components/grid/grid.meta.md +4 -24
  104. package/src/components/grid/grid.stories.tsx +2 -2
  105. package/src/components/hover-card/hover-card.meta.md +9 -10
  106. package/src/components/hover-card/hover-card.stories.tsx +29 -4
  107. package/src/components/hover-card/hover-card.tsx +51 -13
  108. package/src/components/icon/DEVELOPMENT.md +809 -0
  109. package/src/components/icon/icon.meta.md +170 -0
  110. package/src/components/icon/icon.stories.tsx +344 -0
  111. package/src/components/icon/icon.tsx +248 -0
  112. package/src/components/image/image.meta.md +14 -18
  113. package/src/components/image/image.stories.tsx +3 -3
  114. package/src/components/image/image.tsx +2 -0
  115. package/src/components/input/demo/sizes.tsx +2 -2
  116. package/src/components/input/input.meta.md +44 -43
  117. package/src/components/input/input.stories.tsx +62 -35
  118. package/src/components/input/input.tsx +96 -101
  119. package/src/components/input-group/input-group.meta.md +53 -39
  120. package/src/components/input-group/input-group.stories.tsx +49 -16
  121. package/src/components/input-group/input-group.tsx +43 -8
  122. package/src/components/input-number/input-number.meta.md +68 -20
  123. package/src/components/input-number/input-number.stories.tsx +33 -6
  124. package/src/components/input-number/input-number.tsx +79 -20
  125. package/src/components/input-otp/input-otp.meta.md +8 -20
  126. package/src/components/input-otp/input-otp.stories.tsx +3 -3
  127. package/src/components/input-otp/input-otp.tsx +1 -1
  128. package/src/components/item/item.meta.md +8 -26
  129. package/src/components/item/item.stories.tsx +3 -3
  130. package/src/components/item/item.tsx +7 -6
  131. package/src/components/kbd/kbd.meta.md +7 -19
  132. package/src/components/kbd/kbd.stories.tsx +4 -4
  133. package/src/components/kbd/kbd.tsx +8 -4
  134. package/src/components/label/label.meta.md +21 -18
  135. package/src/components/label/label.stories.tsx +64 -6
  136. package/src/components/label/label.tsx +91 -19
  137. package/src/components/masonry/masonry.meta.md +8 -12
  138. package/src/components/masonry/masonry.stories.tsx +4 -4
  139. package/src/components/mentions/mentions.meta.md +42 -21
  140. package/src/components/mentions/mentions.stories.tsx +120 -6
  141. package/src/components/mentions/mentions.tsx +10 -5
  142. package/src/components/menubar/menubar.meta.md +4 -8
  143. package/src/components/menubar/menubar.stories.tsx +55 -3
  144. package/src/components/menubar/menubar.tsx +9 -9
  145. package/src/components/native-select/native-select.meta.md +7 -11
  146. package/src/components/native-select/native-select.stories.tsx +4 -4
  147. package/src/components/native-select/native-select.tsx +1 -1
  148. package/src/components/navigation-menu/navigation-menu.meta.md +4 -8
  149. package/src/components/navigation-menu/navigation-menu.stories.tsx +106 -3
  150. package/src/components/navigation-menu/navigation-menu.tsx +6 -3
  151. package/src/components/notification/notification.meta.md +41 -8
  152. package/src/components/notification/notification.stories.tsx +9 -9
  153. package/src/components/notification/notification.tsx +34 -19
  154. package/src/components/page-header/DEVELOPMENT.md +842 -0
  155. package/src/components/page-header/page-header.meta.md +208 -0
  156. package/src/components/page-header/page-header.stories.tsx +421 -0
  157. package/src/components/page-header/page-header.tsx +281 -0
  158. package/src/components/pagination/pagination.meta.md +122 -50
  159. package/src/components/pagination/pagination.stories.tsx +227 -11
  160. package/src/components/pagination/pagination.tsx +355 -63
  161. package/src/components/popconfirm/popconfirm.meta.md +19 -23
  162. package/src/components/popconfirm/popconfirm.stories.tsx +2 -2
  163. package/src/components/popconfirm/popconfirm.tsx +1 -1
  164. package/src/components/popover/popover.meta.md +64 -12
  165. package/src/components/popover/popover.stories.tsx +83 -7
  166. package/src/components/popover/popover.tsx +77 -28
  167. package/src/components/progress/progress.meta.md +43 -26
  168. package/src/components/progress/progress.stories.tsx +2 -2
  169. package/src/components/progress/progress.tsx +19 -11
  170. package/src/components/radio-group/radio-group.meta.md +78 -11
  171. package/src/components/radio-group/radio-group.stories.tsx +38 -2
  172. package/src/components/radio-group/radio-group.tsx +149 -18
  173. package/src/components/rate/rate.meta.md +41 -19
  174. package/src/components/rate/rate.stories.tsx +2 -2
  175. package/src/components/rate/rate.tsx +37 -10
  176. package/src/components/resizable/resizable.meta.md +4 -12
  177. package/src/components/resizable/resizable.stories.tsx +5 -5
  178. package/src/components/resizable/resizable.tsx +1 -1
  179. package/src/components/result/result.meta.md +10 -14
  180. package/src/components/result/result.stories.tsx +2 -2
  181. package/src/components/result/result.tsx +21 -12
  182. package/src/components/scroll-area/scroll-area.meta.md +4 -8
  183. package/src/components/scroll-area/scroll-area.stories.tsx +5 -5
  184. package/src/components/segmented/segmented.meta.md +15 -17
  185. package/src/components/segmented/segmented.stories.tsx +3 -3
  186. package/src/components/segmented/segmented.tsx +15 -7
  187. package/src/components/select/select.meta.md +199 -67
  188. package/src/components/select/select.stories.tsx +238 -63
  189. package/src/components/select/select.tsx +718 -171
  190. package/src/components/separator/separator.meta.md +10 -14
  191. package/src/components/separator/separator.stories.tsx +2 -2
  192. package/src/components/separator/separator.tsx +3 -7
  193. package/src/components/sheet/sheet.meta.md +26 -21
  194. package/src/components/sheet/sheet.stories.tsx +116 -10
  195. package/src/components/sheet/sheet.tsx +116 -29
  196. package/src/components/sidebar/sidebar.meta.md +28 -38
  197. package/src/components/sidebar/sidebar.stories.tsx +696 -29
  198. package/src/components/sidebar/sidebar.tsx +615 -142
  199. package/src/components/skeleton/skeleton.meta.md +7 -31
  200. package/src/components/skeleton/skeleton.stories.tsx +3 -3
  201. package/src/components/skeleton/skeleton.tsx +7 -7
  202. package/src/components/slider/slider.meta.md +60 -13
  203. package/src/components/slider/slider.stories.tsx +58 -6
  204. package/src/components/slider/slider.tsx +154 -13
  205. package/src/components/sonner/sonner.meta.md +54 -8
  206. package/src/components/sonner/sonner.stories.tsx +79 -11
  207. package/src/components/sonner/sonner.tsx +137 -8
  208. package/src/components/spinner/spinner.meta.md +57 -21
  209. package/src/components/spinner/spinner.stories.tsx +66 -14
  210. package/src/components/spinner/spinner.tsx +111 -9
  211. package/src/components/statistic/statistic.meta.md +14 -30
  212. package/src/components/statistic/statistic.stories.tsx +1 -1
  213. package/src/components/statistic/statistic.tsx +4 -5
  214. package/src/components/steps/steps.meta.md +20 -15
  215. package/src/components/steps/steps.stories.tsx +37 -2
  216. package/src/components/steps/steps.tsx +15 -12
  217. package/src/components/switch/switch.meta.md +56 -15
  218. package/src/components/switch/switch.stories.tsx +5 -5
  219. package/src/components/switch/switch.tsx +59 -13
  220. package/src/components/table/table.meta.md +3 -7
  221. package/src/components/table/table.stories.tsx +1 -1
  222. package/src/components/table/table.tsx +4 -4
  223. package/src/components/tabs/tabs.meta.md +40 -32
  224. package/src/components/tabs/tabs.stories.tsx +104 -26
  225. package/src/components/tabs/tabs.tsx +125 -54
  226. package/src/components/tag/tag.meta.md +104 -68
  227. package/src/components/tag/tag.stories.tsx +183 -15
  228. package/src/components/tag/tag.tsx +222 -21
  229. package/src/components/textarea/textarea.meta.md +42 -31
  230. package/src/components/textarea/textarea.stories.tsx +32 -6
  231. package/src/components/textarea/textarea.tsx +32 -8
  232. package/src/components/time-picker/time-picker.meta.md +119 -50
  233. package/src/components/time-picker/time-picker.stories.tsx +65 -33
  234. package/src/components/time-picker/time-picker.tsx +889 -101
  235. package/src/components/timeline/timeline.meta.md +16 -17
  236. package/src/components/timeline/timeline.stories.tsx +24 -4
  237. package/src/components/timeline/timeline.tsx +32 -12
  238. package/src/components/toggle/toggle.meta.md +8 -12
  239. package/src/components/toggle/toggle.stories.tsx +4 -4
  240. package/src/components/toggle/toggle.tsx +4 -3
  241. package/src/components/toggle-group/toggle-group.meta.md +10 -14
  242. package/src/components/toggle-group/toggle-group.stories.tsx +3 -3
  243. package/src/components/toggle-group/toggle-group.tsx +2 -2
  244. package/src/components/tooltip/tooltip.meta.md +63 -18
  245. package/src/components/tooltip/tooltip.stories.tsx +42 -5
  246. package/src/components/tooltip/tooltip.tsx +81 -21
  247. package/src/components/tour/tour.meta.md +16 -20
  248. package/src/components/tour/tour.stories.tsx +3 -3
  249. package/src/components/tour/tour.tsx +3 -3
  250. package/src/components/transfer/transfer.meta.md +18 -22
  251. package/src/components/transfer/transfer.stories.tsx +2 -2
  252. package/src/components/transfer/transfer.tsx +28 -21
  253. package/src/components/tree/tree.meta.md +67 -22
  254. package/src/components/tree/tree.stories.tsx +1 -1
  255. package/src/components/tree/tree.tsx +9 -8
  256. package/src/components/tree-select/tree-select.meta.md +59 -23
  257. package/src/components/tree-select/tree-select.stories.tsx +2 -2
  258. package/src/components/tree-select/tree-select.tsx +42 -7
  259. package/src/components/typography/typography.meta.md +61 -39
  260. package/src/components/typography/typography.stories.tsx +14 -9
  261. package/src/components/typography/typography.tsx +38 -25
  262. package/src/components/upload/upload.meta.md +61 -25
  263. package/src/components/upload/upload.stories.tsx +69 -3
  264. package/src/components/upload/upload.tsx +170 -37
  265. package/src/components/watermark/watermark.meta.md +15 -19
  266. package/src/components/watermark/watermark.stories.tsx +98 -8
  267. package/src/hooks/use-breakpoint.ts +117 -0
  268. package/src/hooks/use-debounce-callback.ts +52 -0
  269. package/src/hooks/use-mobile.ts +23 -0
  270. package/src/stories/theme-tokens.stories.tsx +747 -0
  271. package/src/utils/trigger-input.ts +53 -0
  272. package/src/components/button-group/button-group.meta.md +0 -101
  273. package/src/components/button-group/button-group.stories.tsx +0 -93
  274. package/src/components/button-group/button-group.tsx +0 -75
  275. package/src/components/combobox/combobox.meta.md +0 -102
  276. package/src/components/combobox/combobox.stories.tsx +0 -55
  277. package/src/components/combobox/combobox.tsx +0 -130
  278. package/src/components/input/demo/addon.tsx +0 -15
  279. package/src/components/input/demo/with-prefix-suffix.tsx +0 -19
  280. package/src/components/space/space.meta.md +0 -103
  281. package/src/components/space/space.stories.tsx +0 -108
  282. 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,7 +73,7 @@ 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
  },
@@ -40,8 +81,10 @@ const Switch = React.forwardRef<
40
81
  ) => {
41
82
  const isSm = size === 'sm';
42
83
  const hasInner = checkedChildren != null || unCheckedChildren != null;
43
- const thumbSize = isSm ? 'size-4' : 'size-5';
44
- const spinnerSize = isSm ? 'size-3' : 'size-3.5';
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';
45
88
  const renderThumb = (extra?: string) => (
46
89
  <SwitchPrimitive.Thumb
47
90
  className={cn(
@@ -71,9 +114,9 @@ const Switch = React.forwardRef<
71
114
  hasInner
72
115
  ? cn(
73
116
  // 内文模式:高度固定,宽度按 thumb + 文字 + gap + padding 自适应
74
- isSm ? 'h-5 min-w-9 gap-1' : 'h-6 min-w-11 gap-1.5',
117
+ isSm ? 'h-4 min-w-7 gap-1' : 'h-5 min-w-9 gap-1',
75
118
  )
76
- : cn(isSm ? 'h-5 w-9' : 'h-6 w-11'),
119
+ : cn(isSm ? 'h-4 w-7' : 'h-5 w-9'),
77
120
  className,
78
121
  )}
79
122
  {...props}
@@ -85,15 +128,18 @@ const Switch = React.forwardRef<
85
128
  <span
86
129
  className={cn(
87
130
  'pointer-events-none select-none font-medium leading-none',
88
- isSm ? 'text-xxs' : 'text-xs',
131
+ isSm ? '' : 'text-xs',
89
132
  'order-2 group-data-[state=checked]:order-1',
90
133
  'group-data-[state=checked]:text-primary-foreground',
91
134
  'group-data-[state=unchecked]:text-muted-foreground',
92
135
  // 文字外侧 padding(远离 thumb 的一侧)—— thumb 侧不加 padding,与其他 switch 一致紧贴边缘
93
136
  isSm
94
137
  ? 'group-data-[state=unchecked]:pr-1 group-data-[state=checked]:pl-1'
95
- : 'group-data-[state=unchecked]:pr-1.5 group-data-[state=checked]:pl-1.5',
138
+ : 'group-data-[state=unchecked]:pr-1 group-data-[state=checked]:pl-1',
96
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}
97
143
  aria-hidden="true"
98
144
  >
99
145
  <span className="group-data-[state=unchecked]:hidden">
@@ -109,8 +155,8 @@ const Switch = React.forwardRef<
109
155
  cn(
110
156
  'transition-transform',
111
157
  isSm
112
- ? 'data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0'
113
- : 'data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
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',
114
160
  ),
115
161
  )
116
162
  )}
@@ -29,9 +29,7 @@ package: '@teamix-evo/ui'
29
29
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。
30
30
 
31
31
  <!-- auto:props:begin -->
32
-
33
32
  _(组件无 `<Name>Props` interface — props 详见 [`table.tsx`](./table.tsx))_
34
-
35
33
  <!-- auto:props:end -->
36
34
 
37
35
  ## 依赖
@@ -39,19 +37,17 @@ _(组件无 `<Name>Props` interface — props 详见 [`table.tsx`](./table.tsx))
39
37
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
40
38
 
41
39
  <!-- auto:deps:begin -->
42
-
43
40
  ### 同库依赖
44
41
 
45
42
  > `teamix-evo ui add table` 时,以下 entry 会被自动连带安装(无需手动 add)。
46
43
 
47
- | Entry | 类型 | 描述 |
48
- | ----- | ---- | -------------------------------------------------- |
49
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
44
+ | Entry | 类型 | 描述 |
45
+ | --- | --- | --- |
46
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
50
47
 
51
48
  ### npm 依赖
52
49
 
53
50
  _无 — 本组件不依赖任何 npm 包。_
54
-
55
51
  <!-- auto:deps:end -->
56
52
 
57
53
  > 子组件:`Table` / `TableHeader`(thead)/ `TableBody`(tbody)/ `TableFooter`(tfoot)/ `TableHead`(th)/ `TableRow`(tr)/ `TableCell`(td)/ `TableCaption`(caption)。
@@ -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,
@@ -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
  ));
@@ -3,21 +3,22 @@ id: tabs
3
3
  name: Tabs
4
4
  displayName: 标签页
5
5
  type: component
6
- category: navigation
6
+ category: data-display
7
7
  since: 0.1.0
8
8
  package: '@teamix-evo/ui'
9
9
  ---
10
10
 
11
11
  # Tabs 标签页
12
12
 
13
- 标签页 — Radix Tabs + antd `type` (line/card) + `tabBarExtraContent`(`extra`) 并集。
14
- 两种风格切换:`type="card"`(shadcn 默认胶囊),`type="line"`(antd 默认下划线)。
13
+ 标签页 — Radix Tabs + antd `type`/`size`/`tabBarExtraContent` 并集,并吸收 `Segmented` 的胶囊视觉。
14
+ 两种风格切换:`variant="line"`(默认,antd 下划线),`variant="capsule"`(muted 底容器 + 选中白底 shadow,可替代 Segmented 的视图切换语义)。
15
15
 
16
16
  ## When to use
17
17
 
18
18
  - 平级内容切换(详情页的 Overview / Logs / Settings 多视图)
19
19
  - 表单分组(基本信息 / 高级配置)
20
20
  - 工具栏顶部多视图
21
+ - **`variant="capsule"`**:紧凑互斥单选(视图切换 / 时间区间 / 主题档),取代旧 Segmented 用法
21
22
 
22
23
  ## When NOT to use
23
24
 
@@ -27,15 +28,14 @@ package: '@teamix-evo/ui'
27
28
 
28
29
  ## Props
29
30
 
30
- > 以下表格由 `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 的上下文(罕用)。
31
32
 
32
33
  <!-- auto:props:begin -->
33
-
34
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
35
- | ------- | ------------------ | -------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
36
- | `type` | `'line' \| 'card'` | `"card"` | – | 视觉风格(antd `type` 并集)。`card` shadcn 默认胶囊;`line` 是 antd 默认下划线。 |
37
- | `extra` | `React.ReactNode` | – | – | 右侧附加内容(antd `tabBarExtraContent` 并集);仅 `type="line"` 显式支持(布局灵活)。 用法:把节点放进来即可,组件用 `flex justify-between` 自动撑开。 |
38
-
34
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
35
+ | --- | --- | --- | --- | --- |
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` 自动撑开。 |
39
39
  <!-- auto:props:end -->
40
40
 
41
41
  ## 依赖
@@ -43,14 +43,13 @@ package: '@teamix-evo/ui'
43
43
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
44
44
 
45
45
  <!-- auto:deps:begin -->
46
-
47
46
  ### 同库依赖
48
47
 
49
48
  > `teamix-evo ui add tabs` 时,以下 entry 会被自动连带安装(无需手动 add)。
50
49
 
51
- | Entry | 类型 | 描述 |
52
- | ----- | ---- | -------------------------------------------------- |
53
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
50
+ | Entry | 类型 | 描述 |
51
+ | --- | --- | --- |
52
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
54
53
 
55
54
  ### npm 依赖
56
55
 
@@ -59,16 +58,17 @@ package: '@teamix-evo/ui'
59
58
  ```bash
60
59
  pnpm add @radix-ui/react-tabs@^1.1.0 class-variance-authority@^0.7.0
61
60
  ```
62
-
63
61
  <!-- auto:deps:end -->
64
62
 
65
- > 子组件:`Tabs` / `TabsList` / `TabsTrigger` / `TabsContent`。
63
+ > 子组件:`Tabs` / `TabsList` / `TabsTrigger` / `TabsContent`。`variant` / `size` 在 `TabsList` 上声明一次,会通过 context 透传给所有 `TabsTrigger`。
66
64
 
67
65
  ## AI 生成纪律
68
66
 
69
- - **`type="card"` 默认**:用于嵌入卡片内 / 紧凑场景(shadcn 胶囊视觉)
70
- - **`type="line"` 用于页面级**:大区块切换、主导航(antd 风格)
71
- - **`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 没有右侧条带空间
72
72
  - **value 必稳定**:切换 tab 间不改变 value 字符串
73
73
  - **orientation="vertical"** 罕用,改用 Sidebar 模式
74
74
 
@@ -77,27 +77,35 @@ pnpm add @radix-ui/react-tabs@^1.1.0 class-variance-authority@^0.7.0
77
77
  ```tsx
78
78
  import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
79
79
  import { Button } from '@/components/ui/button';
80
- import { RefreshCw } from 'lucide-react';
80
+ import { LayoutGrid, List, RefreshCw } from 'lucide-react';
81
81
 
82
- // shadcn 胶囊风格
83
- <Tabs defaultValue="overview" className="w-96">
82
+ // 默认 line 下划线风格
83
+ <Tabs defaultValue="all" className="w-96">
84
84
  <TabsList>
85
- <TabsTrigger value="overview">概览</TabsTrigger>
86
- <TabsTrigger value="logs">日志</TabsTrigger>
87
- <TabsTrigger value="settings">设置</TabsTrigger>
85
+ <TabsTrigger value="all">全部</TabsTrigger>
86
+ <TabsTrigger value="active">活跃</TabsTrigger>
87
+ <TabsTrigger value="archived">已归档</TabsTrigger>
88
88
  </TabsList>
89
- <TabsContent value="overview">...</TabsContent>
90
- <TabsContent value="logs">...</TabsContent>
91
- <TabsContent value="settings">...</TabsContent>
89
+ <TabsContent value="all">全部内容</TabsContent>
92
90
  </Tabs>
93
91
 
94
- // 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
95
105
  <Tabs defaultValue="all">
96
- <TabsList type="line" extra={<Button size="sm" icon={<RefreshCw />}>刷新</Button>}>
106
+ <TabsList variant="line" extra={<Button size="sm" variant="outline" icon={<RefreshCw />}>刷新</Button>}>
97
107
  <TabsTrigger value="all">全部</TabsTrigger>
98
108
  <TabsTrigger value="active">活跃</TabsTrigger>
99
- <TabsTrigger value="archived">已归档</TabsTrigger>
100
109
  </TabsList>
101
- <TabsContent value="all">...</TabsContent>
102
110
  </Tabs>
103
111
  ```
@@ -1,67 +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
10
  parameters: {
11
11
  docs: {
12
12
  description: {
13
13
  component:
14
- '标签页 Radix Tabs + antd type(line/card) + tabBarExtraContent(extra) 并集。胶囊风格(card) 适合嵌入场景,下划线风格(line) 适合页面级切换。',
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
15
  },
16
16
  },
17
17
  },
18
18
  argTypes: {
19
- type: { control: 'inline-radio', options: ['card', 'line'] },
19
+ variant: { control: 'inline-radio', options: ['line', 'capsule'] },
20
+ size: { control: 'inline-radio', options: ['sm', 'md', 'lg'] },
20
21
  },
21
- args: { type: 'card' },
22
+ args: { variant: 'line', size: 'md' },
22
23
  };
23
24
 
24
25
  export default meta;
25
26
  type Story = StoryObj<typeof TabsList>;
26
27
 
27
- export const Card: Story = {
28
- args: { type: 'card' },
28
+ /**
29
+ * 默认 line(下划线)风格 —— antd 主导航的标准形态。
30
+ */
31
+ export const Line: Story = {
32
+ args: { variant: 'line' },
29
33
  render: (args) => (
30
- <Tabs defaultValue="overview" className="w-96">
34
+ <Tabs defaultValue="all" className="w-[480px]">
31
35
  <TabsList {...args}>
32
- <TabsTrigger value="overview">概览</TabsTrigger>
33
- <TabsTrigger value="logs">日志</TabsTrigger>
34
- <TabsTrigger value="settings">设置</TabsTrigger>
36
+ <TabsTrigger value="all">全部</TabsTrigger>
37
+ <TabsTrigger value="active">活跃</TabsTrigger>
38
+ <TabsTrigger value="archived">已归档</TabsTrigger>
35
39
  </TabsList>
36
- <TabsContent value="overview">概览内容</TabsContent>
37
- <TabsContent value="logs">日志内容</TabsContent>
38
- <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>
39
49
  </Tabs>
40
50
  ),
41
51
  };
42
52
 
43
- export const Line: Story = {
44
- args: { type: 'line' },
53
+ /**
54
+ * 胶囊风格(吸收 Segmented)—— muted 底色容器 + 选中项白底 shadow,
55
+ * 适合视图切换、时间区间这类紧凑互斥单选场景。
56
+ */
57
+ export const Capsule: Story = {
58
+ args: { variant: 'capsule' },
45
59
  render: (args) => (
46
- <Tabs defaultValue="all" className="w-96">
60
+ <Tabs defaultValue="week" className="w-fit">
47
61
  <TabsList {...args}>
48
- <TabsTrigger value="all">全部</TabsTrigger>
49
- <TabsTrigger value="active">活跃</TabsTrigger>
50
- <TabsTrigger value="archived">已归档</TabsTrigger>
62
+ <TabsTrigger value="day">日</TabsTrigger>
63
+ <TabsTrigger value="week">周</TabsTrigger>
64
+ <TabsTrigger value="month">月</TabsTrigger>
51
65
  </TabsList>
52
- <TabsContent value="all">全部内容</TabsContent>
53
- <TabsContent value="active">活跃内容</TabsContent>
54
- <TabsContent value="archived">已归档</TabsContent>
55
66
  </Tabs>
56
67
  ),
57
68
  };
58
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>
90
+ </TabsList>
91
+ </Tabs>
92
+ ),
93
+ };
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
+ */
59
135
  export const WithExtra: Story = {
60
136
  parameters: { controls: { disable: true } },
61
137
  render: () => (
62
138
  <Tabs defaultValue="all" className="w-[480px]">
63
139
  <TabsList
64
- type="line"
140
+ variant="line"
65
141
  extra={
66
142
  <Button size="sm" variant="outline" icon={<RefreshCw />}>
67
143
  刷新
@@ -72,7 +148,9 @@ export const WithExtra: Story = {
72
148
  <TabsTrigger value="active">活跃</TabsTrigger>
73
149
  <TabsTrigger value="archived">已归档</TabsTrigger>
74
150
  </TabsList>
75
- <TabsContent value="all">全部内容...</TabsContent>
151
+ <TabsContent value="all" className="text-sm text-muted-foreground">
152
+ 全部内容...
153
+ </TabsContent>
76
154
  </Tabs>
77
155
  ),
78
156
  };