@teamix-evo/ui 0.2.0 → 0.4.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 +695 -487
- package/package.json +16 -10
- package/src/components/accordion/accordion.meta.md +5 -9
- package/src/components/accordion/accordion.stories.tsx +3 -3
- package/src/components/accordion/accordion.tsx +104 -8
- package/src/components/affix/affix.meta.md +21 -12
- package/src/components/affix/affix.stories.tsx +101 -26
- package/src/components/affix/affix.tsx +79 -9
- package/src/components/alert/alert.meta.md +52 -26
- 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 +48 -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 +10 -14
- package/src/components/anchor/anchor.stories.tsx +3 -3
- package/src/components/anchor/anchor.tsx +2 -2
- package/src/components/app/app.meta.md +10 -14
- package/src/components/app/app.stories.tsx +6 -6
- package/src/components/aspect-ratio/aspect-ratio.meta.md +4 -8
- package/src/components/aspect-ratio/aspect-ratio.stories.tsx +3 -3
- package/src/components/auto-complete/auto-complete.meta.md +19 -20
- package/src/components/auto-complete/auto-complete.stories.tsx +44 -3
- package/src/components/auto-complete/auto-complete.tsx +119 -71
- package/src/components/avatar/avatar.meta.md +9 -22
- package/src/components/avatar/avatar.stories.tsx +21 -3
- package/src/components/avatar/avatar.tsx +24 -23
- package/src/components/badge/badge.meta.md +14 -18
- package/src/components/badge/badge.stories.tsx +2 -2
- package/src/components/badge/badge.tsx +2 -2
- package/src/components/breadcrumb/breadcrumb.meta.md +29 -20
- package/src/components/breadcrumb/breadcrumb.stories.tsx +120 -5
- package/src/components/breadcrumb/breadcrumb.tsx +22 -8
- package/src/components/button/button.meta.md +261 -29
- package/src/components/button/button.stories.tsx +549 -41
- package/src/components/button/button.tsx +341 -35
- package/src/components/calendar/calendar.meta.md +19 -14
- package/src/components/calendar/calendar.stories.tsx +5 -5
- package/src/components/calendar/calendar.tsx +73 -8
- package/src/components/card/card.meta.md +31 -34
- package/src/components/card/card.stories.tsx +34 -3
- package/src/components/card/card.tsx +147 -63
- package/src/components/carousel/carousel.meta.md +10 -14
- package/src/components/carousel/carousel.stories.tsx +1 -1
- package/src/components/cascader/cascader.meta.md +43 -22
- package/src/components/cascader/cascader.stories.tsx +13 -2
- package/src/components/cascader/cascader.tsx +439 -89
- package/src/components/checkbox/checkbox.meta.md +74 -24
- package/src/components/checkbox/checkbox.stories.tsx +160 -2
- package/src/components/checkbox/checkbox.tsx +79 -9
- package/src/components/collapsible/collapsible.meta.md +7 -6
- package/src/components/collapsible/collapsible.stories.tsx +2 -2
- package/src/components/collapsible/collapsible.tsx +93 -6
- package/src/components/color-picker/color-picker.meta.md +16 -20
- package/src/components/color-picker/color-picker.stories.tsx +86 -7
- package/src/components/color-picker/color-picker.tsx +19 -9
- package/src/components/command/command.meta.md +7 -11
- package/src/components/command/command.stories.tsx +4 -4
- package/src/components/command/command.tsx +18 -7
- package/src/components/context-menu/context-menu.meta.md +5 -25
- package/src/components/context-menu/context-menu.stories.tsx +4 -4
- package/src/components/context-menu/context-menu.tsx +21 -8
- package/src/components/data-table/data-table.meta.md +14 -18
- package/src/components/data-table/data-table.stories.tsx +1 -1
- package/src/components/data-table/data-table.tsx +2 -2
- package/src/components/date-picker/date-picker.meta.md +90 -41
- 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 +12 -16
- package/src/components/descriptions/descriptions.stories.tsx +2 -2
- package/src/components/descriptions/descriptions.tsx +22 -14
- package/src/components/dialog/dialog.meta.md +67 -17
- 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 +27 -39
- package/src/components/drawer/drawer.stories.tsx +29 -12
- package/src/components/drawer/drawer.tsx +22 -114
- package/src/components/dropdown-menu/dropdown-menu.meta.md +64 -24
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +81 -3
- 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 +10 -14
- package/src/components/empty/empty.stories.tsx +3 -3
- package/src/components/empty/empty.tsx +10 -3
- package/src/components/field/field.meta.md +46 -25
- package/src/components/field/field.stories.tsx +380 -3
- 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 +1086 -0
- package/src/components/filter-bar/filter-bar.tsx +568 -0
- package/src/components/flex/flex.meta.md +59 -20
- package/src/components/flex/flex.stories.tsx +65 -10
- package/src/components/flex/flex.tsx +27 -4
- package/src/components/float-button/float-button.meta.md +10 -29
- package/src/components/float-button/float-button.stories.tsx +6 -6
- package/src/components/form/form.meta.md +31 -52
- package/src/components/form/form.stories.tsx +354 -4
- package/src/components/form/form.tsx +101 -35
- package/src/components/grid/grid.meta.md +4 -24
- package/src/components/grid/grid.stories.tsx +2 -2
- package/src/components/hover-card/hover-card.meta.md +9 -10
- package/src/components/hover-card/hover-card.stories.tsx +29 -4
- 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 +14 -18
- package/src/components/image/image.stories.tsx +3 -3
- package/src/components/image/image.tsx +2 -0
- package/src/components/input/input.meta.md +44 -43
- package/src/components/input/input.stories.tsx +62 -35
- package/src/components/input/input.tsx +96 -101
- package/src/components/input-group/input-group.meta.md +53 -39
- package/src/components/input-group/input-group.stories.tsx +49 -16
- package/src/components/input-group/input-group.tsx +45 -10
- package/src/components/input-number/input-number.meta.md +68 -20
- package/src/components/input-number/input-number.stories.tsx +33 -6
- package/src/components/input-number/input-number.tsx +81 -22
- package/src/components/input-otp/input-otp.meta.md +8 -20
- 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 -26
- package/src/components/item/item.stories.tsx +3 -3
- package/src/components/item/item.tsx +7 -6
- package/src/components/kbd/kbd.meta.md +7 -19
- package/src/components/kbd/kbd.stories.tsx +4 -4
- package/src/components/kbd/kbd.tsx +8 -4
- package/src/components/label/label.meta.md +21 -18
- 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 -12
- package/src/components/masonry/masonry.stories.tsx +4 -4
- package/src/components/mentions/mentions.meta.md +42 -21
- package/src/components/mentions/mentions.stories.tsx +120 -6
- package/src/components/mentions/mentions.tsx +10 -5
- package/src/components/menubar/menubar.meta.md +4 -8
- package/src/components/menubar/menubar.stories.tsx +55 -3
- package/src/components/menubar/menubar.tsx +9 -9
- package/src/components/native-select/native-select.meta.md +7 -11
- package/src/components/native-select/native-select.stories.tsx +4 -4
- package/src/components/native-select/native-select.tsx +2 -2
- package/src/components/navigation-menu/navigation-menu.meta.md +4 -8
- package/src/components/navigation-menu/navigation-menu.stories.tsx +106 -3
- package/src/components/navigation-menu/navigation-menu.tsx +6 -3
- package/src/components/notification/notification.meta.md +41 -8
- package/src/components/notification/notification.stories.tsx +9 -9
- package/src/components/notification/notification.tsx +34 -19
- package/src/components/page-header/DEVELOPMENT.md +842 -0
- package/src/components/page-header/page-header.meta.md +210 -0
- package/src/components/page-header/page-header.stories.tsx +428 -0
- package/src/components/page-header/page-header.tsx +284 -0
- package/src/components/page-shell/page-shell.meta.md +116 -0
- package/src/components/page-shell/page-shell.stories.tsx +149 -0
- package/src/components/page-shell/page-shell.tsx +115 -0
- package/src/components/pagination/pagination.meta.md +122 -50
- package/src/components/pagination/pagination.stories.tsx +227 -11
- package/src/components/pagination/pagination.tsx +345 -63
- package/src/components/popconfirm/popconfirm.meta.md +19 -23
- package/src/components/popconfirm/popconfirm.stories.tsx +2 -2
- package/src/components/popconfirm/popconfirm.tsx +1 -1
- package/src/components/popover/popover.meta.md +64 -12
- package/src/components/popover/popover.stories.tsx +83 -7
- package/src/components/popover/popover.tsx +77 -28
- package/src/components/progress/progress.meta.md +43 -26
- package/src/components/progress/progress.stories.tsx +2 -2
- package/src/components/progress/progress.tsx +19 -11
- package/src/components/radio-group/radio-group.meta.md +78 -11
- package/src/components/radio-group/radio-group.stories.tsx +38 -2
- package/src/components/radio-group/radio-group.tsx +149 -18
- package/src/components/rate/rate.meta.md +41 -19
- package/src/components/rate/rate.stories.tsx +2 -2
- package/src/components/rate/rate.tsx +37 -10
- package/src/components/resizable/resizable.meta.md +4 -12
- package/src/components/resizable/resizable.stories.tsx +5 -5
- package/src/components/resizable/resizable.tsx +1 -1
- package/src/components/result/result.meta.md +10 -14
- package/src/components/result/result.stories.tsx +2 -2
- package/src/components/result/result.tsx +21 -12
- package/src/components/scroll-area/scroll-area.meta.md +4 -8
- package/src/components/scroll-area/scroll-area.stories.tsx +5 -5
- package/src/components/segmented/segmented.meta.md +15 -17
- package/src/components/segmented/segmented.stories.tsx +3 -3
- package/src/components/segmented/segmented.tsx +16 -8
- package/src/components/select/select.meta.md +199 -67
- package/src/components/select/select.stories.tsx +238 -63
- package/src/components/select/select.tsx +718 -171
- package/src/components/separator/separator.meta.md +10 -14
- package/src/components/separator/separator.stories.tsx +2 -2
- package/src/components/separator/separator.tsx +3 -7
- package/src/components/sheet/sheet.meta.md +26 -21
- package/src/components/sheet/sheet.stories.tsx +116 -10
- package/src/components/sheet/sheet.tsx +116 -29
- package/src/components/sidebar/sidebar.meta.md +29 -38
- package/src/components/sidebar/sidebar.stories.tsx +696 -29
- package/src/components/sidebar/sidebar.tsx +643 -141
- package/src/components/skeleton/skeleton.meta.md +7 -31
- package/src/components/skeleton/skeleton.stories.tsx +3 -3
- package/src/components/skeleton/skeleton.tsx +7 -7
- package/src/components/slider/slider.meta.md +60 -13
- package/src/components/slider/slider.stories.tsx +58 -6
- package/src/components/slider/slider.tsx +154 -13
- package/src/components/sonner/sonner.meta.md +54 -8
- package/src/components/sonner/sonner.stories.tsx +79 -11
- package/src/components/sonner/sonner.tsx +137 -8
- package/src/components/spinner/spinner.meta.md +57 -21
- package/src/components/spinner/spinner.stories.tsx +66 -14
- package/src/components/spinner/spinner.tsx +111 -9
- package/src/components/statistic/statistic.meta.md +14 -30
- package/src/components/statistic/statistic.stories.tsx +1 -1
- package/src/components/statistic/statistic.tsx +4 -5
- package/src/components/steps/steps.meta.md +20 -15
- package/src/components/steps/steps.stories.tsx +37 -2
- package/src/components/steps/steps.tsx +15 -12
- package/src/components/switch/switch.meta.md +56 -15
- package/src/components/switch/switch.stories.tsx +5 -5
- package/src/components/switch/switch.tsx +59 -13
- package/src/components/table/table.meta.md +3 -7
- package/src/components/table/table.stories.tsx +1 -1
- package/src/components/table/table.tsx +8 -6
- package/src/components/tabs/tabs.meta.md +40 -32
- package/src/components/tabs/tabs.stories.tsx +104 -26
- package/src/components/tabs/tabs.tsx +125 -54
- package/src/components/tag/tag.meta.md +104 -68
- package/src/components/tag/tag.stories.tsx +183 -15
- package/src/components/tag/tag.tsx +222 -21
- package/src/components/textarea/textarea.meta.md +42 -31
- package/src/components/textarea/textarea.stories.tsx +32 -6
- package/src/components/textarea/textarea.tsx +32 -8
- package/src/components/time-picker/time-picker.meta.md +119 -50
- package/src/components/time-picker/time-picker.stories.tsx +65 -33
- package/src/components/time-picker/time-picker.tsx +889 -101
- package/src/components/timeline/timeline.meta.md +16 -17
- package/src/components/timeline/timeline.stories.tsx +24 -4
- package/src/components/timeline/timeline.tsx +32 -12
- package/src/components/toggle/toggle.meta.md +8 -12
- 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 +10 -14
- 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 +63 -18
- package/src/components/tooltip/tooltip.stories.tsx +42 -5
- package/src/components/tooltip/tooltip.tsx +81 -21
- package/src/components/tour/tour.meta.md +16 -20
- package/src/components/tour/tour.stories.tsx +3 -3
- package/src/components/tour/tour.tsx +3 -3
- package/src/components/transfer/transfer.meta.md +18 -22
- package/src/components/transfer/transfer.stories.tsx +2 -2
- package/src/components/transfer/transfer.tsx +28 -21
- package/src/components/tree/tree.meta.md +67 -22
- package/src/components/tree/tree.stories.tsx +1 -1
- package/src/components/tree/tree.tsx +9 -8
- package/src/components/tree-select/tree-select.meta.md +59 -23
- package/src/components/tree-select/tree-select.stories.tsx +2 -2
- package/src/components/tree-select/tree-select.tsx +42 -7
- package/src/components/typography/typography.meta.md +61 -39
- package/src/components/typography/typography.stories.tsx +14 -9
- package/src/components/typography/typography.tsx +38 -25
- package/src/components/upload/upload.meta.md +61 -25
- package/src/components/upload/upload.stories.tsx +69 -3
- package/src/components/upload/upload.tsx +170 -37
- package/src/components/watermark/watermark.meta.md +15 -19
- package/src/components/watermark/watermark.stories.tsx +98 -8
- 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 +57 -0
- package/src/components/button/demo/as-child.tsx +0 -24
- package/src/components/button/demo/basic.tsx +0 -8
- package/src/components/button/demo/block.tsx +0 -16
- package/src/components/button/demo/loading.tsx +0 -19
- package/src/components/button/demo/shapes.tsx +0 -18
- package/src/components/button/demo/sizes.tsx +0 -19
- package/src/components/button/demo/variants.tsx +0 -19
- package/src/components/button/demo/with-icon.tsx +0 -20
- package/src/components/button-group/button-group.meta.md +0 -101
- package/src/components/button-group/button-group.stories.tsx +0 -93
- package/src/components/button-group/button-group.tsx +0 -75
- package/src/components/combobox/combobox.meta.md +0 -102
- package/src/components/combobox/combobox.stories.tsx +0 -55
- package/src/components/combobox/combobox.tsx +0 -130
- package/src/components/input/demo/addon.tsx +0 -15
- package/src/components/input/demo/basic.tsx +0 -12
- package/src/components/input/demo/clearable.tsx +0 -21
- package/src/components/input/demo/show-count.tsx +0 -18
- package/src/components/input/demo/sizes.tsx +0 -15
- package/src/components/input/demo/with-prefix-suffix.tsx +0 -19
- package/src/components/space/space.meta.md +0 -103
- package/src/components/space/space.stories.tsx +0 -108
- package/src/components/space/space.tsx +0 -106
|
@@ -6,95 +6,159 @@ import { cn } from '@/utils/cn';
|
|
|
6
6
|
|
|
7
7
|
const Tabs = TabsPrimitive.Root;
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* TabsList 的视觉风格 + 尺寸由 cva 表达;
|
|
11
|
+
* 同时通过 `TabsListContext` 把 variant / size 透传到 TabsTrigger,
|
|
12
|
+
* 使得消费者只需在 List 上声明一次。
|
|
13
|
+
*/
|
|
14
|
+
const tabsListVariants = cva('inline-flex items-center', {
|
|
10
15
|
variants: {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
variant: {
|
|
17
|
+
// 下划线风格(antd 默认):整行 baseline border + 选中项底部 primary 高亮线
|
|
18
|
+
line: 'w-full justify-start gap-4 border-b border-border bg-transparent text-muted-foreground',
|
|
19
|
+
// 胶囊风格(吸收 Segmented):圆角容器 + muted 底色 + 选中项 background 白底 shadow
|
|
20
|
+
capsule:
|
|
21
|
+
'justify-center gap-1 rounded-lg bg-muted p-1 text-muted-foreground',
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
sm: '',
|
|
25
|
+
md: '',
|
|
26
|
+
lg: '',
|
|
14
27
|
},
|
|
15
28
|
},
|
|
16
|
-
|
|
29
|
+
compoundVariants: [
|
|
30
|
+
{ variant: 'capsule', size: 'sm', class: 'h-8' },
|
|
31
|
+
{ variant: 'capsule', size: 'md', class: 'h-9' },
|
|
32
|
+
{ variant: 'capsule', size: 'lg', class: 'h-10' },
|
|
33
|
+
],
|
|
34
|
+
defaultVariants: { variant: 'line', size: 'md' },
|
|
17
35
|
});
|
|
18
36
|
|
|
19
37
|
const tabsTriggerVariants = cva(
|
|
20
|
-
'inline-flex items-center justify-center whitespace-nowrap
|
|
38
|
+
'inline-flex cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
21
39
|
{
|
|
22
40
|
variants: {
|
|
23
|
-
|
|
24
|
-
line: 'relative
|
|
25
|
-
|
|
41
|
+
variant: {
|
|
42
|
+
line: 'relative -mb-px border-b-2 border-transparent text-muted-foreground hover:text-foreground data-[state=active]:border-primary data-[state=active]:text-foreground',
|
|
43
|
+
capsule:
|
|
44
|
+
'rounded-md text-muted-foreground hover:text-foreground data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',
|
|
45
|
+
},
|
|
46
|
+
size: {
|
|
47
|
+
sm: 'text-xs',
|
|
48
|
+
md: 'text-xs',
|
|
49
|
+
lg: 'text-sm',
|
|
26
50
|
},
|
|
27
51
|
},
|
|
28
|
-
|
|
52
|
+
compoundVariants: [
|
|
53
|
+
{ variant: 'line', size: 'sm', class: 'px-1 py-1.5' },
|
|
54
|
+
{ variant: 'line', size: 'md', class: 'px-1 py-2' },
|
|
55
|
+
{ variant: 'line', size: 'lg', class: 'px-1 py-2.5' },
|
|
56
|
+
{ variant: 'capsule', size: 'sm', class: 'px-2.5 py-1' },
|
|
57
|
+
{ variant: 'capsule', size: 'md', class: 'px-3 py-1' },
|
|
58
|
+
{ variant: 'capsule', size: 'lg', class: 'px-4 py-1.5' },
|
|
59
|
+
],
|
|
60
|
+
defaultVariants: { variant: 'line', size: 'md' },
|
|
29
61
|
},
|
|
30
62
|
);
|
|
31
63
|
|
|
64
|
+
type TabsVariant = NonNullable<
|
|
65
|
+
VariantProps<typeof tabsListVariants>['variant']
|
|
66
|
+
>;
|
|
67
|
+
type TabsSize = NonNullable<VariantProps<typeof tabsListVariants>['size']>;
|
|
68
|
+
|
|
69
|
+
const TabsListContext = React.createContext<{
|
|
70
|
+
variant: TabsVariant;
|
|
71
|
+
size: TabsSize;
|
|
72
|
+
}>({ variant: 'line', size: 'md' });
|
|
73
|
+
|
|
32
74
|
export interface TabsListProps
|
|
33
75
|
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>,
|
|
34
76
|
VariantProps<typeof tabsListVariants> {
|
|
35
77
|
/**
|
|
36
|
-
* 视觉风格(antd
|
|
37
|
-
*
|
|
78
|
+
* 视觉风格(shadcn ∪ antd 并集 + 吸收 Segmented)。
|
|
79
|
+
* - `line`:下划线风格(antd 默认),适合页面级主导航 / 大区块切换。
|
|
80
|
+
* - `capsule`:胶囊风格(取代旧 `card`,吸收 Segmented),muted 底色 + 选中项白底 shadow,适合紧凑互斥单选(视图切换、时间区间)。
|
|
81
|
+
* @default "line"
|
|
38
82
|
*/
|
|
39
|
-
|
|
83
|
+
variant?: TabsVariant;
|
|
40
84
|
/**
|
|
41
|
-
*
|
|
85
|
+
* 尺寸(antd `size` 并集)。三档统一驱动 trigger 的字号与 padding。
|
|
86
|
+
* @default "md"
|
|
87
|
+
*/
|
|
88
|
+
size?: TabsSize;
|
|
89
|
+
/**
|
|
90
|
+
* 右侧附加内容(antd `tabBarExtraContent` 并集);仅 `variant="line"` 显式支持(布局灵活)。
|
|
42
91
|
* 用法:把节点放进来即可,组件用 `flex justify-between` 自动撑开。
|
|
43
92
|
*/
|
|
44
93
|
extra?: React.ReactNode;
|
|
45
94
|
}
|
|
46
95
|
|
|
47
|
-
const TabsListContext = React.createContext<{ type: 'line' | 'card' }>({
|
|
48
|
-
type: 'card',
|
|
49
|
-
});
|
|
50
|
-
|
|
51
96
|
const TabsList = React.forwardRef<
|
|
52
97
|
React.ElementRef<typeof TabsPrimitive.List>,
|
|
53
98
|
TabsListProps
|
|
54
|
-
>(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
</TabsPrimitive.List>
|
|
65
|
-
);
|
|
66
|
-
if (extra) {
|
|
67
|
-
return (
|
|
68
|
-
<div
|
|
69
|
-
className={cn(
|
|
70
|
-
'flex items-center justify-between',
|
|
71
|
-
type === 'line' && 'border-b border-border',
|
|
72
|
-
)}
|
|
99
|
+
>(
|
|
100
|
+
(
|
|
101
|
+
{ className, variant = 'line', size = 'md', extra, children, ...props },
|
|
102
|
+
ref,
|
|
103
|
+
) => {
|
|
104
|
+
const list = (
|
|
105
|
+
<TabsPrimitive.List
|
|
106
|
+
ref={ref}
|
|
107
|
+
className={cn(tabsListVariants({ variant, size }), className)}
|
|
108
|
+
{...props}
|
|
73
109
|
>
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
className,
|
|
79
|
-
),
|
|
80
|
-
})}
|
|
81
|
-
<div className="shrink-0">{extra}</div>
|
|
82
|
-
</div>
|
|
110
|
+
<TabsListContext.Provider value={{ variant, size }}>
|
|
111
|
+
{children}
|
|
112
|
+
</TabsListContext.Provider>
|
|
113
|
+
</TabsPrimitive.List>
|
|
83
114
|
);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
if (extra) {
|
|
116
|
+
return (
|
|
117
|
+
<div
|
|
118
|
+
className={cn(
|
|
119
|
+
'flex items-center justify-between',
|
|
120
|
+
variant === 'line' && 'border-b border-border',
|
|
121
|
+
)}
|
|
122
|
+
>
|
|
123
|
+
{React.cloneElement(list, {
|
|
124
|
+
className: cn(
|
|
125
|
+
tabsListVariants({ variant, size }),
|
|
126
|
+
variant === 'line' && 'border-b-0',
|
|
127
|
+
className,
|
|
128
|
+
),
|
|
129
|
+
})}
|
|
130
|
+
<div className="shrink-0">{extra}</div>
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return list;
|
|
135
|
+
},
|
|
136
|
+
);
|
|
87
137
|
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
88
138
|
|
|
139
|
+
/**
|
|
140
|
+
* `TabsTrigger` 也接受 `variant` / `size`,但仅用于显式覆盖来自 `TabsList`
|
|
141
|
+
* 的上下文(罕用)—— 通常在 `TabsList` 上声明一次即可。
|
|
142
|
+
* 类型用 inline 形式避免 gen:meta 候选优先匹配。
|
|
143
|
+
*/
|
|
89
144
|
const TabsTrigger = React.forwardRef<
|
|
90
145
|
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
91
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
92
|
-
|
|
93
|
-
|
|
146
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> & {
|
|
147
|
+
variant?: TabsVariant;
|
|
148
|
+
size?: TabsSize;
|
|
149
|
+
}
|
|
150
|
+
>(({ className, variant, size, ...props }, ref) => {
|
|
151
|
+
const ctx = React.useContext(TabsListContext);
|
|
94
152
|
return (
|
|
95
153
|
<TabsPrimitive.Trigger
|
|
96
154
|
ref={ref}
|
|
97
|
-
className={cn(
|
|
155
|
+
className={cn(
|
|
156
|
+
tabsTriggerVariants({
|
|
157
|
+
variant: variant ?? ctx.variant,
|
|
158
|
+
size: size ?? ctx.size,
|
|
159
|
+
}),
|
|
160
|
+
className,
|
|
161
|
+
)}
|
|
98
162
|
{...props}
|
|
99
163
|
/>
|
|
100
164
|
);
|
|
@@ -116,4 +180,11 @@ const TabsContent = React.forwardRef<
|
|
|
116
180
|
));
|
|
117
181
|
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
118
182
|
|
|
119
|
-
export {
|
|
183
|
+
export {
|
|
184
|
+
Tabs,
|
|
185
|
+
TabsList,
|
|
186
|
+
TabsTrigger,
|
|
187
|
+
TabsContent,
|
|
188
|
+
tabsListVariants,
|
|
189
|
+
tabsTriggerVariants,
|
|
190
|
+
};
|
|
@@ -3,70 +3,52 @@ id: tag
|
|
|
3
3
|
name: Tag
|
|
4
4
|
displayName: 标签
|
|
5
5
|
type: component
|
|
6
|
-
category:
|
|
6
|
+
category: data-display
|
|
7
7
|
since: 0.1.0
|
|
8
8
|
package: '@teamix-evo/ui'
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Tag 标签
|
|
12
12
|
|
|
13
|
-
标签 — antd
|
|
13
|
+
标签 — antd 独有补足 + cloud-design 多彩并集。**与 Badge 区别**:Tag 偏向**用户可关闭的关键词标签**(分类 / 筛选条件 / 多彩分类),支持 `variant`(形态轴)× `color`(语义色轴,对齐 [ADR 0021](../../../../../docs/adr/0021-semantic-color-api-unification.md))× `palette`(装饰色轴,9 预设 + 任意 CSS 值)的三轴正交组合,以及 `icon` / `size` / `closable`;Badge 偏向**状态徽标**(数字 / 红点 / 状态条)。
|
|
14
14
|
|
|
15
15
|
## When to use
|
|
16
16
|
|
|
17
|
-
- 关键词 / 标签 / 分类(博客标签、用户兴趣)
|
|
18
|
-
- 当前筛选条件展示(可关闭以移除条件)
|
|
19
|
-
- 列表项的次级标签(优先级 / 类型)
|
|
17
|
+
- 关键词 / 标签 / 分类(博客标签、用户兴趣) — 多彩分类用 `palette`
|
|
18
|
+
- 当前筛选条件展示(可关闭以移除条件) — 配 `closable + onClose`
|
|
19
|
+
- 列表项的次级标签(优先级 / 类型) — 状态语义用 `color`
|
|
20
|
+
- 单选 / 多选筛选 chip — 用 `CheckableTag` / `CheckableTagGroup`
|
|
20
21
|
|
|
21
22
|
## When NOT to use
|
|
22
23
|
|
|
23
|
-
- 状态指示 → `Badge`
|
|
24
|
+
- 状态指示(运行中 / 已停止 + 数字) → `Badge`
|
|
24
25
|
- 切换按钮 → `Toggle` / `ToggleGroup`
|
|
25
26
|
- 选择类输入 → `Combobox` / `Select`
|
|
26
27
|
|
|
27
28
|
## Props
|
|
28
29
|
|
|
29
30
|
<!-- auto:props:begin -->
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
|
|
39
|
-
#### CheckableTag
|
|
40
|
-
|
|
41
|
-
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
42
|
-
| ---------- | ------------------------- | ------ | ---- | ---------------- |
|
|
43
|
-
| `checked` | `boolean` | – | ✓ | 是否选中(受控)。 |
|
|
44
|
-
| `onChange` | `(next: boolean) => void` | – | – | 选中态变化回调。 |
|
|
45
|
-
| `disabled` | `boolean` | – | – | 禁用。 |
|
|
46
|
-
|
|
47
|
-
#### CheckableTagGroup
|
|
48
|
-
|
|
49
|
-
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
50
|
-
| -------------- | --------------------------- | ------ | ---- | --------------------- |
|
|
51
|
-
| `options` | `CheckableTagGroupOption[]` | – | ✓ | 候选项数组。 |
|
|
52
|
-
| `value` | `string[]` | – | – | 受控选中 value 集合。 |
|
|
53
|
-
| `defaultValue` | `string[]` | – | – | 非受控初值。 |
|
|
54
|
-
| `onChange` | `(next: string[]) => void` | – | – | 选中变化回调。 |
|
|
55
|
-
| `disabled` | `boolean` | – | – | 整组禁用。 |
|
|
56
|
-
|
|
31
|
+
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
32
|
+
| --- | --- | --- | --- | --- |
|
|
33
|
+
| `variant` | `'solid' \| 'outline' \| 'ghost'` | `"solid"` | – | 形态轴(对齐 [ADR 0021](../../../../docs/adr/0021-semantic-color-api-unification.md)): `solid` 实色背景 / `outline` 仅描边 / `ghost` 仅文字。 |
|
|
34
|
+
| `color` | `'default' \| 'primary' \| 'success' \| 'warning' \| 'destructive'` | `"default"` | – | 语义色 — 与组件状态绑定的调色板,5 档(填充背景类省略 `muted`,信息色用 `primary`, 不收 `info` — 见 ADR 0021)。装饰性类别区分请用 `palette`。 |
|
|
35
|
+
| `size` | `'sm' \| 'md'` | `"md"` | – | 尺寸:`sm` 高 20px(更紧凑) / `md` 高 24px(默认)。 |
|
|
36
|
+
| `palette` | `TagPalettePreset \| (string & {})` | – | – | **分类色 / 装饰色** — 与 `color`(语义色) 正交,用于纯装饰的类别区分(博客标签 / 项目分类 / ...)。 接受 9 种预设色 `'blue' \| 'cyan' \| 'green' \| 'orange' \| 'purple' \| 'red' \| 'magenta' \| 'lime' \| 'gold'` 或任意 CSS 颜色值(如 `'#FF5733'` / `'hsl(280 80% 60%)'` / `'var(--brand)'`)。 `palette` 存在时会**覆盖** `color` 的语义配色(派生 bg / border / text 三档), 但仍受 `variant` 控制形态:`solid` 12% bg + 35% border、`outline` 仅 solid 描边、`ghost` 仅文字。 装饰类别走 `palette`;状态语义走 `color`。两者同传时 `palette` 优先(因为它是显式装饰意图)。 |
|
|
37
|
+
| `icon` | `React.ReactNode` | – | – | 标签文字左侧图标插槽(antd `icon` 并集)。推荐传 `lucide-react` icon。 与 `closable` 的关闭按钮不冲突 — icon 在左,X 在右。 |
|
|
38
|
+
| `closable` | `boolean` | `false` | – | 显示关闭按钮(antd `closable` 并集)。 |
|
|
39
|
+
| `onClose` | `() => void` | – | – | 关闭回调 — `closable` 触发时调用。建议父组件维护数组并在此回调中移除当前项。 |
|
|
57
40
|
<!-- auto:props:end -->
|
|
58
41
|
|
|
59
42
|
## 依赖
|
|
60
43
|
|
|
61
44
|
<!-- auto:deps:begin -->
|
|
62
|
-
|
|
63
45
|
### 同库依赖
|
|
64
46
|
|
|
65
47
|
> `teamix-evo ui add tag` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
66
48
|
|
|
67
|
-
| Entry | 类型 | 描述
|
|
68
|
-
|
|
|
69
|
-
| `cn`
|
|
49
|
+
| Entry | 类型 | 描述 |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
70
52
|
|
|
71
53
|
### npm 依赖
|
|
72
54
|
|
|
@@ -75,49 +57,103 @@ package: '@teamix-evo/ui'
|
|
|
75
57
|
```bash
|
|
76
58
|
pnpm add class-variance-authority@^0.7.0 lucide-react@^0.460.0
|
|
77
59
|
```
|
|
78
|
-
|
|
79
60
|
<!-- auto:deps:end -->
|
|
80
61
|
|
|
81
62
|
## AI 生成纪律
|
|
82
63
|
|
|
83
|
-
- **`color`
|
|
84
|
-
- **`
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
64
|
+
- **`color`(语义) vs `palette`(装饰) 选轴明确**:状态/反馈/校验类信号 → `color`;纯类别区分(标签云 / 分类) → `palette`。**不要混用**两轴去拼颜色
|
|
65
|
+
- **`variant` 是形态不是颜色**(ADR 0021):`solid` / `outline` / `ghost`,**禁止**回写 `variant="primary"` 等旧风格
|
|
66
|
+
- **`color` 不收 `info` / `error` / `danger`**:对齐 ADR 0021;信息色用 `color="primary"`,失败用 `destructive`
|
|
67
|
+
- **`palette` 优先级高于 `color`**:同时传时 palette 覆盖配色(实现:inline style > utility class)
|
|
68
|
+
- **palette 自定义值要可访问**:任意 CSS 颜色字符串都可传,但要保证 12% 透明度背景下对比度可读;**对纯白 / 极浅色慎用 solid 形态**(转为 `outline` 或 `ghost`)
|
|
69
|
+
- **`closable` 必配 `onClose`**:父组件维护数组并在回调中移除
|
|
70
|
+
- **icon 来源固定** `lucide-react`(ESLint `icon-from-lucide` 阻塞)。**不要**内联 SVG 或引入其它 icon 库
|
|
71
|
+
- **文字 ≤ 4 个汉字 / 8 字符**:过长视觉破碎,考虑改用 Description / Field
|
|
72
|
+
- **不要嵌套交互**:Tag 内不要放 Button / Link;`closable` X 已是组件唯一交互
|
|
73
|
+
- **圆角走 token**:`--radius-tag`(4px) 由组件内 inline style 注入,**不要**覆盖为其他档位
|
|
74
|
+
- **不要把语义色硬塞进 palette**:`palette="red"` 不等于 `color="destructive"` — 前者是装饰红,后者是危险信号语义
|
|
88
75
|
|
|
89
76
|
## Examples
|
|
90
77
|
|
|
91
78
|
```tsx
|
|
92
|
-
import { Tag } from '@/components/ui/tag';
|
|
79
|
+
import { Tag, CheckableTagGroup } from '@/components/ui/tag';
|
|
80
|
+
import { Hash, Star } from 'lucide-react';
|
|
93
81
|
import * as React from 'react';
|
|
94
82
|
|
|
95
|
-
//
|
|
96
|
-
<
|
|
97
|
-
<Tag
|
|
98
|
-
<Tag color="
|
|
99
|
-
<Tag color="
|
|
100
|
-
<Tag color="
|
|
101
|
-
|
|
102
|
-
// 可关闭
|
|
103
|
-
const [tags, setTags] = React.useState(['React', 'Vue', 'Angular']);
|
|
104
|
-
<div className="flex gap-2">
|
|
105
|
-
{tags.map((t) => (
|
|
106
|
-
<Tag
|
|
107
|
-
key={t}
|
|
108
|
-
color="primary"
|
|
109
|
-
closable
|
|
110
|
-
onClose={() => setTags(tags.filter((x) => x !== t))}
|
|
111
|
-
>
|
|
112
|
-
{t}
|
|
113
|
-
</Tag>
|
|
114
|
-
))}
|
|
83
|
+
// 1. 形态 × 语义色(三种 variant × 五档 color)
|
|
84
|
+
<div className="flex flex-wrap gap-2">
|
|
85
|
+
<Tag>Default</Tag>
|
|
86
|
+
<Tag variant="outline" color="primary">Primary outline</Tag>
|
|
87
|
+
<Tag variant="ghost" color="success">Ghost success</Tag>
|
|
88
|
+
<Tag color="warning">Warning</Tag>
|
|
89
|
+
<Tag color="destructive">Destructive</Tag>
|
|
115
90
|
</div>
|
|
116
91
|
|
|
117
|
-
//
|
|
92
|
+
// 2. 多彩分类(9 预设 + 任意 CSS 值)
|
|
118
93
|
<div className="flex flex-wrap gap-2">
|
|
119
|
-
<Tag
|
|
120
|
-
<Tag
|
|
121
|
-
<Tag
|
|
94
|
+
<Tag palette="blue">React</Tag>
|
|
95
|
+
<Tag palette="green">Vue</Tag>
|
|
96
|
+
<Tag palette="orange">Svelte</Tag>
|
|
97
|
+
<Tag palette="purple">Solid</Tag>
|
|
98
|
+
<Tag palette="#ff66cc">Custom Pink</Tag>
|
|
122
99
|
</div>
|
|
100
|
+
|
|
101
|
+
// 3. icon + closable + size
|
|
102
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
103
|
+
<Tag size="sm" icon={<Hash />}>small + icon</Tag>
|
|
104
|
+
<Tag icon={<Star />} closable onClose={() => alert('closed')}>
|
|
105
|
+
favorite
|
|
106
|
+
</Tag>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
// 4. CheckableTagGroup(单/多选 chip)
|
|
110
|
+
const [picked, setPicked] = React.useState<string[]>(['react']);
|
|
111
|
+
<CheckableTagGroup
|
|
112
|
+
value={picked}
|
|
113
|
+
onChange={setPicked}
|
|
114
|
+
options={[
|
|
115
|
+
{ label: 'React', value: 'react' },
|
|
116
|
+
{ label: 'Vue', value: 'vue' },
|
|
117
|
+
{ label: 'Angular', value: 'angular' },
|
|
118
|
+
]}
|
|
119
|
+
/>
|
|
123
120
|
```
|
|
121
|
+
|
|
122
|
+
## Tag 形态 — 旧库 API → 新映射
|
|
123
|
+
|
|
124
|
+
> 本节对齐 cloud-design (Teamix 1.0 hybridcloud) Tag / Tag.Closeable / Tag.Selectable / Tag.Group → 新库 Tag + CheckableTag + CheckableTagGroup 的迁移路径。
|
|
125
|
+
|
|
126
|
+
### 组件拆合
|
|
127
|
+
|
|
128
|
+
| 旧库 | 新库 | 说明 |
|
|
129
|
+
| ---------------- | -------------------------------------- | -------------------------------- |
|
|
130
|
+
| `Tag` | `Tag` | 基础标签,直接对应 |
|
|
131
|
+
| `Tag.Closeable` | `Tag closable onClose={fn}` | 合并为 `closable` prop |
|
|
132
|
+
| `Tag.Selectable` | `CheckableTag` | 重命名 |
|
|
133
|
+
| `Tag.Group` | `div className="flex flex-wrap gap-2"` | 无需专用容器,flex gap 替代 |
|
|
134
|
+
| — | `CheckableTagGroup` | 新库独有,data-driven 多选标签组 |
|
|
135
|
+
|
|
136
|
+
### Props / 值映射
|
|
137
|
+
|
|
138
|
+
| 旧库 | 新库 | 备注 |
|
|
139
|
+
| ------------------------------- | --------------------------------- | ----------------------------- |
|
|
140
|
+
| `type="normal"` | `variant="solid" color="default"` | 默认形态 |
|
|
141
|
+
| `type="primary"` | `variant="solid" color="primary"` | 主色填充 |
|
|
142
|
+
| `color="blue"` (预设色) | `palette="blue"` | 装饰色走 palette 轴 |
|
|
143
|
+
| `color="red"` (预设色) | `palette="red"` | 同上 |
|
|
144
|
+
| `size="small"` | `size="sm"` | 高 20px |
|
|
145
|
+
| `size="medium"` | `size="md"` | 高 24px(默认) |
|
|
146
|
+
| `closable` (Tag.Closeable 专属) | `closable` (Tag prop) | 统一到 Tag |
|
|
147
|
+
| `onClose` 返回 false 阻止 | 外部受控(不渲染) | 父组件 state 管理 |
|
|
148
|
+
| `closeArea="tag"` | — | 不迁移,固定 X 按钮区域 |
|
|
149
|
+
| `animation` / `afterAppear` | — | 不迁移(CSS transition 已内置) |
|
|
150
|
+
|
|
151
|
+
### 不迁移清单(保留新库优势)
|
|
152
|
+
|
|
153
|
+
| 旧库能力 | 理由 |
|
|
154
|
+
| ----------------------------- | ------------------------------------- |
|
|
155
|
+
| `closeArea="tag"` 整体可关闭 | 新库固定 X 按钮交互,语义更清晰 |
|
|
156
|
+
| `onClose` 返回 false 阻止关闭 | 新库用外部受控模式替代 |
|
|
157
|
+
| `animation` / `afterAppear` | 过渡已由 CSS `transition-colors` 覆盖 |
|
|
158
|
+
| `Tag.Group` 容器组件 | flex gap 布局更灵活,无需专用容器 |
|
|
159
|
+
| `hoverUnchangable` | 由 `variant` 形态决定 hover 行为 |
|