@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
@@ -0,0 +1,82 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import {
3
+ Sheet,
4
+ SheetTrigger,
5
+ SheetContent,
6
+ SheetHeader,
7
+ SheetTitle,
8
+ SheetDescription,
9
+ SheetFooter,
10
+ SheetClose,
11
+ } from './sheet';
12
+ import { Button } from '@/components/button/button';
13
+
14
+ const meta: Meta<typeof SheetContent> = {
15
+ title: '反馈与浮层 · Feedback/Sheet',
16
+ component: SheetContent,
17
+ tags: ['autodocs'],
18
+ parameters: {
19
+ docs: {
20
+ description: {
21
+ component:
22
+ '侧边抽屉 — 从屏幕边缘滑入的补充内容面板,补充主区不中断主流程。语义上是 Dialog 的表弟但定位于边缘,对齐 antd `Drawer`;Radix Dialog 内核实现 + shadcn `Sheet` 的 `side` 变体 (top / right / bottom / left) 。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
23
+ },
24
+ },
25
+ },
26
+ argTypes: {
27
+ side: {
28
+ control: 'inline-radio',
29
+ options: ['top', 'right', 'bottom', 'left'],
30
+ },
31
+ },
32
+ args: { side: 'right' },
33
+ };
34
+
35
+ export default meta;
36
+ type Story = StoryObj<typeof SheetContent>;
37
+
38
+ export const Playground: Story = {
39
+ render: (args) => (
40
+ <Sheet>
41
+ <SheetTrigger asChild>
42
+ <Button variant="outline">打开 Sheet</Button>
43
+ </SheetTrigger>
44
+ <SheetContent {...args}>
45
+ <SheetHeader>
46
+ <SheetTitle>编辑资料</SheetTitle>
47
+ <SheetDescription>保存后立即生效。</SheetDescription>
48
+ </SheetHeader>
49
+ <div className="py-4 text-sm text-muted-foreground">
50
+ 表单字段放在这里...
51
+ </div>
52
+ <SheetFooter>
53
+ <SheetClose asChild>
54
+ <Button variant="outline">关闭</Button>
55
+ </SheetClose>
56
+ <Button>保存</Button>
57
+ </SheetFooter>
58
+ </SheetContent>
59
+ </Sheet>
60
+ ),
61
+ };
62
+
63
+ export const FourSides: Story = {
64
+ parameters: { controls: { disable: true } },
65
+ render: () => (
66
+ <div className="flex flex-wrap gap-3">
67
+ {(['top', 'right', 'bottom', 'left'] as const).map((s) => (
68
+ <Sheet key={s}>
69
+ <SheetTrigger asChild>
70
+ <Button variant="outline">{s}</Button>
71
+ </SheetTrigger>
72
+ <SheetContent side={s}>
73
+ <SheetHeader>
74
+ <SheetTitle>side = {s}</SheetTitle>
75
+ <SheetDescription>从 {s} 方向滑入。</SheetDescription>
76
+ </SheetHeader>
77
+ </SheetContent>
78
+ </Sheet>
79
+ ))}
80
+ </div>
81
+ ),
82
+ };
@@ -0,0 +1,139 @@
1
+ import * as React from 'react';
2
+ import * as SheetPrimitive from '@radix-ui/react-dialog';
3
+ import { cva, type VariantProps } from 'class-variance-authority';
4
+ import { X } from 'lucide-react';
5
+
6
+ import { cn } from '@/utils/cn';
7
+
8
+ const Sheet = SheetPrimitive.Root;
9
+ const SheetTrigger = SheetPrimitive.Trigger;
10
+ const SheetClose = SheetPrimitive.Close;
11
+ const SheetPortal = SheetPrimitive.Portal;
12
+
13
+ const SheetOverlay = React.forwardRef<
14
+ React.ElementRef<typeof SheetPrimitive.Overlay>,
15
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
16
+ >(({ className, ...props }, ref) => (
17
+ <SheetPrimitive.Overlay
18
+ ref={ref}
19
+ className={cn(
20
+ 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
21
+ className,
22
+ )}
23
+ {...props}
24
+ />
25
+ ));
26
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
27
+
28
+ const sheetVariants = cva(
29
+ 'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
30
+ {
31
+ variants: {
32
+ side: {
33
+ top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
34
+ bottom:
35
+ 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
36
+ left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
37
+ right:
38
+ 'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
39
+ },
40
+ },
41
+ defaultVariants: { side: 'right' },
42
+ },
43
+ );
44
+
45
+ export interface SheetContentProps
46
+ extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
47
+ VariantProps<typeof sheetVariants> {
48
+ /**
49
+ * 弹出方向(antd Drawer `placement` 并集)。
50
+ * @default "right"
51
+ */
52
+ side?: 'top' | 'right' | 'bottom' | 'left';
53
+ }
54
+
55
+ const SheetContent = React.forwardRef<
56
+ React.ElementRef<typeof SheetPrimitive.Content>,
57
+ SheetContentProps
58
+ >(({ side = 'right', className, children, ...props }, ref) => (
59
+ <SheetPortal>
60
+ <SheetOverlay />
61
+ <SheetPrimitive.Content
62
+ ref={ref}
63
+ className={cn(sheetVariants({ side }), className)}
64
+ {...props}
65
+ >
66
+ {children}
67
+ <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2">
68
+ <X className="size-4" />
69
+ <span className="sr-only">Close</span>
70
+ </SheetPrimitive.Close>
71
+ </SheetPrimitive.Content>
72
+ </SheetPortal>
73
+ ));
74
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
75
+
76
+ const SheetHeader = ({
77
+ className,
78
+ ...props
79
+ }: React.HTMLAttributes<HTMLDivElement>) => (
80
+ <div
81
+ className={cn(
82
+ 'flex flex-col space-y-2 text-center sm:text-left',
83
+ className,
84
+ )}
85
+ {...props}
86
+ />
87
+ );
88
+ SheetHeader.displayName = 'SheetHeader';
89
+
90
+ const SheetFooter = ({
91
+ className,
92
+ ...props
93
+ }: React.HTMLAttributes<HTMLDivElement>) => (
94
+ <div
95
+ className={cn(
96
+ 'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-2',
97
+ className,
98
+ )}
99
+ {...props}
100
+ />
101
+ );
102
+ SheetFooter.displayName = 'SheetFooter';
103
+
104
+ const SheetTitle = React.forwardRef<
105
+ React.ElementRef<typeof SheetPrimitive.Title>,
106
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
107
+ >(({ className, ...props }, ref) => (
108
+ <SheetPrimitive.Title
109
+ ref={ref}
110
+ className={cn('text-lg font-semibold text-foreground', className)}
111
+ {...props}
112
+ />
113
+ ));
114
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
115
+
116
+ const SheetDescription = React.forwardRef<
117
+ React.ElementRef<typeof SheetPrimitive.Description>,
118
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
119
+ >(({ className, ...props }, ref) => (
120
+ <SheetPrimitive.Description
121
+ ref={ref}
122
+ className={cn('text-sm text-muted-foreground', className)}
123
+ {...props}
124
+ />
125
+ ));
126
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
127
+
128
+ export {
129
+ Sheet,
130
+ SheetPortal,
131
+ SheetOverlay,
132
+ SheetTrigger,
133
+ SheetClose,
134
+ SheetContent,
135
+ SheetHeader,
136
+ SheetFooter,
137
+ SheetTitle,
138
+ SheetDescription,
139
+ };
@@ -0,0 +1,131 @@
1
+ ---
2
+ id: sidebar
3
+ name: Sidebar
4
+ type: component
5
+ category: navigation
6
+ since: 0.1.0
7
+ package: "@teamix-evo/ui"
8
+ ---
9
+
10
+ # Sidebar
11
+
12
+ 侧边导航栏 — shadcn 风格复合组件,**对应 antd `Layout.Sider + Menu`**。
13
+ **精简版**(MVP):涵盖 Provider + 折叠状态 + Header/Footer/Content + Menu + Trigger。
14
+ **未含**(留 v0.x):mobile sheet 自动切换、cookie 持久化、Rail(可拖拽折叠杆)、富 SubMenu 嵌套。
15
+
16
+ ## When to use
17
+
18
+ - 后台管理系统的侧边导航(项目列表 / 资源类目)
19
+ - 文档站 / 编辑器的侧边目录
20
+ - 多模块切换(配 SidebarMenuButton 的 isActive)
21
+
22
+ ## When NOT to use
23
+
24
+ - 顶部导航 → `NavigationMenu` / `Menubar`
25
+ - 临时面板 → `Sheet` / `Drawer`
26
+ - 单层简单菜单 → `Tabs`(垂直 orientation)
27
+
28
+ ## Props
29
+
30
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。下表是 `Sidebar` 主容器 props。
31
+
32
+ <!-- auto:props:begin -->
33
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
34
+ | --- | --- | --- | --- | --- |
35
+ | `side` | `'left' \| 'right'` | `"left"` | – | 侧边方向。 |
36
+ | `collapsible` | `'icon' \| 'offcanvas' \| 'none'` | `"icon"` | – | 折叠模式 — `icon` 折叠后只剩图标列(64px);`offcanvas` 完全收起(0px)。 |
37
+ | `width` | `string` | `"16rem"` | – | 展开宽度。 |
38
+ | `collapsedWidth` | `string` | `"3rem"` | – | 折叠后宽度(`collapsible="icon"` 时生效)。 |
39
+ <!-- auto:props:end -->
40
+
41
+ ## 依赖
42
+
43
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
44
+
45
+ <!-- auto:deps:begin -->
46
+ ### 同库依赖
47
+
48
+ > `teamix-evo ui add sidebar` 时,以下 entry 会被自动连带安装(无需手动 add)。
49
+
50
+ | Entry | 类型 | 描述 |
51
+ | --- | --- | --- |
52
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
53
+ | `button` | component | 通用按钮 — shadcn 实现 + antd 功能扩展(loading / icon / shape / block / dashed variant) |
54
+ | `separator` | component | 分隔线 — Radix Separator + antd Divider 的 dashed / 中间装饰文本 |
55
+
56
+ ### npm 依赖
57
+
58
+ > 业务侧需要先 `pnpm add` / `npm install` 这些包。CLI 在 `ui add` 完成后会列出此提示。
59
+
60
+ ```bash
61
+ pnpm add @radix-ui/react-slot@^1.1.0 class-variance-authority@^0.7.0 lucide-react@^0.460.0
62
+ ```
63
+ <!-- auto:deps:end -->
64
+
65
+ > 完整子组件:`SidebarProvider`(Context 容器,必装)/ `Sidebar`(主侧边栏)/ `SidebarHeader` / `SidebarFooter` / `SidebarContent`(中间滚动区)/ `SidebarGroup` + `SidebarGroupLabel` / `SidebarMenu` + `SidebarMenuItem` + `SidebarMenuButton`(支持 `isActive` / `asChild`)/ `SidebarSeparator` / `SidebarTrigger`(切换按钮)/ `SidebarInset`(主内容区)+ `useSidebar()` hook。
66
+
67
+ ## AI 生成纪律
68
+
69
+ - **必装 SidebarProvider**:Sidebar 上下层任何子组件都依赖 Context;通常在 Layout 顶层包裹
70
+ - **`SidebarMenuButton` 配 `asChild`**:wrap React Router / Next.js Link
71
+ - **`isActive` 由路由判断**:不要用 useState 自管;`pathname === href`
72
+ - **`collapsible="icon"` 默认**:折叠后保留图标列;`offcanvas` 完全收起;`none` 静态宽度
73
+ - **`SidebarInset` 与 Sidebar 配对**:`<SidebarProvider><Sidebar/><SidebarInset>main content</SidebarInset></SidebarProvider>`
74
+ - **菜单图标 first**:`<SidebarMenuButton><Icon /> 文字</SidebarMenuButton>`,顺序固定
75
+
76
+ ## Examples
77
+
78
+ ```tsx
79
+ import {
80
+ SidebarProvider, Sidebar, SidebarHeader, SidebarContent,
81
+ SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuItem,
82
+ SidebarMenuButton, SidebarFooter, SidebarTrigger, SidebarInset,
83
+ } from '@/components/ui/sidebar';
84
+ import { Home, Settings, Inbox, Users } from 'lucide-react';
85
+
86
+ const items = [
87
+ { title: '首页', url: '/', icon: Home },
88
+ { title: '收件箱', url: '/inbox', icon: Inbox },
89
+ { title: '团队', url: '/team', icon: Users },
90
+ { title: '设置', url: '/settings', icon: Settings },
91
+ ];
92
+
93
+ function AppLayout({ children }: { children: React.ReactNode }) {
94
+ return (
95
+ <SidebarProvider>
96
+ <Sidebar>
97
+ <SidebarHeader>
98
+ <h1 className="px-2 text-sm font-semibold">Teamix Evo</h1>
99
+ </SidebarHeader>
100
+ <SidebarContent>
101
+ <SidebarGroup>
102
+ <SidebarGroupLabel>导航</SidebarGroupLabel>
103
+ <SidebarMenu>
104
+ {items.map((it) => (
105
+ <SidebarMenuItem key={it.title}>
106
+ <SidebarMenuButton asChild>
107
+ <a href={it.url}>
108
+ <it.icon />
109
+ <span>{it.title}</span>
110
+ </a>
111
+ </SidebarMenuButton>
112
+ </SidebarMenuItem>
113
+ ))}
114
+ </SidebarMenu>
115
+ </SidebarGroup>
116
+ </SidebarContent>
117
+ <SidebarFooter>
118
+ <p className="px-2 text-xs text-muted-foreground">v0.1.0</p>
119
+ </SidebarFooter>
120
+ </Sidebar>
121
+ <SidebarInset>
122
+ <header className="flex h-12 items-center gap-2 border-b px-4">
123
+ <SidebarTrigger />
124
+ <h2 className="text-sm font-medium">主内容区</h2>
125
+ </header>
126
+ <div className="p-6">{children}</div>
127
+ </SidebarInset>
128
+ </SidebarProvider>
129
+ );
130
+ }
131
+ ```
@@ -0,0 +1,82 @@
1
+ import * as React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { Home, Inbox, Settings, Users } from 'lucide-react';
4
+ import {
5
+ SidebarProvider,
6
+ Sidebar,
7
+ SidebarHeader,
8
+ SidebarContent,
9
+ SidebarGroup,
10
+ SidebarGroupLabel,
11
+ SidebarMenu,
12
+ SidebarMenuItem,
13
+ SidebarMenuButton,
14
+ SidebarFooter,
15
+ SidebarTrigger,
16
+ SidebarInset,
17
+ } from './sidebar';
18
+
19
+ const meta: Meta<typeof Sidebar> = {
20
+ title: '导航 · Navigation/Sidebar',
21
+ component: Sidebar,
22
+ tags: ['autodocs'],
23
+ parameters: { layout: 'fullscreen' },
24
+ };
25
+
26
+ export default meta;
27
+ type Story = StoryObj<typeof Sidebar>;
28
+
29
+ const items = [
30
+ { title: '首页', url: '#home', icon: Home },
31
+ { title: '收件箱', url: '#inbox', icon: Inbox },
32
+ { title: '团队', url: '#team', icon: Users },
33
+ { title: '设置', url: '#settings', icon: Settings },
34
+ ];
35
+
36
+ function DemoLayout({ active }: { active: string }) {
37
+ return (
38
+ <SidebarProvider>
39
+ <Sidebar>
40
+ <SidebarHeader>
41
+ <h1 className="px-2 text-sm font-semibold">Teamix Evo</h1>
42
+ </SidebarHeader>
43
+ <SidebarContent>
44
+ <SidebarGroup>
45
+ <SidebarGroupLabel>导航</SidebarGroupLabel>
46
+ <SidebarMenu>
47
+ {items.map((it) => (
48
+ <SidebarMenuItem key={it.title}>
49
+ <SidebarMenuButton
50
+ asChild
51
+ isActive={active === it.url}
52
+ >
53
+ <a href={it.url} onClick={(e) => e.preventDefault()}>
54
+ <it.icon />
55
+ <span>{it.title}</span>
56
+ </a>
57
+ </SidebarMenuButton>
58
+ </SidebarMenuItem>
59
+ ))}
60
+ </SidebarMenu>
61
+ </SidebarGroup>
62
+ </SidebarContent>
63
+ <SidebarFooter>
64
+ <p className="px-2 text-xs text-muted-foreground">v0.1.0</p>
65
+ </SidebarFooter>
66
+ </Sidebar>
67
+ <SidebarInset>
68
+ <header className="flex h-12 items-center gap-2 border-b px-4">
69
+ <SidebarTrigger />
70
+ <h2 className="text-sm font-medium">主内容区</h2>
71
+ </header>
72
+ <div className="flex-1 p-6 text-sm text-muted-foreground">
73
+ 点击左上角图标可折叠 / 展开 Sidebar。
74
+ </div>
75
+ </SidebarInset>
76
+ </SidebarProvider>
77
+ );
78
+ }
79
+
80
+ export const Default: Story = {
81
+ render: () => <DemoLayout active="#home" />,
82
+ };