@teamix-evo/ui 0.1.1

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 (270) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +336 -0
  3. package/_data.json +12 -0
  4. package/manifest.json +1688 -0
  5. package/package.json +90 -0
  6. package/src/components/accordion/accordion.meta.md +87 -0
  7. package/src/components/accordion/accordion.stories.tsx +67 -0
  8. package/src/components/accordion/accordion.tsx +58 -0
  9. package/src/components/affix/affix.meta.md +80 -0
  10. package/src/components/affix/affix.stories.tsx +57 -0
  11. package/src/components/affix/affix.tsx +97 -0
  12. package/src/components/alert/alert.meta.md +101 -0
  13. package/src/components/alert/alert.stories.tsx +93 -0
  14. package/src/components/alert/alert.tsx +132 -0
  15. package/src/components/alert-dialog/alert-dialog.meta.md +107 -0
  16. package/src/components/alert-dialog/alert-dialog.stories.tsx +81 -0
  17. package/src/components/alert-dialog/alert-dialog.tsx +136 -0
  18. package/src/components/anchor/anchor.meta.md +87 -0
  19. package/src/components/anchor/anchor.stories.tsx +74 -0
  20. package/src/components/anchor/anchor.tsx +130 -0
  21. package/src/components/app/app.meta.md +86 -0
  22. package/src/components/app/app.stories.tsx +62 -0
  23. package/src/components/app/app.tsx +58 -0
  24. package/src/components/aspect-ratio/aspect-ratio.meta.md +81 -0
  25. package/src/components/aspect-ratio/aspect-ratio.stories.tsx +59 -0
  26. package/src/components/aspect-ratio/aspect-ratio.tsx +22 -0
  27. package/src/components/auto-complete/auto-complete.meta.md +102 -0
  28. package/src/components/auto-complete/auto-complete.stories.tsx +93 -0
  29. package/src/components/auto-complete/auto-complete.tsx +205 -0
  30. package/src/components/avatar/avatar.meta.md +94 -0
  31. package/src/components/avatar/avatar.stories.tsx +80 -0
  32. package/src/components/avatar/avatar.tsx +126 -0
  33. package/src/components/badge/badge.meta.md +119 -0
  34. package/src/components/badge/badge.stories.tsx +153 -0
  35. package/src/components/badge/badge.tsx +210 -0
  36. package/src/components/breadcrumb/breadcrumb.meta.md +107 -0
  37. package/src/components/breadcrumb/breadcrumb.stories.tsx +84 -0
  38. package/src/components/breadcrumb/breadcrumb.tsx +122 -0
  39. package/src/components/button/button.meta.md +98 -0
  40. package/src/components/button/button.stories.tsx +235 -0
  41. package/src/components/button/button.tsx +160 -0
  42. package/src/components/button-group/button-group.meta.md +92 -0
  43. package/src/components/button-group/button-group.stories.tsx +90 -0
  44. package/src/components/button-group/button-group.tsx +75 -0
  45. package/src/components/calendar/calendar.meta.md +118 -0
  46. package/src/components/calendar/calendar.stories.tsx +68 -0
  47. package/src/components/calendar/calendar.tsx +107 -0
  48. package/src/components/card/card.meta.md +117 -0
  49. package/src/components/card/card.stories.tsx +112 -0
  50. package/src/components/card/card.tsx +222 -0
  51. package/src/components/carousel/carousel.meta.md +117 -0
  52. package/src/components/carousel/carousel.stories.tsx +84 -0
  53. package/src/components/carousel/carousel.tsx +224 -0
  54. package/src/components/cascader/cascader.meta.md +110 -0
  55. package/src/components/cascader/cascader.stories.tsx +108 -0
  56. package/src/components/cascader/cascader.tsx +198 -0
  57. package/src/components/checkbox/checkbox.meta.md +99 -0
  58. package/src/components/checkbox/checkbox.stories.tsx +130 -0
  59. package/src/components/checkbox/checkbox.tsx +125 -0
  60. package/src/components/collapsible/collapsible.meta.md +80 -0
  61. package/src/components/collapsible/collapsible.stories.tsx +35 -0
  62. package/src/components/collapsible/collapsible.tsx +18 -0
  63. package/src/components/color-picker/color-picker.meta.md +84 -0
  64. package/src/components/color-picker/color-picker.stories.tsx +80 -0
  65. package/src/components/color-picker/color-picker.tsx +160 -0
  66. package/src/components/combobox/combobox.meta.md +93 -0
  67. package/src/components/combobox/combobox.stories.tsx +55 -0
  68. package/src/components/combobox/combobox.tsx +130 -0
  69. package/src/components/command/command.meta.md +104 -0
  70. package/src/components/command/command.stories.tsx +59 -0
  71. package/src/components/command/command.tsx +147 -0
  72. package/src/components/context-menu/context-menu.meta.md +90 -0
  73. package/src/components/context-menu/context-menu.stories.tsx +46 -0
  74. package/src/components/context-menu/context-menu.tsx +191 -0
  75. package/src/components/data-table/data-table.meta.md +149 -0
  76. package/src/components/data-table/data-table.stories.tsx +125 -0
  77. package/src/components/data-table/data-table.tsx +185 -0
  78. package/src/components/date-picker/date-picker.meta.md +106 -0
  79. package/src/components/date-picker/date-picker.stories.tsx +58 -0
  80. package/src/components/date-picker/date-picker.tsx +156 -0
  81. package/src/components/descriptions/descriptions.meta.md +78 -0
  82. package/src/components/descriptions/descriptions.stories.tsx +60 -0
  83. package/src/components/descriptions/descriptions.tsx +129 -0
  84. package/src/components/dialog/dialog.meta.md +105 -0
  85. package/src/components/dialog/dialog.stories.tsx +93 -0
  86. package/src/components/dialog/dialog.tsx +128 -0
  87. package/src/components/drawer/drawer.meta.md +96 -0
  88. package/src/components/drawer/drawer.stories.tsx +54 -0
  89. package/src/components/drawer/drawer.tsx +114 -0
  90. package/src/components/dropdown-menu/dropdown-menu.meta.md +103 -0
  91. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +112 -0
  92. package/src/components/dropdown-menu/dropdown-menu.tsx +195 -0
  93. package/src/components/empty/empty.meta.md +81 -0
  94. package/src/components/empty/empty.stories.tsx +46 -0
  95. package/src/components/empty/empty.tsx +47 -0
  96. package/src/components/field/field.meta.md +116 -0
  97. package/src/components/field/field.stories.tsx +117 -0
  98. package/src/components/field/field.tsx +164 -0
  99. package/src/components/flex/flex.meta.md +94 -0
  100. package/src/components/flex/flex.stories.tsx +112 -0
  101. package/src/components/flex/flex.tsx +122 -0
  102. package/src/components/float-button/float-button.meta.md +87 -0
  103. package/src/components/float-button/float-button.stories.tsx +78 -0
  104. package/src/components/float-button/float-button.tsx +143 -0
  105. package/src/components/form/form.meta.md +131 -0
  106. package/src/components/form/form.stories.tsx +122 -0
  107. package/src/components/form/form.tsx +194 -0
  108. package/src/components/grid/grid.meta.md +87 -0
  109. package/src/components/grid/grid.stories.tsx +99 -0
  110. package/src/components/grid/grid.tsx +130 -0
  111. package/src/components/hover-card/hover-card.meta.md +92 -0
  112. package/src/components/hover-card/hover-card.stories.tsx +68 -0
  113. package/src/components/hover-card/hover-card.tsx +29 -0
  114. package/src/components/image/image.meta.md +94 -0
  115. package/src/components/image/image.stories.tsx +55 -0
  116. package/src/components/image/image.tsx +138 -0
  117. package/src/components/input/input.meta.md +109 -0
  118. package/src/components/input/input.stories.tsx +117 -0
  119. package/src/components/input/input.tsx +213 -0
  120. package/src/components/input-group/input-group.meta.md +92 -0
  121. package/src/components/input-group/input-group.stories.tsx +88 -0
  122. package/src/components/input-group/input-group.tsx +107 -0
  123. package/src/components/input-number/input-number.meta.md +91 -0
  124. package/src/components/input-number/input-number.stories.tsx +87 -0
  125. package/src/components/input-number/input-number.tsx +210 -0
  126. package/src/components/input-otp/input-otp.meta.md +105 -0
  127. package/src/components/input-otp/input-otp.stories.tsx +65 -0
  128. package/src/components/input-otp/input-otp.tsx +97 -0
  129. package/src/components/item/item.meta.md +116 -0
  130. package/src/components/item/item.stories.tsx +113 -0
  131. package/src/components/item/item.tsx +171 -0
  132. package/src/components/kbd/kbd.meta.md +85 -0
  133. package/src/components/kbd/kbd.stories.tsx +70 -0
  134. package/src/components/kbd/kbd.tsx +81 -0
  135. package/src/components/label/label.meta.md +91 -0
  136. package/src/components/label/label.stories.tsx +87 -0
  137. package/src/components/label/label.tsx +66 -0
  138. package/src/components/masonry/masonry.meta.md +85 -0
  139. package/src/components/masonry/masonry.stories.tsx +66 -0
  140. package/src/components/masonry/masonry.tsx +59 -0
  141. package/src/components/mentions/mentions.meta.md +89 -0
  142. package/src/components/mentions/mentions.stories.tsx +75 -0
  143. package/src/components/mentions/mentions.tsx +237 -0
  144. package/src/components/menubar/menubar.meta.md +100 -0
  145. package/src/components/menubar/menubar.stories.tsx +81 -0
  146. package/src/components/menubar/menubar.tsx +232 -0
  147. package/src/components/native-select/native-select.meta.md +88 -0
  148. package/src/components/native-select/native-select.stories.tsx +80 -0
  149. package/src/components/native-select/native-select.tsx +54 -0
  150. package/src/components/navigation-menu/navigation-menu.meta.md +108 -0
  151. package/src/components/navigation-menu/navigation-menu.stories.tsx +112 -0
  152. package/src/components/navigation-menu/navigation-menu.tsx +125 -0
  153. package/src/components/notification/notification.meta.md +91 -0
  154. package/src/components/notification/notification.stories.tsx +96 -0
  155. package/src/components/notification/notification.tsx +84 -0
  156. package/src/components/pagination/pagination.meta.md +127 -0
  157. package/src/components/pagination/pagination.stories.tsx +62 -0
  158. package/src/components/pagination/pagination.tsx +285 -0
  159. package/src/components/popconfirm/popconfirm.meta.md +109 -0
  160. package/src/components/popconfirm/popconfirm.stories.tsx +76 -0
  161. package/src/components/popconfirm/popconfirm.tsx +134 -0
  162. package/src/components/popover/popover.meta.md +97 -0
  163. package/src/components/popover/popover.stories.tsx +82 -0
  164. package/src/components/popover/popover.tsx +55 -0
  165. package/src/components/progress/progress.meta.md +86 -0
  166. package/src/components/progress/progress.stories.tsx +75 -0
  167. package/src/components/progress/progress.tsx +195 -0
  168. package/src/components/radio-group/radio-group.meta.md +103 -0
  169. package/src/components/radio-group/radio-group.stories.tsx +77 -0
  170. package/src/components/radio-group/radio-group.tsx +78 -0
  171. package/src/components/rate/rate.meta.md +87 -0
  172. package/src/components/rate/rate.stories.tsx +81 -0
  173. package/src/components/rate/rate.tsx +153 -0
  174. package/src/components/resizable/resizable.meta.md +92 -0
  175. package/src/components/resizable/resizable.stories.tsx +104 -0
  176. package/src/components/resizable/resizable.tsx +56 -0
  177. package/src/components/result/result.meta.md +90 -0
  178. package/src/components/result/result.stories.tsx +71 -0
  179. package/src/components/result/result.tsx +91 -0
  180. package/src/components/scroll-area/scroll-area.meta.md +84 -0
  181. package/src/components/scroll-area/scroll-area.stories.tsx +41 -0
  182. package/src/components/scroll-area/scroll-area.tsx +51 -0
  183. package/src/components/segmented/segmented.meta.md +103 -0
  184. package/src/components/segmented/segmented.stories.tsx +101 -0
  185. package/src/components/segmented/segmented.tsx +138 -0
  186. package/src/components/select/select.meta.md +110 -0
  187. package/src/components/select/select.stories.tsx +100 -0
  188. package/src/components/select/select.tsx +188 -0
  189. package/src/components/separator/separator.meta.md +74 -0
  190. package/src/components/separator/separator.stories.tsx +71 -0
  191. package/src/components/separator/separator.tsx +104 -0
  192. package/src/components/sheet/sheet.meta.md +97 -0
  193. package/src/components/sheet/sheet.stories.tsx +82 -0
  194. package/src/components/sheet/sheet.tsx +139 -0
  195. package/src/components/sidebar/sidebar.meta.md +131 -0
  196. package/src/components/sidebar/sidebar.stories.tsx +82 -0
  197. package/src/components/sidebar/sidebar.tsx +351 -0
  198. package/src/components/skeleton/skeleton.meta.md +95 -0
  199. package/src/components/skeleton/skeleton.stories.tsx +79 -0
  200. package/src/components/skeleton/skeleton.tsx +144 -0
  201. package/src/components/slider/slider.meta.md +94 -0
  202. package/src/components/slider/slider.stories.tsx +69 -0
  203. package/src/components/slider/slider.tsx +86 -0
  204. package/src/components/sonner/sonner.meta.md +96 -0
  205. package/src/components/sonner/sonner.stories.tsx +91 -0
  206. package/src/components/sonner/sonner.tsx +40 -0
  207. package/src/components/space/space.meta.md +94 -0
  208. package/src/components/space/space.stories.tsx +94 -0
  209. package/src/components/space/space.tsx +106 -0
  210. package/src/components/spinner/spinner.meta.md +76 -0
  211. package/src/components/spinner/spinner.stories.tsx +71 -0
  212. package/src/components/spinner/spinner.tsx +64 -0
  213. package/src/components/statistic/statistic.meta.md +99 -0
  214. package/src/components/statistic/statistic.stories.tsx +71 -0
  215. package/src/components/statistic/statistic.tsx +197 -0
  216. package/src/components/steps/steps.meta.md +102 -0
  217. package/src/components/steps/steps.stories.tsx +75 -0
  218. package/src/components/steps/steps.tsx +170 -0
  219. package/src/components/switch/switch.meta.md +92 -0
  220. package/src/components/switch/switch.stories.tsx +75 -0
  221. package/src/components/switch/switch.tsx +101 -0
  222. package/src/components/table/table.meta.md +95 -0
  223. package/src/components/table/table.stories.tsx +75 -0
  224. package/src/components/table/table.tsx +122 -0
  225. package/src/components/tabs/tabs.meta.md +98 -0
  226. package/src/components/tabs/tabs.stories.tsx +70 -0
  227. package/src/components/tabs/tabs.tsx +119 -0
  228. package/src/components/tag/tag.meta.md +94 -0
  229. package/src/components/tag/tag.stories.tsx +77 -0
  230. package/src/components/tag/tag.tsx +185 -0
  231. package/src/components/textarea/textarea.meta.md +83 -0
  232. package/src/components/textarea/textarea.stories.tsx +63 -0
  233. package/src/components/textarea/textarea.tsx +113 -0
  234. package/src/components/time-picker/time-picker.meta.md +83 -0
  235. package/src/components/time-picker/time-picker.stories.tsx +59 -0
  236. package/src/components/time-picker/time-picker.tsx +94 -0
  237. package/src/components/timeline/timeline.meta.md +102 -0
  238. package/src/components/timeline/timeline.stories.tsx +104 -0
  239. package/src/components/timeline/timeline.tsx +147 -0
  240. package/src/components/toggle/toggle.meta.md +88 -0
  241. package/src/components/toggle/toggle.stories.tsx +66 -0
  242. package/src/components/toggle/toggle.tsx +53 -0
  243. package/src/components/toggle-group/toggle-group.meta.md +90 -0
  244. package/src/components/toggle-group/toggle-group.stories.tsx +83 -0
  245. package/src/components/toggle-group/toggle-group.tsx +78 -0
  246. package/src/components/tooltip/tooltip.meta.md +99 -0
  247. package/src/components/tooltip/tooltip.stories.tsx +71 -0
  248. package/src/components/tooltip/tooltip.tsx +93 -0
  249. package/src/components/tour/tour.meta.md +116 -0
  250. package/src/components/tour/tour.stories.tsx +66 -0
  251. package/src/components/tour/tour.tsx +242 -0
  252. package/src/components/transfer/transfer.meta.md +90 -0
  253. package/src/components/transfer/transfer.stories.tsx +68 -0
  254. package/src/components/transfer/transfer.tsx +251 -0
  255. package/src/components/tree/tree.meta.md +111 -0
  256. package/src/components/tree/tree.stories.tsx +109 -0
  257. package/src/components/tree/tree.tsx +367 -0
  258. package/src/components/tree-select/tree-select.meta.md +100 -0
  259. package/src/components/tree-select/tree-select.stories.tsx +80 -0
  260. package/src/components/tree-select/tree-select.tsx +171 -0
  261. package/src/components/typography/typography.meta.md +102 -0
  262. package/src/components/typography/typography.stories.tsx +115 -0
  263. package/src/components/typography/typography.tsx +245 -0
  264. package/src/components/upload/upload.meta.md +111 -0
  265. package/src/components/upload/upload.stories.tsx +75 -0
  266. package/src/components/upload/upload.tsx +265 -0
  267. package/src/components/watermark/watermark.meta.md +95 -0
  268. package/src/components/watermark/watermark.stories.tsx +78 -0
  269. package/src/components/watermark/watermark.tsx +165 -0
  270. package/src/utils/cn.ts +6 -0
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@teamix-evo/ui",
3
+ "version": "0.1.1",
4
+ "description": "Source-injected UI components for Teamix Evo (shadcn-based, antd capabilities)",
5
+ "type": "module",
6
+ "files": [
7
+ "manifest.json",
8
+ "_data.json",
9
+ "src",
10
+ "README.md"
11
+ ],
12
+ "peerDependencies": {
13
+ "react": ">=18",
14
+ "react-dom": ">=18"
15
+ },
16
+ "devDependencies": {
17
+ "@hookform/resolvers": "^3",
18
+ "@radix-ui/react-accordion": "^1",
19
+ "@radix-ui/react-alert-dialog": "^1",
20
+ "@radix-ui/react-aspect-ratio": "^1",
21
+ "@radix-ui/react-avatar": "^1",
22
+ "@radix-ui/react-checkbox": "^1",
23
+ "@radix-ui/react-collapsible": "^1",
24
+ "@radix-ui/react-context-menu": "^2",
25
+ "@radix-ui/react-dialog": "^1",
26
+ "@radix-ui/react-dropdown-menu": "^2",
27
+ "@radix-ui/react-hover-card": "^1",
28
+ "@radix-ui/react-label": "^2",
29
+ "@radix-ui/react-menubar": "^1",
30
+ "@radix-ui/react-navigation-menu": "^1",
31
+ "@radix-ui/react-popover": "^1",
32
+ "@radix-ui/react-progress": "^1",
33
+ "@radix-ui/react-radio-group": "^1",
34
+ "@radix-ui/react-scroll-area": "^1",
35
+ "@radix-ui/react-select": "^2",
36
+ "@radix-ui/react-separator": "^1",
37
+ "@radix-ui/react-slider": "^1",
38
+ "@radix-ui/react-slot": "^1.1.0",
39
+ "@radix-ui/react-switch": "^1",
40
+ "@radix-ui/react-tabs": "^1",
41
+ "@radix-ui/react-toggle": "^1",
42
+ "@radix-ui/react-toggle-group": "^1",
43
+ "@radix-ui/react-tooltip": "^1",
44
+ "@storybook/addon-essentials": "^8",
45
+ "@storybook/react": "^8",
46
+ "@storybook/react-vite": "^8",
47
+ "@tailwindcss/vite": "^4",
48
+ "@tanstack/react-table": "^8",
49
+ "@types/react": "^18.3.0",
50
+ "@types/react-dom": "^18.3.0",
51
+ "@vitejs/plugin-react": "^4.3.0",
52
+ "class-variance-authority": "^0.7.0",
53
+ "clsx": "^2.1.0",
54
+ "cmdk": "^1",
55
+ "date-fns": "^3",
56
+ "embla-carousel-react": "^8",
57
+ "eslint": "^9.0.0",
58
+ "input-otp": "^1",
59
+ "lucide-react": "^0.460.0",
60
+ "react": "^18.3.0",
61
+ "react-day-picker": "^9",
62
+ "react-dom": "^18.3.0",
63
+ "react-hook-form": "^7",
64
+ "react-resizable-panels": "^2",
65
+ "sonner": "^1",
66
+ "storybook": "^8",
67
+ "tailwind-merge": "^2.5.0",
68
+ "tailwindcss": "^4",
69
+ "ts-morph": "^22",
70
+ "tsx": "^4.0.0",
71
+ "vaul": "^1",
72
+ "vite": "^5.4.0",
73
+ "vite-tsconfig-paths": "^6.1.1",
74
+ "zod": "^3",
75
+ "@teamix-evo/eslint-config": "0.1.0",
76
+ "@teamix-evo/registry": "0.2.0",
77
+ "@teamix-evo/design": "^0.2.0"
78
+ },
79
+ "scripts": {
80
+ "validate": "tsx scripts/validate-entries.ts",
81
+ "gen:meta": "tsx scripts/generate-meta.ts",
82
+ "gen:check": "tsx scripts/generate-meta.ts --check",
83
+ "test": "echo 'validate only' && pnpm validate",
84
+ "typecheck": "tsc --noEmit",
85
+ "lint": "eslint .",
86
+ "build": "echo 'pure resource package, no build needed'",
87
+ "storybook": "storybook dev -p 6006",
88
+ "build-storybook": "storybook build"
89
+ }
90
+ }
@@ -0,0 +1,87 @@
1
+ ---
2
+ id: accordion
3
+ name: Accordion
4
+ type: component
5
+ category: navigation
6
+ since: 0.1.0
7
+ package: "@teamix-evo/ui"
8
+ ---
9
+
10
+ # Accordion
11
+
12
+ 折叠面板 — Radix Accordion + antd Collapse 的 `accordion` 模式(`type="single"` 即单展开)。
13
+ **与 Collapsible 区别**:Accordion 是**多 item 列表**,可单展开 / 多展开;Collapsible 是单个区域的展开收起。
14
+
15
+ ## When to use
16
+
17
+ - FAQ 列表
18
+ - 表单分组(高级选项 / 联系方式 / 隐私偏好)
19
+ - 长内容分章节折叠
20
+
21
+ ## When NOT to use
22
+
23
+ - 单区域折叠 → `Collapsible`
24
+ - 平级 tab 切换 → `Tabs`
25
+ - 列表项的展开内容 → `Table` 的 expandable row
26
+
27
+ ## Props
28
+
29
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。
30
+
31
+ <!-- auto:props:begin -->
32
+ _(组件无 `<Name>Props` interface — props 详见 [`accordion.tsx`](./accordion.tsx))_
33
+ <!-- auto:props:end -->
34
+
35
+ ## 依赖
36
+
37
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
38
+
39
+ <!-- auto:deps:begin -->
40
+ ### 同库依赖
41
+
42
+ > `teamix-evo ui add accordion` 时,以下 entry 会被自动连带安装(无需手动 add)。
43
+
44
+ | Entry | 类型 | 描述 |
45
+ | --- | --- | --- |
46
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
47
+
48
+ ### npm 依赖
49
+
50
+ > 业务侧需要先 `pnpm add` / `npm install` 这些包。CLI 在 `ui add` 完成后会列出此提示。
51
+
52
+ ```bash
53
+ pnpm add @radix-ui/react-accordion@^1.2.0 lucide-react@^0.460.0
54
+ ```
55
+ <!-- auto:deps:end -->
56
+
57
+ > 子组件:`Accordion`(Root,需 `type="single"` 或 `"multiple"`)/ `AccordionItem` / `AccordionTrigger` / `AccordionContent`。
58
+
59
+ ## AI 生成纪律
60
+
61
+ - **`type` 必传**:`"single"`(单展开,可选 `collapsible` 让用户折叠)/ `"multiple"`(多展开)
62
+ - **每项 value 唯一**:用稳定 ID
63
+ - **AccordionTrigger 默认带 ChevronDown**:展开时 180° 翻转,**不要**自行加图标
64
+ - **单展开 + collapsible**:`type="single" collapsible` 才能让"再次点击当前项"折叠;不加只能在 item 间切换
65
+
66
+ ## Examples
67
+
68
+ ```tsx
69
+ import {
70
+ Accordion, AccordionItem, AccordionTrigger, AccordionContent,
71
+ } from '@/components/ui/accordion';
72
+
73
+ // 单展开(可折叠)
74
+ <Accordion type="single" collapsible className="w-96">
75
+ <AccordionItem value="item-1">
76
+ <AccordionTrigger>什么是 Teamix Evo?</AccordionTrigger>
77
+ <AccordionContent>面向产品研发的 AI Coding 套件...</AccordionContent>
78
+ </AccordionItem>
79
+ <AccordionItem value="item-2">
80
+ <AccordionTrigger>如何安装?</AccordionTrigger>
81
+ <AccordionContent>npx teamix-evo design init opentrek</AccordionContent>
82
+ </AccordionItem>
83
+ </Accordion>
84
+
85
+ // 多展开
86
+ <Accordion type="multiple" defaultValue={['a', 'b']}>...</Accordion>
87
+ ```
@@ -0,0 +1,67 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import {
3
+ Accordion,
4
+ AccordionItem,
5
+ AccordionTrigger,
6
+ AccordionContent,
7
+ } from './accordion';
8
+
9
+ const meta: Meta<typeof Accordion> = {
10
+ title: '导航 · Navigation/Accordion',
11
+ component: Accordion,
12
+ tags: ['autodocs'],
13
+ };
14
+
15
+ export default meta;
16
+ type Story = StoryObj<typeof Accordion>;
17
+
18
+ export const Single: Story = {
19
+ render: () => (
20
+ <Accordion type="single" collapsible className="w-96">
21
+ <AccordionItem value="item-1">
22
+ <AccordionTrigger>什么是 Teamix Evo?</AccordionTrigger>
23
+ <AccordionContent>
24
+ 面向产品研发场景的 AI Coding 套件,提供设计体系、技能、组件、文档等可装配资产。
25
+ </AccordionContent>
26
+ </AccordionItem>
27
+ <AccordionItem value="item-2">
28
+ <AccordionTrigger>如何安装?</AccordionTrigger>
29
+ <AccordionContent>
30
+ <code className="rounded bg-muted px-1.5 py-0.5">
31
+ npx teamix-evo design init opentrek
32
+ </code>
33
+ </AccordionContent>
34
+ </AccordionItem>
35
+ <AccordionItem value="item-3">
36
+ <AccordionTrigger>可以同时支持多个 IDE 吗?</AccordionTrigger>
37
+ <AccordionContent>
38
+ 可以,Skills 同时支持 Qoder 和 Claude Code(同源 SKILL.md 格式)。
39
+ </AccordionContent>
40
+ </AccordionItem>
41
+ </Accordion>
42
+ ),
43
+ };
44
+
45
+ export const Multiple: Story = {
46
+ parameters: { controls: { disable: true } },
47
+ render: () => (
48
+ <Accordion
49
+ type="multiple"
50
+ defaultValue={['a', 'b']}
51
+ className="w-96"
52
+ >
53
+ <AccordionItem value="a">
54
+ <AccordionTrigger>分组 A</AccordionTrigger>
55
+ <AccordionContent>分组 A 的内容</AccordionContent>
56
+ </AccordionItem>
57
+ <AccordionItem value="b">
58
+ <AccordionTrigger>分组 B</AccordionTrigger>
59
+ <AccordionContent>分组 B 的内容</AccordionContent>
60
+ </AccordionItem>
61
+ <AccordionItem value="c">
62
+ <AccordionTrigger>分组 C</AccordionTrigger>
63
+ <AccordionContent>分组 C 的内容</AccordionContent>
64
+ </AccordionItem>
65
+ </Accordion>
66
+ ),
67
+ };
@@ -0,0 +1,58 @@
1
+ import * as React from 'react';
2
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
3
+ import { ChevronDown } from 'lucide-react';
4
+
5
+ import { cn } from '@/utils/cn';
6
+
7
+ const Accordion = AccordionPrimitive.Root;
8
+ export type AccordionProps = React.ComponentPropsWithoutRef<
9
+ typeof AccordionPrimitive.Root
10
+ >;
11
+
12
+ const AccordionItem = React.forwardRef<
13
+ React.ElementRef<typeof AccordionPrimitive.Item>,
14
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
15
+ >(({ className, ...props }, ref) => (
16
+ <AccordionPrimitive.Item
17
+ ref={ref}
18
+ className={cn('border-b', className)}
19
+ {...props}
20
+ />
21
+ ));
22
+ AccordionItem.displayName = 'AccordionItem';
23
+
24
+ const AccordionTrigger = React.forwardRef<
25
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
26
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
27
+ >(({ className, children, ...props }, ref) => (
28
+ <AccordionPrimitive.Header className="flex">
29
+ <AccordionPrimitive.Trigger
30
+ ref={ref}
31
+ className={cn(
32
+ 'flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180',
33
+ className,
34
+ )}
35
+ {...props}
36
+ >
37
+ {children}
38
+ <ChevronDown className="size-4 shrink-0 text-muted-foreground transition-transform duration-200" />
39
+ </AccordionPrimitive.Trigger>
40
+ </AccordionPrimitive.Header>
41
+ ));
42
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
43
+
44
+ const AccordionContent = React.forwardRef<
45
+ React.ElementRef<typeof AccordionPrimitive.Content>,
46
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
47
+ >(({ className, children, ...props }, ref) => (
48
+ <AccordionPrimitive.Content
49
+ ref={ref}
50
+ className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
51
+ {...props}
52
+ >
53
+ <div className={cn('pb-4 pt-0', className)}>{children}</div>
54
+ </AccordionPrimitive.Content>
55
+ ));
56
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
57
+
58
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -0,0 +1,80 @@
1
+ ---
2
+ id: affix
3
+ name: Affix
4
+ type: component
5
+ category: navigation
6
+ since: 0.1.0
7
+ package: "@teamix-evo/ui"
8
+ ---
9
+
10
+ # Affix
11
+
12
+ 滚动吸顶 / 吸底 — antd 独有补足。**等价 antd `Affix`**。当容器滚出指定偏移时,把 children 切换为 `position: fixed`,保留原占位避免页面跳动。监听 `scroll` 事件 + `getBoundingClientRect()`,无第三方依赖。
13
+
14
+ ## When to use
15
+
16
+ - 表格操作栏在滚动时吸顶(批量删除 / 导出)
17
+ - 长表单的"提交"按钮在底部时吸顶
18
+ - 文档侧边的目录/锚点导航
19
+ - 落地页 CTA(吸顶 / 吸底"立即注册")
20
+
21
+ ## When NOT to use
22
+
23
+ - 整页 header → 直接 `position: sticky` 配 Tailwind `sticky top-0` 更轻
24
+ - 弹窗内的吸附 → Drawer / Sheet 已有内置
25
+ - 一页超过 1 个 Affix:容易形成"漂浮屏",有损可读性
26
+
27
+ <!-- auto:props:begin -->
28
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
29
+ | --- | --- | --- | --- | --- |
30
+ | `offsetTop` | `number` | `0` | – | 滚动到此偏移量(相对视口顶部)时开始吸顶,单位 px。 |
31
+ | `offsetBottom` | `number` | – | – | 滚动到此偏移量(相对视口底部)时开始吸底 — 与 `offsetTop` 互斥。 |
32
+ | `onAffixChange` | `(affixed: boolean) => void` | – | – | 吸附状态变化回调(antd `onChange` 并集)。 |
33
+ <!-- auto:props:end -->
34
+
35
+ <!-- auto:deps:begin -->
36
+ ### 同库依赖
37
+
38
+ > `teamix-evo ui add affix` 时,以下 entry 会被自动连带安装(无需手动 add)。
39
+
40
+ | Entry | 类型 | 描述 |
41
+ | --- | --- | --- |
42
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
43
+
44
+ ### npm 依赖
45
+
46
+ _无 — 本组件不依赖任何 npm 包。_
47
+ <!-- auto:deps:end -->
48
+
49
+ ## AI 生成纪律
50
+
51
+ - **一页 ≤ 1 个 Affix** — 滥用会让页面充满浮动元素,极差体验
52
+ - **`offsetTop` 与 `offsetBottom` 互斥** — 同时传时优先 `offsetBottom`(吸底)
53
+ - **优先用 Tailwind `sticky top-N`** — 大部分"吸附顶部"用 sticky 就够,只有需要"超出容器边界仍跟随视口"才用 Affix
54
+ - **不要让 Affix 包裹复杂动态高度内容** — width / height 是按初次渲染算的,内容剧烈变化会失同步
55
+ - **`zIndex` 默认 10** — 与 Sonner toast(z=9999)、Dialog(z=50)等级别错开;如需更高自行 className 覆盖
56
+
57
+ ## Examples
58
+
59
+ ```tsx
60
+ import { Affix } from '@/components/ui/affix';
61
+ import { Button } from '@/components/ui/button';
62
+
63
+ // 吸顶
64
+ <Affix offsetTop={64}>
65
+ <div className="rounded-md border bg-card p-3 shadow-sm">
66
+ <Button>导出全部</Button>
67
+ <Button variant="outline">批量删除</Button>
68
+ </div>
69
+ </Affix>
70
+
71
+ // 吸底
72
+ <Affix offsetBottom={24}>
73
+ <Button block>立即提交</Button>
74
+ </Affix>
75
+
76
+ // 监听状态变化
77
+ <Affix offsetTop={0} onAffixChange={(affixed) => console.log('affixed:', affixed)}>
78
+ <Toolbar />
79
+ </Affix>
80
+ ```
@@ -0,0 +1,57 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { Affix } from './affix';
3
+ import { Button } from '@/components/button/button';
4
+
5
+ const meta: Meta<typeof Affix> = {
6
+ title: '导航 · Navigation/Affix',
7
+ component: Affix,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ '滚动吸顶 / 吸底 — 当容器滚出指定偏移时把 children 切换为 position: fixed,保留原占位。基于 scroll 事件 + getBoundingClientRect。等价 antd `Affix`。视觉走 OpenTrek tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
14
+ },
15
+ },
16
+ },
17
+ argTypes: {
18
+ offsetTop: { control: 'number' },
19
+ },
20
+ args: { offsetTop: 0 },
21
+ };
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof Affix>;
25
+
26
+ export const Playground: Story = {
27
+ parameters: { controls: { disable: true } },
28
+ render: () => (
29
+ <div className="space-y-3">
30
+ <div className="rounded-md border p-4 text-sm text-muted-foreground">
31
+ ↓ 在 Storybook 容器内滚动以触发吸顶
32
+ </div>
33
+ <div className="h-64 rounded-md border bg-muted/30 p-4">占位 1</div>
34
+ <Affix offsetTop={0}>
35
+ <div className="rounded-md border bg-card p-3 shadow-sm">
36
+ <Button>吸顶按钮</Button>
37
+ </div>
38
+ </Affix>
39
+ <div className="h-[800px] rounded-md border bg-muted/30 p-4">长占位</div>
40
+ </div>
41
+ ),
42
+ };
43
+
44
+ export const Bottom: Story = {
45
+ parameters: { controls: { disable: true } },
46
+ render: () => (
47
+ <div className="space-y-3">
48
+ <div className="h-[600px] rounded-md border bg-muted/30 p-4">向下滚动</div>
49
+ <Affix offsetBottom={24}>
50
+ <div className="rounded-md border bg-card p-3 shadow-sm">
51
+ <Button block>立即提交(吸底)</Button>
52
+ </div>
53
+ </Affix>
54
+ <div className="h-[600px] rounded-md border bg-muted/30 p-4">滚到底</div>
55
+ </div>
56
+ ),
57
+ };
@@ -0,0 +1,97 @@
1
+ import * as React from 'react';
2
+
3
+ import { cn } from '@/utils/cn';
4
+
5
+ export interface AffixProps extends React.HTMLAttributes<HTMLDivElement> {
6
+ /**
7
+ * 滚动到此偏移量(相对视口顶部)时开始吸顶,单位 px。
8
+ * @default 0
9
+ */
10
+ offsetTop?: number;
11
+ /**
12
+ * 滚动到此偏移量(相对视口底部)时开始吸底 — 与 `offsetTop` 互斥。
13
+ */
14
+ offsetBottom?: number;
15
+ /**
16
+ * 吸附状态变化回调(antd `onChange` 并集)。
17
+ */
18
+ onAffixChange?: (affixed: boolean) => void;
19
+ }
20
+
21
+ /**
22
+ * 滚动吸顶 / 吸底 — antd 独有补足。**等价 antd `Affix`**。
23
+ * 当容器滚出指定偏移时,把 children 切换为 `position: fixed`,保留原占位避免页面跳动。
24
+ *
25
+ * 实现:监听 `scroll` 事件 + 节点 `getBoundingClientRect()`,无依赖。
26
+ * **务必慎用** — 滥用 Affix 会让页面充满浮动元素,通常一页 ≤ 1 个。
27
+ */
28
+ const Affix = React.forwardRef<HTMLDivElement, AffixProps>(
29
+ (
30
+ {
31
+ offsetTop = 0,
32
+ offsetBottom,
33
+ onAffixChange,
34
+ className,
35
+ style,
36
+ children,
37
+ ...props
38
+ },
39
+ ref,
40
+ ) => {
41
+ const wrapperRef = React.useRef<HTMLDivElement | null>(null);
42
+ React.useImperativeHandle(ref, () => wrapperRef.current as HTMLDivElement);
43
+ const [affixed, setAffixed] = React.useState(false);
44
+ const [size, setSize] = React.useState<{ w: number; h: number }>({ w: 0, h: 0 });
45
+
46
+ React.useEffect(() => {
47
+ const el = wrapperRef.current;
48
+ if (!el) return;
49
+
50
+ const compute = () => {
51
+ const rect = el.getBoundingClientRect();
52
+ const useBottom = typeof offsetBottom === 'number';
53
+ const shouldAffix = useBottom
54
+ ? window.innerHeight - rect.bottom < (offsetBottom ?? 0)
55
+ : rect.top < offsetTop;
56
+ if (shouldAffix !== affixed) {
57
+ setAffixed(shouldAffix);
58
+ onAffixChange?.(shouldAffix);
59
+ }
60
+ setSize({ w: rect.width, h: rect.height });
61
+ };
62
+
63
+ compute();
64
+ window.addEventListener('scroll', compute, { passive: true });
65
+ window.addEventListener('resize', compute);
66
+ return () => {
67
+ window.removeEventListener('scroll', compute);
68
+ window.removeEventListener('resize', compute);
69
+ };
70
+ }, [affixed, offsetBottom, offsetTop, onAffixChange]);
71
+
72
+ const fixedStyle: React.CSSProperties | undefined = affixed
73
+ ? {
74
+ position: 'fixed',
75
+ top: typeof offsetBottom === 'number' ? undefined : offsetTop,
76
+ bottom: typeof offsetBottom === 'number' ? offsetBottom : undefined,
77
+ width: size.w,
78
+ zIndex: 10,
79
+ }
80
+ : undefined;
81
+
82
+ return (
83
+ <div
84
+ ref={wrapperRef}
85
+ style={{ ...style, height: affixed ? size.h : undefined }}
86
+ className={className}
87
+ >
88
+ <div style={fixedStyle} className={cn(affixed && 'shadow-sm')} {...props}>
89
+ {children}
90
+ </div>
91
+ </div>
92
+ );
93
+ },
94
+ );
95
+ Affix.displayName = 'Affix';
96
+
97
+ export { Affix };
@@ -0,0 +1,101 @@
1
+ ---
2
+ id: alert
3
+ name: Alert
4
+ type: component
5
+ category: feedback
6
+ since: 0.1.0
7
+ package: "@teamix-evo/ui"
8
+ ---
9
+
10
+ # Alert
11
+
12
+ 静态提示条 — shadcn 简约视觉 + antd 的 `type / showIcon / closable / banner` 并集。
13
+ **inline 形态**,与对话框 / Toast 不同,常驻在页面上方或表单上方。
14
+
15
+ ## When to use
16
+
17
+ - 表单提交前的提示(必填项 / 操作不可逆)
18
+ - 页面级公告(banner 模式)
19
+ - 长任务的状态提示(开始 / 进行中 / 失败)
20
+
21
+ ## When NOT to use
22
+
23
+ - 短暂提示 → 用 `Sonner`(Toast,自动消失)
24
+ - 阻断式确认 → 用 `AlertDialog`
25
+ - 表单字段错误 → 字段下方 `<p className="text-destructive text-sm">...</p>`
26
+
27
+ ## Props
28
+
29
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。
30
+
31
+ <!-- auto:props:begin -->
32
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
33
+ | --- | --- | --- | --- | --- |
34
+ | `type` | `'info' \| 'success' \| 'warning' \| 'error'` | `"info"` | – | 类型(antd `type` 并集)— 控制语义色与默认图标。 |
35
+ | `showIcon` | `boolean` | `true` | – | 是否显示图标(antd `showIcon` 并集)。 |
36
+ | `closable` | `boolean` | `false` | – | 是否可关闭,显示右侧 X 按钮(antd `closable` 并集)。 |
37
+ | `onClose` | `() => void` | – | – | 关闭按钮点击回调。 |
38
+ | `banner` | `boolean` | `false` | – | Banner 模式 — 去除横向圆角,沿屏幕宽度铺满,常用于全局公告条。 |
39
+ | `title` | `React.ReactNode` | – | – | 标题(粗体行)。 |
40
+ | `description` | `React.ReactNode` | – | – | 描述(标题下方主体内容)。 |
41
+ <!-- auto:props:end -->
42
+
43
+ ## 依赖
44
+
45
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
46
+
47
+ <!-- auto:deps:begin -->
48
+ ### 同库依赖
49
+
50
+ > `teamix-evo ui add alert` 时,以下 entry 会被自动连带安装(无需手动 add)。
51
+
52
+ | Entry | 类型 | 描述 |
53
+ | --- | --- | --- |
54
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
55
+
56
+ ### npm 依赖
57
+
58
+ > 业务侧需要先 `pnpm add` / `npm install` 这些包。CLI 在 `ui add` 完成后会列出此提示。
59
+
60
+ ```bash
61
+ pnpm add class-variance-authority@^0.7.0 lucide-react@^0.460.0
62
+ ```
63
+ <!-- auto:deps:end -->
64
+
65
+ ## AI 生成纪律
66
+
67
+ - **`type` 反映业务语义**:`error` 仅用于真正错误,**不要**滥用红色制造紧张感
68
+ - **`title` + `description` 一对**:无 title 直接 description 是反模式;一个 Alert 至少要有 title 让用户判断重要性
69
+ - **`closable` 配 `onClose` 持久化**:用户关闭后下次刷新别再出现 — 用 localStorage 记忆
70
+ - **`banner` 模式只放页面顶部**:不要在卡片内 banner
71
+ - **不嵌套 button 链接**:Alert 内放交互链接用 `<a className="underline">`,不要塞 Button — 视觉过重
72
+
73
+ ## Examples
74
+
75
+ ```tsx
76
+ import { Alert } from '@/components/ui/alert';
77
+
78
+ // 基本
79
+ <Alert type="info" title="提示" description="数据将在 10 分钟后刷新。" />
80
+
81
+ // 成功
82
+ <Alert type="success" title="保存成功" />
83
+
84
+ // 警告 + 可关闭
85
+ <Alert type="warning" title="账号即将过期" description="请在 7 天内续费。" closable />
86
+
87
+ // 错误
88
+ <Alert type="error" title="提交失败" description="请检查网络连接后重试。" />
89
+
90
+ // 无图标
91
+ <Alert type="info" showIcon={false} description="纯文本提示" />
92
+
93
+ // Banner 全局公告
94
+ <Alert
95
+ type="warning"
96
+ banner
97
+ title="系统维护"
98
+ description="本站将于 02:00 起暂停服务 30 分钟。"
99
+ closable
100
+ />
101
+ ```