@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
@@ -1,16 +1,17 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import { Flex } from './flex';
3
3
  import { Button } from '@/components/button/button';
4
+ import { Separator } from '@/components/separator/separator';
4
5
 
5
6
  const meta: Meta<typeof Flex> = {
6
- title: '布局与容器 · Layout/Flex',
7
+ title: '布局 · Layout/Flex',
7
8
  component: Flex,
8
9
  tags: ['autodocs'],
9
10
  parameters: {
10
11
  docs: {
11
12
  description: {
12
13
  component:
13
- 'Flex 布局容器 Tailwind flex 的常用配置(对齐 / 间距 / 换行 / 方向 / 渲染元素)收敛为枚举。等价 antd `Flex`(v5.10+),与 Space 互补:Flex 偏完整布局容器,Space inline 小集合。视觉走 OpenTrek tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
14
+ 'Flex 弹性布局 —— 以架构者语言描述一维 / 二维的子项排列。**等价 antd `Flex`**(v5.10+) **∪ antd `Space`**——覆盖完整布局容器(页头 / 卡片 / 整页)与 inline 小集合(按钮组 / tag / 链接组)两类场景:`direction`(row/column/-reverse) / `gap`(none→xl 6 档走 design 间距刻度) / `align` / `justify` / `wrap` / `inline`(等价 antd `Space`) / `as`(语义标签 section/header/main…) / `split`(等价 antd `Space.split`,在相邻子项间插入分隔节点)。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
14
15
  },
15
16
  },
16
17
  },
@@ -19,7 +20,10 @@ const meta: Meta<typeof Flex> = {
19
20
  control: 'inline-radio',
20
21
  options: ['row', 'column', 'row-reverse', 'column-reverse'],
21
22
  },
22
- gap: { control: 'select', options: ['none', 'xs', 'sm', 'default', 'lg', 'xl'] },
23
+ gap: {
24
+ control: 'select',
25
+ options: ['none', 'xs', 'sm', 'default', 'lg', 'xl'],
26
+ },
23
27
  align: {
24
28
  control: 'inline-radio',
25
29
  options: ['start', 'center', 'end', 'baseline', 'stretch'],
@@ -45,14 +49,14 @@ export default meta;
45
49
  type Story = StoryObj<typeof Flex>;
46
50
 
47
51
  const swatch = (label: string) => (
48
- <div className="grid h-12 w-20 place-items-center rounded-md border bg-muted text-xs">
52
+ <div className="grid h-12 w-20 place-items-center rounded-md border border-border bg-muted text-xs">
49
53
  {label}
50
54
  </div>
51
55
  );
52
56
 
53
57
  export const Playground: Story = {
54
58
  render: (args) => (
55
- <Flex {...args} className="min-h-32 rounded-md border bg-card p-4">
59
+ <Flex {...args} className="min-h-32 rounded-md border border-border bg-card p-4">
56
60
  {swatch('A')}
57
61
  {swatch('B')}
58
62
  {swatch('C')}
@@ -63,12 +67,23 @@ export const Playground: Story = {
63
67
  export const Header: Story = {
64
68
  parameters: { controls: { disable: true } },
65
69
  render: () => (
66
- <Flex as="header" justify="between" align="center" className="rounded-md border bg-card px-6 py-3">
70
+ <Flex
71
+ as="header"
72
+ justify="between"
73
+ align="center"
74
+ className="rounded-md border border-border bg-card px-6 py-3"
75
+ >
67
76
  <span className="font-semibold">Logo</span>
68
77
  <Flex gap="sm">
69
- <a href="#" className="text-sm hover:underline">首页</a>
70
- <a href="#" className="text-sm hover:underline">文档</a>
71
- <a href="#" className="text-sm hover:underline">价格</a>
78
+ <a href="#" className="text-sm hover:underline">
79
+ 首页
80
+ </a>
81
+ <a href="#" className="text-sm hover:underline">
82
+ 文档
83
+ </a>
84
+ <a href="#" className="text-sm hover:underline">
85
+ 价格
86
+ </a>
72
87
  </Flex>
73
88
  <Button size="sm">登录</Button>
74
89
  </Flex>
@@ -78,7 +93,11 @@ export const Header: Story = {
78
93
  export const ColumnStack: Story = {
79
94
  parameters: { controls: { disable: true } },
80
95
  render: () => (
81
- <Flex direction="column" gap="sm" className="w-80 rounded-md border bg-card p-6">
96
+ <Flex
97
+ direction="column"
98
+ gap="sm"
99
+ className="w-80 rounded-md border border-border bg-card p-6"
100
+ >
82
101
  <span className="text-lg font-semibold">标题</span>
83
102
  <span className="text-sm text-muted-foreground">这是一段描述文字</span>
84
103
  <Button>操作</Button>
@@ -89,24 +108,92 @@ export const ColumnStack: Story = {
89
108
  export const Toolbar: Story = {
90
109
  parameters: { controls: { disable: true } },
91
110
  render: () => (
92
- <Flex justify="end" gap="sm" className="rounded-md border bg-card p-3">
111
+ <Flex justify="end" gap="sm" className="rounded-md border border-border bg-card p-3">
93
112
  <Button variant="outline">取消</Button>
94
113
  <Button>提交</Button>
95
114
  </Flex>
96
115
  ),
97
116
  };
98
117
 
118
+ /**
119
+ * inline 小集合——等价 antd `Space`。加 `inline` + 小 `gap` + `align="center"` 即可覆盖原 Space 场景。
120
+ */
121
+ export const InlineGroup: Story = {
122
+ parameters: { controls: { disable: true } },
123
+ render: () => (
124
+ <Flex inline gap="sm" align="center">
125
+ <Button variant="outline">取消</Button>
126
+ <Button>确定</Button>
127
+ <Button variant="ghost">更多</Button>
128
+ </Flex>
129
+ ),
130
+ };
131
+
132
+ /**
133
+ * 链接组带分隔——等价 antd `Space.split`。`split` 接受任意 ReactNode,常用 `<Separator orientation="vertical" />`。
134
+ */
135
+ export const WithSplit: Story = {
136
+ parameters: { controls: { disable: true } },
137
+ render: () => (
138
+ <Flex
139
+ inline
140
+ gap="sm"
141
+ align="center"
142
+ split={<Separator orientation="vertical" className="h-4" />}
143
+ >
144
+ <a href="#" className="text-sm text-primary hover:underline">
145
+ 查看
146
+ </a>
147
+ <a href="#" className="text-sm text-primary hover:underline">
148
+ 编辑
149
+ </a>
150
+ <a href="#" className="text-sm text-destructive hover:underline">
151
+ 删除
152
+ </a>
153
+ </Flex>
154
+ ),
155
+ };
156
+
157
+ /**
158
+ * 主轴分几——表单行 “总计 / 金额”。等价 antd `Space justify="between"`。
159
+ */
160
+ export const Between: Story = {
161
+ parameters: { controls: { disable: true } },
162
+ render: () => (
163
+ <div className="w-80 rounded-md border border-border p-3">
164
+ <Flex justify="between" align="center">
165
+ <span className="text-sm text-muted-foreground">总计</span>
166
+ <span className="text-lg font-semibold">¥ 1,299</span>
167
+ </Flex>
168
+ </div>
169
+ ),
170
+ };
171
+
99
172
  export const WrapCloud: Story = {
100
173
  parameters: { controls: { disable: true } },
101
174
  render: () => (
102
- <Flex wrap gap="sm" className="w-96 rounded-md border bg-card p-3">
103
- {['React', 'Vue', 'Svelte', 'Solid', 'Angular', 'Lit', 'Qwik', 'Astro', 'Next', 'Remix', 'Nuxt', 'Gatsby'].map(
104
- (t) => (
105
- <span key={t} className="rounded-md border bg-muted px-2 py-0.5 text-xs">
106
- {t}
107
- </span>
108
- ),
109
- )}
175
+ <Flex wrap gap="sm" className="w-96 rounded-md border border-border bg-card p-3">
176
+ {[
177
+ 'React',
178
+ 'Vue',
179
+ 'Svelte',
180
+ 'Solid',
181
+ 'Angular',
182
+ 'Lit',
183
+ 'Qwik',
184
+ 'Astro',
185
+ 'Next',
186
+ 'Remix',
187
+ 'Nuxt',
188
+ 'Gatsby',
189
+ ].map((t) => (
190
+ <span
191
+ key={t}
192
+ className="rounded-md border border-border bg-muted px-2 py-0.5 text-xs"
193
+ >
194
+ {t}
195
+ </span>
196
+ ))}
110
197
  </Flex>
111
198
  ),
112
199
  };
@@ -67,13 +67,21 @@ export interface FlexProps extends React.HTMLAttributes<HTMLDivElement> {
67
67
  React.JSX.IntrinsicElements,
68
68
  'div' | 'section' | 'header' | 'footer' | 'aside' | 'main' | 'nav' | 'article'
69
69
  >;
70
+ /**
71
+ * 子项之间的分隔节点(antd `Space.split` 并集) — 常用 `<Separator orientation="vertical" />`、`'·'`、`'|'`。
72
+ * 设置后会在每两个相邻子项之间插入该节点。
73
+ */
74
+ split?: React.ReactNode;
70
75
  }
71
76
 
72
77
  /**
73
- * Flex 布局容器 — antd 独有补足。**等价 antd `Flex`**(v5.10+),提供 Tailwind flex 的语义封装,
74
- * 把常用对齐 / 间距 / 换行 / 方向 / 渲染元素收敛为枚举,避免散落的 className 反复手写。
78
+ * Flex 布局容器 — antd 独有补足。**等价 antd `Flex`**(v5.10+) **antd `Space`**(`split`)。
79
+ * Tailwind flex 的常用对齐 / 间距 / 换行 / 方向 / 渲染元素 / 分隔节点收敛为枚举,避免散落的 className 反复手写。
75
80
  *
76
- * 与 `Space` 区别:Flex 偏向**完整布局容器**(页头、卡片体、整页),Space 偏向 inline 小集合。
81
+ * 用法约定:
82
+ * - 完整布局容器(页头、卡片体、整页): `<Flex as="header" justify="between" align="center" />`
83
+ * - inline 小集合(按钮组、tag 组、链接组): `<Flex inline gap="sm" align="center" />`(等价 antd `Space`)
84
+ * - 链接组带分隔: `<Flex inline gap="sm" split={<Separator orientation="vertical" />} />`
77
85
  */
78
86
  const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
79
87
  (
@@ -85,7 +93,9 @@ const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
85
93
  wrap = false,
86
94
  inline = false,
87
95
  as = 'div',
96
+ split,
88
97
  className,
98
+ children,
89
99
  ...props
90
100
  },
91
101
  ref,
@@ -100,6 +110,17 @@ const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
100
110
  ? 'flex-row-reverse'
101
111
  : 'flex-col-reverse';
102
112
 
113
+ const content = split
114
+ ? React.Children.toArray(children)
115
+ .filter(Boolean)
116
+ .map((child, i) => (
117
+ <React.Fragment key={i}>
118
+ {i > 0 ? split : null}
119
+ {child}
120
+ </React.Fragment>
121
+ ))
122
+ : children;
123
+
103
124
  return (
104
125
  <Tag
105
126
  ref={ref}
@@ -113,7 +134,9 @@ const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
113
134
  className,
114
135
  )}
115
136
  {...props}
116
- />
137
+ >
138
+ {content}
139
+ </Tag>
117
140
  );
118
141
  },
119
142
  );
@@ -2,12 +2,13 @@
2
2
  id: float-button
3
3
  name: FloatButton
4
4
  type: component
5
- category: navigation
5
+ category: deprecated
6
6
  since: 0.1.0
7
- package: "@teamix-evo/ui"
7
+ package: '@teamix-evo/ui'
8
+ displayName: 悬浮按钮
8
9
  ---
9
10
 
10
- # FloatButton
11
+ # FloatButton 悬浮按钮
11
12
 
12
13
  悬浮按钮 — antd 独有补足。**等价 antd `FloatButton`**(v5.0 加入,取代旧 `BackTop`)。`position: fixed` 在右下角的强主张操作按钮:回到顶部、客服入口、新建按钮。配 `FloatButtonGroup` 纵向堆叠多个,`FloatButtonBackTop` 是预置的"回到顶部"快捷件。
13
14
 
@@ -24,6 +25,8 @@ package: "@teamix-evo/ui"
24
25
  - 列表行末操作 → 普通 `Button` / `DropdownMenu`
25
26
  - 多个无关操作堆在右下:容易遮挡内容,> 3 个 FloatButton 时换 SpeedDial 模式
26
27
 
28
+ ## Props
29
+
27
30
  <!-- auto:props:begin -->
28
31
  | 名称 | 类型 | 默认值 | 必填 | 说明 |
29
32
  | --- | --- | --- | --- | --- |
@@ -33,6 +36,8 @@ package: "@teamix-evo/ui"
33
36
  | `badge` | `React.ReactNode` | – | – | 触发徽标(antd `badge` 并集) — 简短数字 / 字符。 |
34
37
  <!-- auto:props:end -->
35
38
 
39
+ ## 依赖
40
+
36
41
  <!-- auto:deps:begin -->
37
42
  ### 同库依赖
38
43
 
@@ -1,4 +1,4 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import { MessageCircle, Plus } from 'lucide-react';
3
3
  import {
4
4
  FloatButton,
@@ -7,14 +7,14 @@ import {
7
7
  } from './float-button';
8
8
 
9
9
  const meta: Meta<typeof FloatButton> = {
10
- title: '导航 · Navigation/FloatButton',
10
+ title: '废弃 · Deprecated/FloatButton',
11
11
  component: FloatButton,
12
12
  tags: ['autodocs'],
13
13
  parameters: {
14
14
  docs: {
15
15
  description: {
16
16
  component:
17
- '悬浮按钮 — position: fixed 在右下角的强主张操作按钮(回到顶部 / 客服 / 新建)。配 FloatButtonGroup 堆叠多个,FloatButtonBackTop 是预置的"回到顶部"。等价 antd `FloatButton`(v5.0,替代旧 BackTop)。视觉走 OpenTrek tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
17
+ '⚠️ **已废弃** — 仅 Storybook 留档,不通过 manifest 对外发布。\n\n悬浮按钮 — position: fixed 在右下角的强主张操作按钮(回到顶部 / 客服 / 新建)。配 FloatButtonGroup 堆叠多个,FloatButtonBackTop 是预置的“回到顶部”。等价 antd `FloatButton`(v5.0,替代旧 BackTop)。',
18
18
  },
19
19
  },
20
20
  },
@@ -26,7 +26,7 @@ type Story = StoryObj<typeof FloatButton>;
26
26
  export const Playground: Story = {
27
27
  parameters: { controls: { disable: true } },
28
28
  render: () => (
29
- <div className="relative h-72 overflow-hidden rounded-md border">
29
+ <div className="relative h-72 overflow-hidden rounded-md border border-border">
30
30
  <div className="p-4 text-sm text-muted-foreground">
31
31
  ← 右下角是 FloatButton 演示
32
32
  </div>
@@ -40,7 +40,7 @@ export const Playground: Story = {
40
40
  export const Group: Story = {
41
41
  parameters: { controls: { disable: true } },
42
42
  render: () => (
43
- <div className="relative h-96 overflow-hidden rounded-md border">
43
+ <div className="relative h-96 overflow-hidden rounded-md border border-border">
44
44
  <div className="p-4 text-sm text-muted-foreground">右下角浮动按钮组</div>
45
45
  <div className="absolute bottom-6 right-6 flex flex-col items-end gap-3">
46
46
  <FloatButton
@@ -62,10 +62,12 @@ export const BackTopReal: Story = {
62
62
  parameters: { controls: { disable: true } },
63
63
  render: () => (
64
64
  <>
65
- <div className="text-sm text-muted-foreground">向下滚动 200px 查看回到顶部按钮:</div>
65
+ <div className="text-sm text-muted-foreground">
66
+ 向下滚动 200px 查看回到顶部按钮:
67
+ </div>
66
68
  <div className="mt-3 space-y-3">
67
69
  {Array.from({ length: 30 }).map((_, i) => (
68
- <div key={i} className="rounded-md border bg-muted/30 p-6">
70
+ <div key={i} className="rounded-md border border-border bg-muted/30 p-6">
69
71
  占位段落 {i + 1}
70
72
  </div>
71
73
  ))}
@@ -62,7 +62,7 @@ const FloatButton = React.forwardRef<HTMLButtonElement, FloatButtonProps>(
62
62
  >
63
63
  {icon ?? children}
64
64
  {badge != null ? (
65
- <span className="absolute -right-1 -top-1 flex h-5 min-w-[1.25rem] items-center justify-center rounded-full bg-destructive px-1 text-[10px] font-medium leading-none text-destructive-foreground">
65
+ <span className="absolute -right-1 -top-1 flex h-5 min-w-counter items-center justify-center rounded-full bg-destructive px-1 text-xxs font-medium leading-none text-destructive-foreground">
66
66
  {badge}
67
67
  </span>
68
68
  ) : null}
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  id: form
3
3
  name: Form
4
+ displayName: 表单
4
5
  type: component
5
- category: form
6
+ category: data-entry
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # Form
11
+ # Form 表单
11
12
 
12
13
  表单 — 基于 [`react-hook-form`](https://react-hook-form.com/),shadcn 标准 7 件套(`Form / FormField / FormItem / FormLabel / FormControl / FormDescription / FormMessage`)。
13
14
  **配合 [`zod`](https://zod.dev/) + `@hookform/resolvers/zod` 做 schema 校验**(行业惯例)。
@@ -26,7 +27,7 @@ package: "@teamix-evo/ui"
26
27
 
27
28
  ## Props
28
29
 
29
- > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。`Form` 是 `FormProvider` 别名,直接接受 `useForm()` 返回值的所有方法;不存在专门的 props 表 —下表代表 `FormItem` 的 props 作为 docs anchor,实际用法见 Examples
30
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。`Form` 是 `FormProvider` 别名,直接接受 `useForm()` 返回值;下表按子组件分节列出各自的 Props
30
31
 
31
32
  <!-- auto:props:begin -->
32
33
  | 名称 | 类型 | 默认值 | 必填 | 说明 |
@@ -46,28 +47,41 @@ package: "@teamix-evo/ui"
46
47
  | Entry | 类型 | 描述 |
47
48
  | --- | --- | --- |
48
49
  | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
49
- | `label` | component | 表单字段标签Radix Label 包装,补 antd Form.Item 风格的 required / disabled 显式视觉 |
50
+ | `field` | component | 通用表单字段抽象shadcn 2025-10 新增。Field / FieldLabel / FieldDescription / FieldError / FieldGroup / FieldSet / FieldLegend 7 个语义槽,跟任何状态管理(Server Actions / RHF / TanStack Form)都能搭,与 form 共存 |
50
51
 
51
52
  ### npm 依赖
52
53
 
53
54
  > 业务侧需要先 `pnpm add` / `npm install` 这些包。CLI 在 `ui add` 完成后会列出此提示。
54
55
 
55
56
  ```bash
56
- pnpm add react-hook-form@^7.50.0 @hookform/resolvers@^3.0.0 zod@^3.22.0 @radix-ui/react-label@^2.1.0 @radix-ui/react-slot@^1.1.0
57
+ pnpm add react-hook-form@^7.50.0 @hookform/resolvers@^3.0.0 zod@^3.22.0 @radix-ui/react-slot@^1.1.0
57
58
  ```
58
59
  <!-- auto:deps:end -->
59
60
 
60
- > 完整子组件:`Form` / `FormField` / `FormItem` / `FormLabel` / `FormControl` / `FormDescription` / `FormMessage`,配合 `useFormField()` hook。
61
+ ## 子组件
62
+
63
+ 除 shadcn 7 件套(`Form / FormField / FormItem / FormLabel / FormControl / FormDescription / FormMessage`)外,本包补两个表单骨架子组件:
64
+
65
+ - **`FormSection`**:表单分组容器,支持 `title`(组标题,14px medium)和 `columns`(`1 \| 2 \| 3 \| 4` 多栏 grid)。代替手写 h3 + Row/Col。
66
+ - **`FormActions`**:表单操作按钮容器,支持 `position`(`'inline'` / `'sticky'`)、`align`(`'start'` / `'end'`)和 `alignWithInput`(与输入域基线对齐,避免按钮与 label 列重叠)。
67
+
68
+ > **实现共享**:`FormSection` / `FormActions` 是 Field 包同名组件的 re-export 别名(一处实现,规范变更只改一处)。Props 与行为完全等同 `FieldSection` / `FieldActions`,详见 [`field.meta.md`](../field/field.meta.md)。
61
69
 
62
70
  ## AI 生成纪律
63
71
 
64
- - **`Form` 必包 `useForm()`**:`<Form {...form}>...</Form>`,把整个 form instance 散开传入(FormProvider 期望)
65
- - **每个字段必有 `<FormField name="..." control={form.control} render={({ field }) => <FormItem>...</FormItem>} />`**:不要直接渲染 input 不走 Field,会失去校验关联
66
- - **`<FormControl>` 只放真正的输入控件**:input / textarea / Select / Checkbox 等;Slot 模式自动注入 id / aria-describedby / aria-invalid
67
- - **错误消息走 `<FormMessage />`**:不要手写 `{errors.x?.message}` — FormMessage 自动连接 fieldState
68
- - **schema 优先**:用 zod schema `useForm({ resolver: zodResolver(schema) })`;校验逻辑集中在 schema,不要散在 input 上
69
- - **提交后保留状态**:`form.reset()` 重置;**不要**手动清空每个字段
70
- - **不要嵌套 Form**:嵌套会破坏 React Context
72
+ - **`Form` 必包 `useForm()`**:`<Form {...form}>...</Form>`,把整个 form instance 散开传入(FormProvider 期望)
73
+ - **每个字段必有 `<FormField name="..." control={form.control} render={({ field }) => <FormItem>...</FormItem>} />`**:不要直接渲染 input 不走 Field,会失去校验关联
74
+ - **`<FormControl>` 只放真正的输入控件**:input / textarea / Select / Checkbox 等;Slot 模式自动注入 id / aria-describedby / aria-invalid
75
+ - **错误消息走 `<FormMessage />`**:不要手写 `{errors.x?.message}` — FormMessage 自动连接 fieldState
76
+ - **必填标记 `*` 总是后置**:`<FormLabel required>` 由底层 `Label` 组件在文字与 tooltip icon **后**渲染红色 `*`(顺序为 `文字 ⓘ *`),对齐设计规范;不要手写 `<FormLabel>邮箱 *</FormLabel>` 或 `<FormLabel>* 邮箱</FormLabel>`。同时记得在 schema `z.string().min(1)` 或控件上 `aria-required="true"`。
77
+ - **schema 优先**:用 zod 写 schema → `useForm({ resolver: zodResolver(schema) })`;校验逻辑集中在 schema,不要散在 input 上
78
+ - **提交后保留状态**:`form.reset()` 重置;**不要**手动清空每个字段
79
+ - **不要嵌套 Form**:嵌套会破坏 React Context
80
+ - ✅ 复杂表单必须用 `FormSection` 分组(组标题用 `title` prop,不要手写 `<h3>`)
81
+ - ✅ 多栏布局用 `FormSection columns={N}`(不要手写 `Row`/`Col` 或 `grid grid-cols-N`)
82
+ - ✅ 表单提交 / 取消按钮必须用 `FormActions`
83
+ - ✅ 多个 `FormSection` 的父容器必须用 `gap-8`(32px 组间距)
84
+ - ✅ 错误信息(`FormMessage`)紧贴 input,不要额外加 `mt-*` 或包裹 `<div>`
71
85
 
72
86
  ## Examples
73
87
 
@@ -76,8 +90,13 @@ import { useForm } from 'react-hook-form';
76
90
  import { zodResolver } from '@hookform/resolvers/zod';
77
91
  import { z } from 'zod';
78
92
  import {
79
- Form, FormField, FormItem, FormLabel, FormControl,
80
- FormDescription, FormMessage,
93
+ Form,
94
+ FormField,
95
+ FormItem,
96
+ FormLabel,
97
+ FormControl,
98
+ FormDescription,
99
+ FormMessage,
81
100
  } from '@/components/ui/form';
82
101
  import { Input } from '@/components/ui/input';
83
102
  import { Button } from '@/components/ui/button';
@@ -95,7 +114,10 @@ function MyForm() {
95
114
 
96
115
  return (
97
116
  <Form {...form}>
98
- <form onSubmit={form.handleSubmit((v) => console.log(v))} className="space-y-4">
117
+ <form
118
+ onSubmit={form.handleSubmit((v) => console.log(v))}
119
+ className="space-y-4"
120
+ >
99
121
  <FormField
100
122
  control={form.control}
101
123
  name="username"