@teamix-evo/ui 0.1.1 → 0.2.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 (229) hide show
  1. package/README.md +1 -1
  2. package/package.json +8 -4
  3. package/src/components/accordion/accordion.meta.md +10 -5
  4. package/src/components/accordion/accordion.stories.tsx +11 -6
  5. package/src/components/affix/affix.meta.md +19 -10
  6. package/src/components/affix/affix.stories.tsx +4 -2
  7. package/src/components/alert/alert.meta.md +19 -14
  8. package/src/components/alert/alert.stories.tsx +1 -1
  9. package/src/components/alert/alert.tsx +5 -5
  10. package/src/components/alert-dialog/alert-dialog.meta.md +23 -10
  11. package/src/components/alert-dialog/alert-dialog.stories.tsx +1 -1
  12. package/src/components/alert-dialog/alert-dialog.tsx +1 -1
  13. package/src/components/anchor/anchor.meta.md +20 -11
  14. package/src/components/anchor/anchor.stories.tsx +1 -1
  15. package/src/components/app/app.meta.md +19 -10
  16. package/src/components/app/app.stories.tsx +4 -2
  17. package/src/components/aspect-ratio/aspect-ratio.meta.md +10 -5
  18. package/src/components/aspect-ratio/aspect-ratio.stories.tsx +1 -1
  19. package/src/components/auto-complete/auto-complete.meta.md +25 -16
  20. package/src/components/auto-complete/auto-complete.stories.tsx +4 -2
  21. package/src/components/avatar/avatar.meta.md +23 -11
  22. package/src/components/avatar/avatar.stories.tsx +1 -1
  23. package/src/components/badge/badge.meta.md +26 -21
  24. package/src/components/badge/badge.tsx +7 -13
  25. package/src/components/breadcrumb/breadcrumb.meta.md +21 -10
  26. package/src/components/breadcrumb/breadcrumb.stories.tsx +8 -0
  27. package/src/components/button/button.meta.md +22 -17
  28. package/src/components/button/button.stories.tsx +1 -1
  29. package/src/components/button/demo/as-child.tsx +24 -0
  30. package/src/components/button/demo/basic.tsx +8 -0
  31. package/src/components/button/demo/block.tsx +16 -0
  32. package/src/components/button/demo/loading.tsx +19 -0
  33. package/src/components/button/demo/shapes.tsx +18 -0
  34. package/src/components/button/demo/sizes.tsx +19 -0
  35. package/src/components/button/demo/variants.tsx +19 -0
  36. package/src/components/button/demo/with-icon.tsx +20 -0
  37. package/src/components/button-group/button-group.meta.md +18 -9
  38. package/src/components/button-group/button-group.stories.tsx +5 -2
  39. package/src/components/calendar/calendar.meta.md +14 -9
  40. package/src/components/calendar/calendar.stories.tsx +1 -1
  41. package/src/components/calendar/calendar.tsx +1 -1
  42. package/src/components/card/card.meta.md +36 -11
  43. package/src/components/card/card.stories.tsx +8 -0
  44. package/src/components/carousel/carousel.meta.md +16 -11
  45. package/src/components/carousel/carousel.stories.tsx +10 -5
  46. package/src/components/cascader/cascader.meta.md +28 -19
  47. package/src/components/cascader/cascader.stories.tsx +9 -8
  48. package/src/components/cascader/cascader.tsx +2 -2
  49. package/src/components/checkbox/checkbox.meta.md +26 -8
  50. package/src/components/checkbox/checkbox.stories.tsx +1 -1
  51. package/src/components/collapsible/collapsible.meta.md +11 -4
  52. package/src/components/collapsible/collapsible.stories.tsx +8 -0
  53. package/src/components/color-picker/color-picker.meta.md +27 -18
  54. package/src/components/color-picker/color-picker.stories.tsx +1 -1
  55. package/src/components/color-picker/color-picker.tsx +1 -0
  56. package/src/components/combobox/combobox.meta.md +29 -20
  57. package/src/components/combobox/combobox.stories.tsx +1 -1
  58. package/src/components/combobox/combobox.tsx +3 -3
  59. package/src/components/command/command.meta.md +32 -12
  60. package/src/components/command/command.stories.tsx +1 -1
  61. package/src/components/command/command.tsx +1 -1
  62. package/src/components/context-menu/context-menu.meta.md +34 -11
  63. package/src/components/context-menu/context-menu.stories.tsx +8 -0
  64. package/src/components/context-menu/context-menu.tsx +2 -2
  65. package/src/components/data-table/data-table.meta.md +24 -19
  66. package/src/components/data-table/data-table.stories.tsx +12 -5
  67. package/src/components/date-picker/date-picker.meta.md +40 -20
  68. package/src/components/date-picker/date-picker.stories.tsx +1 -1
  69. package/src/components/descriptions/descriptions.meta.md +23 -14
  70. package/src/components/descriptions/descriptions.stories.tsx +1 -1
  71. package/src/components/dialog/dialog.meta.md +25 -12
  72. package/src/components/dialog/dialog.stories.tsx +1 -1
  73. package/src/components/dialog/dialog.tsx +1 -1
  74. package/src/components/drawer/drawer.meta.md +19 -8
  75. package/src/components/drawer/drawer.stories.tsx +1 -1
  76. package/src/components/drawer/drawer.tsx +1 -0
  77. package/src/components/dropdown-menu/dropdown-menu.meta.md +42 -14
  78. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +8 -0
  79. package/src/components/dropdown-menu/dropdown-menu.tsx +2 -2
  80. package/src/components/empty/empty.meta.md +20 -11
  81. package/src/components/empty/empty.stories.tsx +1 -1
  82. package/src/components/field/field.meta.md +27 -10
  83. package/src/components/field/field.stories.tsx +6 -3
  84. package/src/components/flex/flex.meta.md +23 -14
  85. package/src/components/flex/flex.stories.tsx +46 -14
  86. package/src/components/float-button/float-button.meta.md +35 -11
  87. package/src/components/float-button/float-button.stories.tsx +4 -2
  88. package/src/components/float-button/float-button.tsx +1 -1
  89. package/src/components/form/form.meta.md +57 -14
  90. package/src/components/form/form.stories.tsx +1 -1
  91. package/src/components/grid/grid.meta.md +31 -6
  92. package/src/components/grid/grid.stories.tsx +4 -2
  93. package/src/components/hover-card/hover-card.meta.md +21 -9
  94. package/src/components/hover-card/hover-card.stories.tsx +6 -2
  95. package/src/components/image/image.meta.md +24 -15
  96. package/src/components/image/image.stories.tsx +1 -1
  97. package/src/components/image/image.tsx +4 -4
  98. package/src/components/input/demo/addon.tsx +15 -0
  99. package/src/components/input/demo/basic.tsx +12 -0
  100. package/src/components/input/demo/clearable.tsx +21 -0
  101. package/src/components/input/demo/show-count.tsx +18 -0
  102. package/src/components/input/demo/sizes.tsx +15 -0
  103. package/src/components/input/demo/with-prefix-suffix.tsx +19 -0
  104. package/src/components/input/input.meta.md +21 -16
  105. package/src/components/input/input.stories.tsx +1 -1
  106. package/src/components/input/input.tsx +51 -47
  107. package/src/components/input-group/input-group.meta.md +26 -8
  108. package/src/components/input-group/input-group.stories.tsx +1 -1
  109. package/src/components/input-group/input-group.tsx +4 -3
  110. package/src/components/input-number/input-number.meta.md +26 -17
  111. package/src/components/input-number/input-number.stories.tsx +14 -3
  112. package/src/components/input-number/input-number.tsx +20 -6
  113. package/src/components/input-otp/input-otp.meta.md +22 -9
  114. package/src/components/input-otp/input-otp.stories.tsx +1 -1
  115. package/src/components/item/item.meta.md +32 -9
  116. package/src/components/item/item.stories.tsx +5 -2
  117. package/src/components/kbd/kbd.meta.md +29 -8
  118. package/src/components/kbd/kbd.stories.tsx +1 -1
  119. package/src/components/kbd/kbd.tsx +2 -1
  120. package/src/components/label/label.meta.md +14 -9
  121. package/src/components/masonry/masonry.meta.md +18 -9
  122. package/src/components/masonry/masonry.stories.tsx +4 -2
  123. package/src/components/masonry/masonry.tsx +1 -0
  124. package/src/components/mentions/mentions.meta.md +28 -19
  125. package/src/components/mentions/mentions.stories.tsx +1 -1
  126. package/src/components/mentions/mentions.tsx +2 -1
  127. package/src/components/menubar/menubar.meta.md +36 -14
  128. package/src/components/menubar/menubar.stories.tsx +8 -0
  129. package/src/components/menubar/menubar.tsx +2 -2
  130. package/src/components/native-select/native-select.meta.md +17 -8
  131. package/src/components/native-select/native-select.stories.tsx +6 -3
  132. package/src/components/navigation-menu/navigation-menu.meta.md +25 -11
  133. package/src/components/navigation-menu/navigation-menu.stories.tsx +11 -11
  134. package/src/components/navigation-menu/navigation-menu.tsx +3 -2
  135. package/src/components/notification/notification.meta.md +14 -5
  136. package/src/components/notification/notification.stories.tsx +5 -3
  137. package/src/components/notification/notification.tsx +3 -3
  138. package/src/components/pagination/pagination.meta.md +59 -28
  139. package/src/components/pagination/pagination.stories.tsx +9 -3
  140. package/src/components/popconfirm/popconfirm.meta.md +30 -21
  141. package/src/components/popconfirm/popconfirm.stories.tsx +1 -2
  142. package/src/components/popconfirm/popconfirm.tsx +1 -1
  143. package/src/components/popover/popover.meta.md +13 -8
  144. package/src/components/popover/popover.stories.tsx +1 -1
  145. package/src/components/progress/progress.meta.md +28 -13
  146. package/src/components/progress/progress.stories.tsx +1 -1
  147. package/src/components/progress/progress.tsx +6 -6
  148. package/src/components/radio-group/radio-group.meta.md +17 -12
  149. package/src/components/radio-group/radio-group.stories.tsx +1 -1
  150. package/src/components/rate/rate.meta.md +25 -16
  151. package/src/components/rate/rate.stories.tsx +11 -3
  152. package/src/components/rate/rate.tsx +2 -2
  153. package/src/components/resizable/resizable.meta.md +19 -8
  154. package/src/components/resizable/resizable.stories.tsx +1 -1
  155. package/src/components/result/result.meta.md +21 -12
  156. package/src/components/result/result.stories.tsx +2 -6
  157. package/src/components/result/result.tsx +3 -3
  158. package/src/components/scroll-area/scroll-area.meta.md +10 -5
  159. package/src/components/scroll-area/scroll-area.stories.tsx +8 -0
  160. package/src/components/scroll-area/scroll-area.tsx +3 -3
  161. package/src/components/segmented/segmented.meta.md +19 -14
  162. package/src/components/segmented/segmented.stories.tsx +35 -6
  163. package/src/components/select/select.meta.md +22 -9
  164. package/src/components/select/select.stories.tsx +1 -1
  165. package/src/components/select/select.tsx +2 -2
  166. package/src/components/separator/separator.meta.md +16 -11
  167. package/src/components/separator/separator.stories.tsx +1 -1
  168. package/src/components/sheet/sheet.meta.md +22 -11
  169. package/src/components/sheet/sheet.stories.tsx +1 -1
  170. package/src/components/sidebar/sidebar.meta.md +47 -18
  171. package/src/components/sidebar/sidebar.stories.tsx +10 -5
  172. package/src/components/skeleton/skeleton.meta.md +33 -10
  173. package/src/components/skeleton/skeleton.stories.tsx +1 -1
  174. package/src/components/slider/slider.meta.md +12 -7
  175. package/src/components/slider/slider.stories.tsx +1 -1
  176. package/src/components/sonner/sonner.meta.md +8 -3
  177. package/src/components/sonner/sonner.stories.tsx +13 -8
  178. package/src/components/space/space.meta.md +22 -13
  179. package/src/components/space/space.stories.tsx +20 -6
  180. package/src/components/spinner/spinner.meta.md +23 -10
  181. package/src/components/spinner/spinner.stories.tsx +1 -1
  182. package/src/components/statistic/statistic.meta.md +37 -16
  183. package/src/components/statistic/statistic.stories.tsx +2 -6
  184. package/src/components/statistic/statistic.tsx +1 -1
  185. package/src/components/steps/steps.meta.md +21 -12
  186. package/src/components/steps/steps.stories.tsx +7 -2
  187. package/src/components/switch/switch.meta.md +16 -11
  188. package/src/components/switch/switch.stories.tsx +1 -1
  189. package/src/components/switch/switch.tsx +58 -36
  190. package/src/components/table/table.meta.md +24 -9
  191. package/src/components/table/table.stories.tsx +9 -4
  192. package/src/components/tabs/tabs.meta.md +14 -9
  193. package/src/components/tabs/tabs.stories.tsx +8 -0
  194. package/src/components/tag/tag.meta.md +39 -10
  195. package/src/components/tag/tag.stories.tsx +7 -2
  196. package/src/components/tag/tag.tsx +3 -3
  197. package/src/components/textarea/textarea.meta.md +17 -12
  198. package/src/components/textarea/textarea.stories.tsx +1 -1
  199. package/src/components/textarea/textarea.tsx +1 -1
  200. package/src/components/time-picker/time-picker.meta.md +38 -15
  201. package/src/components/time-picker/time-picker.stories.tsx +44 -6
  202. package/src/components/time-picker/time-picker.tsx +74 -10
  203. package/src/components/timeline/timeline.meta.md +20 -11
  204. package/src/components/timeline/timeline.stories.tsx +14 -4
  205. package/src/components/timeline/timeline.tsx +3 -2
  206. package/src/components/toggle/toggle.meta.md +14 -9
  207. package/src/components/toggle/toggle.stories.tsx +1 -1
  208. package/src/components/toggle-group/toggle-group.meta.md +16 -11
  209. package/src/components/toggle-group/toggle-group.stories.tsx +1 -1
  210. package/src/components/tooltip/tooltip.meta.md +18 -13
  211. package/src/components/tooltip/tooltip.stories.tsx +1 -1
  212. package/src/components/tour/tour.meta.md +25 -16
  213. package/src/components/tour/tour.stories.tsx +1 -1
  214. package/src/components/tour/tour.tsx +1 -1
  215. package/src/components/transfer/transfer.meta.md +29 -20
  216. package/src/components/transfer/transfer.stories.tsx +2 -6
  217. package/src/components/tree/tree.meta.md +36 -23
  218. package/src/components/tree/tree.stories.tsx +30 -11
  219. package/src/components/tree-select/tree-select.meta.md +37 -22
  220. package/src/components/tree-select/tree-select.stories.tsx +1 -1
  221. package/src/components/tree-select/tree-select.tsx +1 -1
  222. package/src/components/typography/typography.meta.md +41 -16
  223. package/src/components/typography/typography.stories.tsx +4 -8
  224. package/src/components/typography/typography.tsx +5 -3
  225. package/src/components/upload/upload.meta.md +31 -22
  226. package/src/components/upload/upload.stories.tsx +8 -14
  227. package/src/components/watermark/watermark.meta.md +26 -17
  228. package/src/components/watermark/watermark.stories.tsx +4 -2
  229. package/src/components/watermark/watermark.tsx +1 -0
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  id: tabs
3
3
  name: Tabs
4
+ displayName: 标签页
4
5
  type: component
5
6
  category: navigation
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
13
  标签页 — Radix Tabs + antd `type` (line/card) + `tabBarExtraContent`(`extra`) 并集。
13
14
  两种风格切换:`type="card"`(shadcn 默认胶囊),`type="line"`(antd 默认下划线)。
@@ -29,10 +30,12 @@ package: "@teamix-evo/ui"
29
30
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。下表是 `TabsList` 的 props;`Tabs`(Root)透传 Radix `value / defaultValue / onValueChange / orientation / activationMode`。
30
31
 
31
32
  <!-- auto:props:begin -->
32
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
33
- | --- | --- | --- | --- | --- |
34
- | `type` | `'line' \| 'card'` | `"card"` | | 视觉风格(antd `type` 并集)。`card` 是 shadcn 默认胶囊;`line` 是 antd 默认下划线。 |
35
- | `extra` | `React.ReactNode` | | – | 右侧附加内容(antd `tabBarExtraContent` 并集);仅 `type="line"` 显式支持(布局灵活)。 用法:把节点放进来即可,组件用 `flex justify-between` 自动撑开。 |
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
+
36
39
  <!-- auto:props:end -->
37
40
 
38
41
  ## 依赖
@@ -40,13 +43,14 @@ package: "@teamix-evo/ui"
40
43
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
41
44
 
42
45
  <!-- auto:deps:begin -->
46
+
43
47
  ### 同库依赖
44
48
 
45
49
  > `teamix-evo ui add tabs` 时,以下 entry 会被自动连带安装(无需手动 add)。
46
50
 
47
- | Entry | 类型 | 描述 |
48
- | --- | --- | --- |
49
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
51
+ | Entry | 类型 | 描述 |
52
+ | ----- | ---- | -------------------------------------------------- |
53
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
50
54
 
51
55
  ### npm 依赖
52
56
 
@@ -55,6 +59,7 @@ package: "@teamix-evo/ui"
55
59
  ```bash
56
60
  pnpm add @radix-ui/react-tabs@^1.1.0 class-variance-authority@^0.7.0
57
61
  ```
62
+
58
63
  <!-- auto:deps:end -->
59
64
 
60
65
  > 子组件:`Tabs` / `TabsList` / `TabsTrigger` / `TabsContent`。
@@ -7,6 +7,14 @@ const meta: Meta<typeof TabsList> = {
7
7
  title: '导航 · Navigation/Tabs',
8
8
  component: TabsList,
9
9
  tags: ['autodocs'],
10
+ parameters: {
11
+ docs: {
12
+ description: {
13
+ component:
14
+ '标签页 — Radix Tabs + antd type(line/card) + tabBarExtraContent(extra) 并集。胶囊风格(card) 适合嵌入场景,下划线风格(line) 适合页面级切换。',
15
+ },
16
+ },
17
+ },
10
18
  argTypes: {
11
19
  type: { control: 'inline-radio', options: ['card', 'line'] },
12
20
  },
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  id: tag
3
3
  name: Tag
4
+ displayName: 标签
4
5
  type: component
5
6
  category: foundation
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # Tag
11
+ # Tag 标签
11
12
 
12
13
  标签 — antd 独有补足。**与 Badge 区别**:Tag 偏向**用户可关闭的关键词标签**(分类 / 标签 / 筛选条件),支持 `closable` + 6 种语义色;Badge 偏向**状态徽标**(数字 / 红点 / 状态条)。
13
14
 
@@ -23,22 +24,49 @@ package: "@teamix-evo/ui"
23
24
  - 切换按钮 → `Toggle` / `ToggleGroup`
24
25
  - 选择类输入 → `Combobox` / `Select`
25
26
 
27
+ ## Props
28
+
26
29
  <!-- auto:props:begin -->
27
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
28
- | --- | --- | --- | --- | --- |
29
- | `color` | `'default' \| 'primary' \| 'success' \| 'warning' \| 'error' \| 'info'` | `"default"` | – | 语义颜色(antd `color` 并集) — 与 Badge 不同,Tag 偏向**用户可关闭的标签**(关键词 / 分类),Badge 偏向状态徽标。 |
30
- | `closable` | `boolean` | `false` | | 显示关闭按钮(antd `closable` 并集)。 |
31
- | `onClose` | `() => void` | | | 关闭回调。 |
30
+
31
+ #### Tag
32
+
33
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
34
+ | ---------- | ----------------------------------------------------------------------- | ----------- | ---- | ------------------------------------------------------------------------------------------------------------ |
35
+ | `color` | `'default' \| 'primary' \| 'success' \| 'warning' \| 'error' \| 'info'` | `"default"` | – | 语义颜色(antd `color` 并集) — 与 Badge 不同,Tag 偏向**用户可关闭的标签**(关键词 / 分类),Badge 偏向状态徽标。 |
36
+ | `closable` | `boolean` | `false` | – | 显示关闭按钮(antd `closable` 并集)。 |
37
+ | `onClose` | `() => void` | – | – | 关闭回调。 |
38
+
39
+ #### CheckableTag
40
+
41
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
42
+ | ---------- | ------------------------- | ------ | ---- | ---------------- |
43
+ | `checked` | `boolean` | – | ✓ | 是否选中(受控)。 |
44
+ | `onChange` | `(next: boolean) => void` | – | – | 选中态变化回调。 |
45
+ | `disabled` | `boolean` | – | – | 禁用。 |
46
+
47
+ #### CheckableTagGroup
48
+
49
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
50
+ | -------------- | --------------------------- | ------ | ---- | --------------------- |
51
+ | `options` | `CheckableTagGroupOption[]` | – | ✓ | 候选项数组。 |
52
+ | `value` | `string[]` | – | – | 受控选中 value 集合。 |
53
+ | `defaultValue` | `string[]` | – | – | 非受控初值。 |
54
+ | `onChange` | `(next: string[]) => void` | – | – | 选中变化回调。 |
55
+ | `disabled` | `boolean` | – | – | 整组禁用。 |
56
+
32
57
  <!-- auto:props:end -->
33
58
 
59
+ ## 依赖
60
+
34
61
  <!-- auto:deps:begin -->
62
+
35
63
  ### 同库依赖
36
64
 
37
65
  > `teamix-evo ui add tag` 时,以下 entry 会被自动连带安装(无需手动 add)。
38
66
 
39
- | Entry | 类型 | 描述 |
40
- | --- | --- | --- |
41
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
67
+ | Entry | 类型 | 描述 |
68
+ | ----- | ---- | -------------------------------------------------- |
69
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
42
70
 
43
71
  ### npm 依赖
44
72
 
@@ -47,6 +75,7 @@ package: "@teamix-evo/ui"
47
75
  ```bash
48
76
  pnpm add class-variance-authority@^0.7.0 lucide-react@^0.460.0
49
77
  ```
78
+
50
79
  <!-- auto:deps:end -->
51
80
 
52
81
  ## AI 生成纪律
@@ -10,7 +10,7 @@ const meta: Meta<typeof Tag> = {
10
10
  docs: {
11
11
  description: {
12
12
  component:
13
- '标签 — 用户可关闭的关键词 / 分类标签(分类、筛选条件、博客标签)。6 种语义色 + closable + onClose。OpenTrek tokens 适配,等价 antd Tag(与 Badge 互补,Badge 偏状态徽标)。',
13
+ '标签 — 用户可关闭的关键词 / 分类标签(分类、筛选条件、博客标签)。6 种语义色 + closable + onClose。等价 antd Tag(与 Badge 互补,Badge 偏状态徽标)。',
14
14
  },
15
15
  },
16
16
  },
@@ -46,7 +46,12 @@ export const Colors: Story = {
46
46
  export const Closable: Story = {
47
47
  parameters: { controls: { disable: true } },
48
48
  render: () => {
49
- const [tags, setTags] = React.useState(['React', 'Vue', 'Angular', 'Svelte']);
49
+ const [tags, setTags] = React.useState([
50
+ 'React',
51
+ 'Vue',
52
+ 'Angular',
53
+ 'Svelte',
54
+ ]);
50
55
  return (
51
56
  <div className="flex flex-wrap gap-2">
52
57
  {tags.map((t) => (
@@ -11,10 +11,10 @@ const tagVariants = cva(
11
11
  color: {
12
12
  default: 'border-border bg-muted text-foreground',
13
13
  primary: 'border-primary/30 bg-primary/10 text-primary',
14
- success: 'border-emerald-200 bg-emerald-50 text-emerald-700',
15
- warning: 'border-amber-200 bg-amber-50 text-amber-700',
14
+ success: 'border-success-border/30 bg-success-subtle text-success',
15
+ warning: 'border-warning-border/30 bg-warning-subtle text-warning',
16
16
  error: 'border-destructive/30 bg-destructive/10 text-destructive',
17
- info: 'border-blue-200 bg-blue-50 text-blue-700',
17
+ info: 'border-info-border/30 bg-info-subtle text-info',
18
18
  },
19
19
  },
20
20
  defaultVariants: { color: 'default' },
@@ -4,10 +4,11 @@ name: Textarea
4
4
  type: component
5
5
  category: form
6
6
  since: 0.1.0
7
- package: "@teamix-evo/ui"
7
+ package: '@teamix-evo/ui'
8
+ displayName: 多行文本框
8
9
  ---
9
10
 
10
- # Textarea
11
+ # Textarea 多行文本框
11
12
 
12
13
  多行文本输入 — shadcn 简洁基底 + antd 的 `autoSize / showCount`。
13
14
 
@@ -27,13 +28,15 @@ package: "@teamix-evo/ui"
27
28
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。
28
29
 
29
30
  <!-- auto:props:begin -->
30
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
31
- | --- | --- | --- | --- | --- |
32
- | `autoSize` | `boolean \| { minRows?: number; maxRows?: number }` | `false` | | 自动高度。`true` 时无上下限;传 `{ minRows, maxRows }` 时受限。 实现:监听 input 事件,把 textarea 设为 auto 后再读 scrollHeight。 |
33
- | `showCount` | `boolean` | `false` | – | 显示字符计数(antd `showCount` 并集);需配合 `maxLength`。 |
34
- | `value` | `string` | – | | 受控值。 |
35
- | `defaultValue` | `string` | – | – | uncontrolled 初始值。 |
36
- | `rows` | `number` | `3` | – | 行数(autoSize 关闭时生效)。 |
31
+
32
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
33
+ | -------------- | --------------------------------------------------- | ------- | ---- | ------------------------------------------------------------------------------------------------------------------------------- |
34
+ | `autoSize` | `boolean \| { minRows?: number; maxRows?: number }` | `false` | – | 自动高度。`true` 时无上下限;传 `{ minRows, maxRows }` 时受限。 实现:监听 input 事件,把 textarea 设为 auto 后再读 scrollHeight。 |
35
+ | `showCount` | `boolean` | `false` | – | 显示字符计数(antd `showCount` 并集);需配合 `maxLength`。 |
36
+ | `value` | `string` | – | – | 受控值。 |
37
+ | `defaultValue` | `string` | | – | uncontrolled 初始值。 |
38
+ | `rows` | `number` | `3` | – | 行数(autoSize 关闭时生效)。 |
39
+
37
40
  <!-- auto:props:end -->
38
41
 
39
42
  ## 依赖
@@ -41,17 +44,19 @@ package: "@teamix-evo/ui"
41
44
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
42
45
 
43
46
  <!-- auto:deps:begin -->
47
+
44
48
  ### 同库依赖
45
49
 
46
50
  > `teamix-evo ui add textarea` 时,以下 entry 会被自动连带安装(无需手动 add)。
47
51
 
48
- | Entry | 类型 | 描述 |
49
- | --- | --- | --- |
50
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
52
+ | Entry | 类型 | 描述 |
53
+ | ----- | ---- | -------------------------------------------------- |
54
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
51
55
 
52
56
  ### npm 依赖
53
57
 
54
58
  _无 — 本组件不依赖任何 npm 包。_
59
+
55
60
  <!-- auto:deps:end -->
56
61
 
57
62
  > 透传所有 `<textarea>` 原生属性(`name` / `placeholder` / `disabled` / `onChange` / ...)。
@@ -9,7 +9,7 @@ const meta: Meta<typeof Textarea> = {
9
9
  docs: {
10
10
  description: {
11
11
  component:
12
- '多行文本输入 — 用于输入多行文本信息。shadcn `Textarea` 原子 + antd `Input.TextArea` 的并集能力:支持 `autoSize`(传 `{ minRows, maxRows }` 随内容自适应高度)、`showCount` 发表字数计数、`maxLength` 限制。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
12
+ '多行文本输入 — 用于输入多行文本信息。shadcn `Textarea` 原子 + antd `Input.TextArea` 的并集能力:支持 `autoSize`(传 `{ minRows, maxRows }` 随内容自适应高度)、`showCount` 发表字数计数、`maxLength` 限制。',
13
13
  },
14
14
  },
15
15
  },
@@ -88,7 +88,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
88
88
  onChange={handleChange}
89
89
  className={cn(
90
90
  'flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
91
- autoSize ? 'resize-none' : 'min-h-[80px]',
91
+ autoSize ? 'resize-none' : 'min-h-textarea',
92
92
  className,
93
93
  )}
94
94
  {...props}
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  id: time-picker
3
3
  name: TimePicker
4
+ displayName: 时间选择
4
5
  type: component
5
6
  category: form
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # TimePicker
11
+ # TimePicker 时间选择
11
12
 
12
13
  时间选择 — antd 独有补足。**等价 antd `TimePicker`** 的基础能力,基于原生 `<input type="time">` 样式封装(零 JS、移动端友好、SSR safe)。配 `DatePicker` 完成日期 + 时间填写。
13
14
 
@@ -22,25 +23,37 @@ package: "@teamix-evo/ui"
22
23
  - 日期 → `DatePicker`(日期 + 时间二合一也可在 DatePicker 上拓展)
23
24
  - 复杂禁用规则 / 自定义面板:当前实现走原生,**不支持** `disabledHours` / `disabledMinutes` 等 antd 高级 API — 需要时基于 Popover + ListBox 自实现
24
25
 
26
+ ## Props
27
+
25
28
  <!-- auto:props:begin -->
26
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
27
- | --- | --- | --- | --- | --- |
28
- | `value` | `string` | | | 受控值(`HH:mm` 或 `HH:mm:ss`)— 空串表示未选。 |
29
- | `defaultValue` | `string` | – | – | uncontrolled 初值。 |
30
- | `onChange` | `(value: string) => void` | – | – | 值变化回调(实时,跟随原生 input)。 |
31
- | `showSeconds` | `boolean` | `false` | – | 是否显示秒(antd `showSeconds` 并集)— 关闭时原生 input 仅显示 HH:mm |
32
- | `step` | `number` | `60` | – | 步长() 影响原生 picker 的滚动粒度,e.g. 60 = 一分钟一档。 |
33
- | `size` | `'sm' \| 'default' \| 'lg'` | `"default"` | – | 尺寸。 |
29
+
30
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
31
+ | -------------- | --------------------------- | -------------- | ---- | -------------------------------------------------------------------- |
32
+ | `value` | `string` | – | – | 受控值(`HH:mm` `HH:mm:ss`)— 空串表示未选。 |
33
+ | `defaultValue` | `string` | – | – | uncontrolled 初值。 |
34
+ | `onChange` | `(value: string) => void` | | – | 值变化回调(实时,跟随原生 input)。 |
35
+ | `showSeconds` | `boolean` | `false` | – | 是否显示秒(antd `showSeconds` 并集)— 关闭时原生 input 仅显示 HH:mm。 |
36
+ | `step` | `number` | `60` | – | 步长(秒) — 影响原生 picker 的滚动粒度,e.g. 60 = 一分钟一档。 |
37
+ | `size` | `'sm' \| 'default' \| 'lg'` | `"default"` | – | 尺寸。 |
38
+ | `min` | `string` | – | – | 最小可选时间(antd `minDate` 并集),格式 `HH:mm` 或 `HH:mm:ss`。 |
39
+ | `max` | `string` | – | – | 最大可选时间(antd `maxDate` 并集),格式 `HH:mm` 或 `HH:mm:ss`。 |
40
+ | `allowClear` | `boolean` | `false` | – | 是否显示清除按钮(antd `allowClear` 并集)。 |
41
+ | `status` | `'error' \| 'warning'` | – | – | 校验状态,影响边框颜色(antd `status` 并集)。 |
42
+ | `placeholder` | `string` | `"请选择时间"` | – | 占位文本。 |
43
+
34
44
  <!-- auto:props:end -->
35
45
 
46
+ ## 依赖
47
+
36
48
  <!-- auto:deps:begin -->
49
+
37
50
  ### 同库依赖
38
51
 
39
52
  > `teamix-evo ui add time-picker` 时,以下 entry 会被自动连带安装(无需手动 add)。
40
53
 
41
- | Entry | 类型 | 描述 |
42
- | --- | --- | --- |
43
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
54
+ | Entry | 类型 | 描述 |
55
+ | ----- | ---- | -------------------------------------------------- |
56
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
44
57
 
45
58
  ### npm 依赖
46
59
 
@@ -49,6 +62,7 @@ package: "@teamix-evo/ui"
49
62
  ```bash
50
63
  pnpm add lucide-react@^0.460.0
51
64
  ```
65
+
52
66
  <!-- auto:deps:end -->
53
67
 
54
68
  ## AI 生成纪律
@@ -58,6 +72,9 @@ pnpm add lucide-react@^0.460.0
58
72
  - **`step`** 单位是**秒**(原生规范) — `step=900` 表示 15 分钟一档
59
73
  - **空状态用空字符串** `""`,不要传 `null` / `undefined`(原生 input 不接受 null)
60
74
  - **当前实现不支持 12 小时制 / AM-PM** — 浏览器根据系统 locale 自动决定显示格式;**不要**手动加 AM/PM 字段
75
+ - **`allowClear` 仅在受控模式下有意义** — 点击清除会触发 `onChange('')`
76
+ - **`status` 配 `Form` 使用** — 校验失败时传 `status="error"`,不要手动写 `className="border-destructive"`
77
+ - **`min` / `max` 是原生约束** — 浏览器会阻止选择范围外的时间,但手动输入仍可绕过,严格场景需配 zod 校验
61
78
 
62
79
  ## Examples
63
80
 
@@ -68,13 +85,19 @@ import * as React from 'react';
68
85
  // 基础(HH:mm)
69
86
  <TimePicker defaultValue="09:30" />
70
87
 
71
- // 受控 + 秒
88
+ // 受控 + 秒 + 可清除
72
89
  const [t, setT] = React.useState('09:30:00');
73
- <TimePicker value={t} onChange={setT} showSeconds />
90
+ <TimePicker value={t} onChange={setT} showSeconds allowClear />
74
91
 
75
92
  // 15 分钟一档
76
93
  <TimePicker step={15 * 60} />
77
94
 
95
+ // 限制工作时间范围
96
+ <TimePicker defaultValue="09:00" min="09:00" max="18:00" />
97
+
98
+ // 校验状态
99
+ <TimePicker defaultValue="09:00" status="error" />
100
+
78
101
  // 与 DatePicker 配对
79
102
  <div className="flex gap-2">
80
103
  <DatePicker />
@@ -10,7 +10,7 @@ const meta: Meta<typeof TimePicker> = {
10
10
  docs: {
11
11
  description: {
12
12
  component:
13
- '时间选择 — 基于原生 input[type=time] 样式封装(零 JS、移动端友好、SSR safe)。等价 antd `TimePicker` 基础能力,复杂禁用规则需自实现。视觉走 OpenTrek tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
13
+ '时间选择 — 基于原生 input[type=time] 样式封装(零 JS、移动端友好、SSR safe)。图标在右侧(suffix 位置,对齐 antd),有值时可清除。等价 antd `TimePicker` 基础能力,复杂禁用规则需自实现。',
14
14
  },
15
15
  },
16
16
  },
@@ -18,15 +18,25 @@ const meta: Meta<typeof TimePicker> = {
18
18
  size: { control: 'inline-radio', options: ['sm', 'default', 'lg'] },
19
19
  showSeconds: { control: 'boolean' },
20
20
  disabled: { control: 'boolean' },
21
+ allowClear: { control: 'boolean' },
22
+ status: {
23
+ control: 'inline-radio',
24
+ options: [undefined, 'error', 'warning'],
25
+ },
26
+ },
27
+ args: {
28
+ size: 'default',
29
+ showSeconds: true,
30
+ disabled: false,
31
+ allowClear: true,
21
32
  },
22
- args: { size: 'default', showSeconds: false, disabled: false },
23
33
  };
24
34
 
25
35
  export default meta;
26
36
  type Story = StoryObj<typeof TimePicker>;
27
37
 
28
38
  export const Playground: Story = {
29
- render: (args) => <TimePicker {...args} defaultValue="09:30" />,
39
+ render: (args) => <TimePicker {...args} defaultValue="09:30:00" />,
30
40
  };
31
41
 
32
42
  export const Controlled: Story = {
@@ -35,8 +45,10 @@ export const Controlled: Story = {
35
45
  const [t, setT] = React.useState('09:30:00');
36
46
  return (
37
47
  <div className="flex items-center gap-3">
38
- <TimePicker value={t} onChange={setT} showSeconds />
39
- <span className="text-sm text-muted-foreground tabular-nums">{t || '(空)'}</span>
48
+ <TimePicker value={t} onChange={setT} showSeconds allowClear />
49
+ <span className="text-sm text-muted-foreground tabular-nums">
50
+ {t || '(空)'}
51
+ </span>
40
52
  </div>
41
53
  );
42
54
  },
@@ -44,7 +56,9 @@ export const Controlled: Story = {
44
56
 
45
57
  export const QuarterHourStep: Story = {
46
58
  parameters: { controls: { disable: true } },
47
- render: () => <TimePicker showSeconds step={15 * 60} defaultValue="10:00:00" />,
59
+ render: () => (
60
+ <TimePicker showSeconds step={15 * 60} defaultValue="10:00:00" />
61
+ ),
48
62
  };
49
63
 
50
64
  export const Sizes: Story = {
@@ -57,3 +71,27 @@ export const Sizes: Story = {
57
71
  </div>
58
72
  ),
59
73
  };
74
+
75
+ export const AllowClear: Story = {
76
+ parameters: { controls: { disable: true } },
77
+ render: () => {
78
+ const [t, setT] = React.useState('14:30');
79
+ return <TimePicker value={t} onChange={setT} allowClear />;
80
+ },
81
+ };
82
+
83
+ export const MinMax: Story = {
84
+ name: 'Min / Max 限制',
85
+ parameters: { controls: { disable: true } },
86
+ render: () => <TimePicker defaultValue="09:00" min="09:00" max="18:00" />,
87
+ };
88
+
89
+ export const Status: Story = {
90
+ parameters: { controls: { disable: true } },
91
+ render: () => (
92
+ <div className="flex flex-col gap-3">
93
+ <TimePicker defaultValue="09:00" status="error" />
94
+ <TimePicker defaultValue="09:00" status="warning" />
95
+ </div>
96
+ ),
97
+ };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { Clock } from 'lucide-react';
2
+ import { Clock, X } from 'lucide-react';
3
3
 
4
4
  import { cn } from '@/utils/cn';
5
5
 
@@ -21,6 +21,7 @@ export interface TimePickerProps
21
21
  showSeconds?: boolean;
22
22
  /**
23
23
  * 步长(秒) — 影响原生 picker 的滚动粒度,e.g. 60 = 一分钟一档。
24
+ * 当 showSeconds=true 且未手动指定时,默认为 1(启用秒级选择)。
24
25
  * @default 60
25
26
  */
26
27
  step?: number;
@@ -29,6 +30,28 @@ export interface TimePickerProps
29
30
  * @default "default"
30
31
  */
31
32
  size?: 'sm' | 'default' | 'lg';
33
+ /**
34
+ * 最小可选时间(antd `minDate` 并集),格式 `HH:mm` 或 `HH:mm:ss`。
35
+ */
36
+ min?: string;
37
+ /**
38
+ * 最大可选时间(antd `maxDate` 并集),格式 `HH:mm` 或 `HH:mm:ss`。
39
+ */
40
+ max?: string;
41
+ /**
42
+ * 是否显示清除按钮(antd `allowClear` 并集)。
43
+ * @default false
44
+ */
45
+ allowClear?: boolean;
46
+ /**
47
+ * 校验状态,影响边框颜色(antd `status` 并集)。
48
+ */
49
+ status?: 'error' | 'warning';
50
+ /**
51
+ * 占位文本。
52
+ * @default "请选择时间"
53
+ */
54
+ placeholder?: string;
32
55
  }
33
56
 
34
57
  const sizeMap = {
@@ -42,6 +65,11 @@ const sizeMap = {
42
65
  * 当前实现是**原生 `<input type="time">` 的样式封装**(零 JS,移动端友好);
43
66
  * 复杂场景(范围选择 / disabledTime / 自定义面板)可后续基于 Popover + Listbox 升级。
44
67
  */
68
+ const statusStyles = {
69
+ error: 'border-destructive focus-visible:ring-destructive/30',
70
+ warning: 'border-warning focus-visible:ring-warning/30',
71
+ } as const;
72
+
45
73
  const TimePicker = React.forwardRef<HTMLInputElement, TimePickerProps>(
46
74
  (
47
75
  {
@@ -49,42 +77,78 @@ const TimePicker = React.forwardRef<HTMLInputElement, TimePickerProps>(
49
77
  defaultValue,
50
78
  onChange,
51
79
  showSeconds = false,
52
- step = 60,
80
+ step,
53
81
  size = 'default',
82
+ min,
83
+ max,
84
+ allowClear = false,
85
+ status,
86
+ placeholder = '请选择时间',
54
87
  disabled,
55
88
  className,
56
89
  ...props
57
90
  },
58
91
  ref,
59
92
  ) => {
93
+ const inputRef = React.useRef<HTMLInputElement>(null);
94
+ React.useImperativeHandle(ref, () => inputRef.current!);
95
+
96
+ const showClear = allowClear && !disabled && !!value;
97
+
98
+ // showSeconds 时 step 默认为 1(启用秒级选择),否则不设置 step(仅 HH:mm)
99
+ const resolvedStep = showSeconds ? step ?? 1 : undefined;
100
+
101
+ const handleClear = (e: React.MouseEvent) => {
102
+ e.preventDefault();
103
+ onChange?.('');
104
+ inputRef.current?.focus();
105
+ };
106
+
60
107
  return (
61
108
  <div
62
109
  className={cn(
63
- 'relative inline-flex w-fit items-center',
110
+ 'group/tp relative inline-flex w-fit items-center',
64
111
  disabled && 'cursor-not-allowed opacity-50',
65
112
  )}
66
113
  >
67
- <Clock
68
- aria-hidden="true"
69
- className="pointer-events-none absolute left-3 size-4 text-muted-foreground"
70
- />
71
114
  <input
72
- ref={ref}
115
+ ref={inputRef}
73
116
  type="time"
74
117
  value={value}
75
118
  defaultValue={defaultValue}
76
- step={showSeconds ? step : undefined}
119
+ min={min}
120
+ max={max}
121
+ step={resolvedStep}
77
122
  disabled={disabled}
123
+ placeholder={placeholder}
78
124
  onChange={(e) => onChange?.(e.target.value)}
79
125
  className={cn(
80
- 'w-full rounded-md border border-input bg-background pl-9 pr-3 text-foreground shadow-sm',
126
+ 'w-full rounded-md border border-input bg-background px-3 pr-8 text-foreground shadow-sm',
81
127
  'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
82
128
  'disabled:cursor-not-allowed',
129
+ status && statusStyles[status],
83
130
  sizeMap[size],
84
131
  className,
85
132
  )}
86
133
  {...props}
87
134
  />
135
+ {/* Suffix: clear button (on hover/value) or clock icon */}
136
+ {showClear ? (
137
+ <button
138
+ type="button"
139
+ tabIndex={-1}
140
+ aria-label="清除时间"
141
+ onClick={handleClear}
142
+ className="absolute right-2 flex items-center justify-center rounded-full p-0.5 text-muted-foreground hover:text-foreground"
143
+ >
144
+ <X className="size-3.5" />
145
+ </button>
146
+ ) : (
147
+ <Clock
148
+ aria-hidden="true"
149
+ className="pointer-events-none absolute right-2.5 size-4 text-muted-foreground"
150
+ />
151
+ )}
88
152
  </div>
89
153
  );
90
154
  },