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