@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.
- package/LICENSE +21 -0
- package/README.md +336 -0
- package/_data.json +12 -0
- package/manifest.json +1688 -0
- package/package.json +90 -0
- package/src/components/accordion/accordion.meta.md +87 -0
- package/src/components/accordion/accordion.stories.tsx +67 -0
- package/src/components/accordion/accordion.tsx +58 -0
- package/src/components/affix/affix.meta.md +80 -0
- package/src/components/affix/affix.stories.tsx +57 -0
- package/src/components/affix/affix.tsx +97 -0
- package/src/components/alert/alert.meta.md +101 -0
- package/src/components/alert/alert.stories.tsx +93 -0
- package/src/components/alert/alert.tsx +132 -0
- package/src/components/alert-dialog/alert-dialog.meta.md +107 -0
- package/src/components/alert-dialog/alert-dialog.stories.tsx +81 -0
- package/src/components/alert-dialog/alert-dialog.tsx +136 -0
- package/src/components/anchor/anchor.meta.md +87 -0
- package/src/components/anchor/anchor.stories.tsx +74 -0
- package/src/components/anchor/anchor.tsx +130 -0
- package/src/components/app/app.meta.md +86 -0
- package/src/components/app/app.stories.tsx +62 -0
- package/src/components/app/app.tsx +58 -0
- package/src/components/aspect-ratio/aspect-ratio.meta.md +81 -0
- package/src/components/aspect-ratio/aspect-ratio.stories.tsx +59 -0
- package/src/components/aspect-ratio/aspect-ratio.tsx +22 -0
- package/src/components/auto-complete/auto-complete.meta.md +102 -0
- package/src/components/auto-complete/auto-complete.stories.tsx +93 -0
- package/src/components/auto-complete/auto-complete.tsx +205 -0
- package/src/components/avatar/avatar.meta.md +94 -0
- package/src/components/avatar/avatar.stories.tsx +80 -0
- package/src/components/avatar/avatar.tsx +126 -0
- package/src/components/badge/badge.meta.md +119 -0
- package/src/components/badge/badge.stories.tsx +153 -0
- package/src/components/badge/badge.tsx +210 -0
- package/src/components/breadcrumb/breadcrumb.meta.md +107 -0
- package/src/components/breadcrumb/breadcrumb.stories.tsx +84 -0
- package/src/components/breadcrumb/breadcrumb.tsx +122 -0
- package/src/components/button/button.meta.md +98 -0
- package/src/components/button/button.stories.tsx +235 -0
- package/src/components/button/button.tsx +160 -0
- package/src/components/button-group/button-group.meta.md +92 -0
- package/src/components/button-group/button-group.stories.tsx +90 -0
- package/src/components/button-group/button-group.tsx +75 -0
- package/src/components/calendar/calendar.meta.md +118 -0
- package/src/components/calendar/calendar.stories.tsx +68 -0
- package/src/components/calendar/calendar.tsx +107 -0
- package/src/components/card/card.meta.md +117 -0
- package/src/components/card/card.stories.tsx +112 -0
- package/src/components/card/card.tsx +222 -0
- package/src/components/carousel/carousel.meta.md +117 -0
- package/src/components/carousel/carousel.stories.tsx +84 -0
- package/src/components/carousel/carousel.tsx +224 -0
- package/src/components/cascader/cascader.meta.md +110 -0
- package/src/components/cascader/cascader.stories.tsx +108 -0
- package/src/components/cascader/cascader.tsx +198 -0
- package/src/components/checkbox/checkbox.meta.md +99 -0
- package/src/components/checkbox/checkbox.stories.tsx +130 -0
- package/src/components/checkbox/checkbox.tsx +125 -0
- package/src/components/collapsible/collapsible.meta.md +80 -0
- package/src/components/collapsible/collapsible.stories.tsx +35 -0
- package/src/components/collapsible/collapsible.tsx +18 -0
- package/src/components/color-picker/color-picker.meta.md +84 -0
- package/src/components/color-picker/color-picker.stories.tsx +80 -0
- package/src/components/color-picker/color-picker.tsx +160 -0
- package/src/components/combobox/combobox.meta.md +93 -0
- package/src/components/combobox/combobox.stories.tsx +55 -0
- package/src/components/combobox/combobox.tsx +130 -0
- package/src/components/command/command.meta.md +104 -0
- package/src/components/command/command.stories.tsx +59 -0
- package/src/components/command/command.tsx +147 -0
- package/src/components/context-menu/context-menu.meta.md +90 -0
- package/src/components/context-menu/context-menu.stories.tsx +46 -0
- package/src/components/context-menu/context-menu.tsx +191 -0
- package/src/components/data-table/data-table.meta.md +149 -0
- package/src/components/data-table/data-table.stories.tsx +125 -0
- package/src/components/data-table/data-table.tsx +185 -0
- package/src/components/date-picker/date-picker.meta.md +106 -0
- package/src/components/date-picker/date-picker.stories.tsx +58 -0
- package/src/components/date-picker/date-picker.tsx +156 -0
- package/src/components/descriptions/descriptions.meta.md +78 -0
- package/src/components/descriptions/descriptions.stories.tsx +60 -0
- package/src/components/descriptions/descriptions.tsx +129 -0
- package/src/components/dialog/dialog.meta.md +105 -0
- package/src/components/dialog/dialog.stories.tsx +93 -0
- package/src/components/dialog/dialog.tsx +128 -0
- package/src/components/drawer/drawer.meta.md +96 -0
- package/src/components/drawer/drawer.stories.tsx +54 -0
- package/src/components/drawer/drawer.tsx +114 -0
- package/src/components/dropdown-menu/dropdown-menu.meta.md +103 -0
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +112 -0
- package/src/components/dropdown-menu/dropdown-menu.tsx +195 -0
- package/src/components/empty/empty.meta.md +81 -0
- package/src/components/empty/empty.stories.tsx +46 -0
- package/src/components/empty/empty.tsx +47 -0
- package/src/components/field/field.meta.md +116 -0
- package/src/components/field/field.stories.tsx +117 -0
- package/src/components/field/field.tsx +164 -0
- package/src/components/flex/flex.meta.md +94 -0
- package/src/components/flex/flex.stories.tsx +112 -0
- package/src/components/flex/flex.tsx +122 -0
- package/src/components/float-button/float-button.meta.md +87 -0
- package/src/components/float-button/float-button.stories.tsx +78 -0
- package/src/components/float-button/float-button.tsx +143 -0
- package/src/components/form/form.meta.md +131 -0
- package/src/components/form/form.stories.tsx +122 -0
- package/src/components/form/form.tsx +194 -0
- package/src/components/grid/grid.meta.md +87 -0
- package/src/components/grid/grid.stories.tsx +99 -0
- package/src/components/grid/grid.tsx +130 -0
- package/src/components/hover-card/hover-card.meta.md +92 -0
- package/src/components/hover-card/hover-card.stories.tsx +68 -0
- package/src/components/hover-card/hover-card.tsx +29 -0
- package/src/components/image/image.meta.md +94 -0
- package/src/components/image/image.stories.tsx +55 -0
- package/src/components/image/image.tsx +138 -0
- package/src/components/input/input.meta.md +109 -0
- package/src/components/input/input.stories.tsx +117 -0
- package/src/components/input/input.tsx +213 -0
- package/src/components/input-group/input-group.meta.md +92 -0
- package/src/components/input-group/input-group.stories.tsx +88 -0
- package/src/components/input-group/input-group.tsx +107 -0
- package/src/components/input-number/input-number.meta.md +91 -0
- package/src/components/input-number/input-number.stories.tsx +87 -0
- package/src/components/input-number/input-number.tsx +210 -0
- package/src/components/input-otp/input-otp.meta.md +105 -0
- package/src/components/input-otp/input-otp.stories.tsx +65 -0
- package/src/components/input-otp/input-otp.tsx +97 -0
- package/src/components/item/item.meta.md +116 -0
- package/src/components/item/item.stories.tsx +113 -0
- package/src/components/item/item.tsx +171 -0
- package/src/components/kbd/kbd.meta.md +85 -0
- package/src/components/kbd/kbd.stories.tsx +70 -0
- package/src/components/kbd/kbd.tsx +81 -0
- package/src/components/label/label.meta.md +91 -0
- package/src/components/label/label.stories.tsx +87 -0
- package/src/components/label/label.tsx +66 -0
- package/src/components/masonry/masonry.meta.md +85 -0
- package/src/components/masonry/masonry.stories.tsx +66 -0
- package/src/components/masonry/masonry.tsx +59 -0
- package/src/components/mentions/mentions.meta.md +89 -0
- package/src/components/mentions/mentions.stories.tsx +75 -0
- package/src/components/mentions/mentions.tsx +237 -0
- package/src/components/menubar/menubar.meta.md +100 -0
- package/src/components/menubar/menubar.stories.tsx +81 -0
- package/src/components/menubar/menubar.tsx +232 -0
- package/src/components/native-select/native-select.meta.md +88 -0
- package/src/components/native-select/native-select.stories.tsx +80 -0
- package/src/components/native-select/native-select.tsx +54 -0
- package/src/components/navigation-menu/navigation-menu.meta.md +108 -0
- package/src/components/navigation-menu/navigation-menu.stories.tsx +112 -0
- package/src/components/navigation-menu/navigation-menu.tsx +125 -0
- package/src/components/notification/notification.meta.md +91 -0
- package/src/components/notification/notification.stories.tsx +96 -0
- package/src/components/notification/notification.tsx +84 -0
- package/src/components/pagination/pagination.meta.md +127 -0
- package/src/components/pagination/pagination.stories.tsx +62 -0
- package/src/components/pagination/pagination.tsx +285 -0
- package/src/components/popconfirm/popconfirm.meta.md +109 -0
- package/src/components/popconfirm/popconfirm.stories.tsx +76 -0
- package/src/components/popconfirm/popconfirm.tsx +134 -0
- package/src/components/popover/popover.meta.md +97 -0
- package/src/components/popover/popover.stories.tsx +82 -0
- package/src/components/popover/popover.tsx +55 -0
- package/src/components/progress/progress.meta.md +86 -0
- package/src/components/progress/progress.stories.tsx +75 -0
- package/src/components/progress/progress.tsx +195 -0
- package/src/components/radio-group/radio-group.meta.md +103 -0
- package/src/components/radio-group/radio-group.stories.tsx +77 -0
- package/src/components/radio-group/radio-group.tsx +78 -0
- package/src/components/rate/rate.meta.md +87 -0
- package/src/components/rate/rate.stories.tsx +81 -0
- package/src/components/rate/rate.tsx +153 -0
- package/src/components/resizable/resizable.meta.md +92 -0
- package/src/components/resizable/resizable.stories.tsx +104 -0
- package/src/components/resizable/resizable.tsx +56 -0
- package/src/components/result/result.meta.md +90 -0
- package/src/components/result/result.stories.tsx +71 -0
- package/src/components/result/result.tsx +91 -0
- package/src/components/scroll-area/scroll-area.meta.md +84 -0
- package/src/components/scroll-area/scroll-area.stories.tsx +41 -0
- package/src/components/scroll-area/scroll-area.tsx +51 -0
- package/src/components/segmented/segmented.meta.md +103 -0
- package/src/components/segmented/segmented.stories.tsx +101 -0
- package/src/components/segmented/segmented.tsx +138 -0
- package/src/components/select/select.meta.md +110 -0
- package/src/components/select/select.stories.tsx +100 -0
- package/src/components/select/select.tsx +188 -0
- package/src/components/separator/separator.meta.md +74 -0
- package/src/components/separator/separator.stories.tsx +71 -0
- package/src/components/separator/separator.tsx +104 -0
- package/src/components/sheet/sheet.meta.md +97 -0
- package/src/components/sheet/sheet.stories.tsx +82 -0
- package/src/components/sheet/sheet.tsx +139 -0
- package/src/components/sidebar/sidebar.meta.md +131 -0
- package/src/components/sidebar/sidebar.stories.tsx +82 -0
- package/src/components/sidebar/sidebar.tsx +351 -0
- package/src/components/skeleton/skeleton.meta.md +95 -0
- package/src/components/skeleton/skeleton.stories.tsx +79 -0
- package/src/components/skeleton/skeleton.tsx +144 -0
- package/src/components/slider/slider.meta.md +94 -0
- package/src/components/slider/slider.stories.tsx +69 -0
- package/src/components/slider/slider.tsx +86 -0
- package/src/components/sonner/sonner.meta.md +96 -0
- package/src/components/sonner/sonner.stories.tsx +91 -0
- package/src/components/sonner/sonner.tsx +40 -0
- package/src/components/space/space.meta.md +94 -0
- package/src/components/space/space.stories.tsx +94 -0
- package/src/components/space/space.tsx +106 -0
- package/src/components/spinner/spinner.meta.md +76 -0
- package/src/components/spinner/spinner.stories.tsx +71 -0
- package/src/components/spinner/spinner.tsx +64 -0
- package/src/components/statistic/statistic.meta.md +99 -0
- package/src/components/statistic/statistic.stories.tsx +71 -0
- package/src/components/statistic/statistic.tsx +197 -0
- package/src/components/steps/steps.meta.md +102 -0
- package/src/components/steps/steps.stories.tsx +75 -0
- package/src/components/steps/steps.tsx +170 -0
- package/src/components/switch/switch.meta.md +92 -0
- package/src/components/switch/switch.stories.tsx +75 -0
- package/src/components/switch/switch.tsx +101 -0
- package/src/components/table/table.meta.md +95 -0
- package/src/components/table/table.stories.tsx +75 -0
- package/src/components/table/table.tsx +122 -0
- package/src/components/tabs/tabs.meta.md +98 -0
- package/src/components/tabs/tabs.stories.tsx +70 -0
- package/src/components/tabs/tabs.tsx +119 -0
- package/src/components/tag/tag.meta.md +94 -0
- package/src/components/tag/tag.stories.tsx +77 -0
- package/src/components/tag/tag.tsx +185 -0
- package/src/components/textarea/textarea.meta.md +83 -0
- package/src/components/textarea/textarea.stories.tsx +63 -0
- package/src/components/textarea/textarea.tsx +113 -0
- package/src/components/time-picker/time-picker.meta.md +83 -0
- package/src/components/time-picker/time-picker.stories.tsx +59 -0
- package/src/components/time-picker/time-picker.tsx +94 -0
- package/src/components/timeline/timeline.meta.md +102 -0
- package/src/components/timeline/timeline.stories.tsx +104 -0
- package/src/components/timeline/timeline.tsx +147 -0
- package/src/components/toggle/toggle.meta.md +88 -0
- package/src/components/toggle/toggle.stories.tsx +66 -0
- package/src/components/toggle/toggle.tsx +53 -0
- package/src/components/toggle-group/toggle-group.meta.md +90 -0
- package/src/components/toggle-group/toggle-group.stories.tsx +83 -0
- package/src/components/toggle-group/toggle-group.tsx +78 -0
- package/src/components/tooltip/tooltip.meta.md +99 -0
- package/src/components/tooltip/tooltip.stories.tsx +71 -0
- package/src/components/tooltip/tooltip.tsx +93 -0
- package/src/components/tour/tour.meta.md +116 -0
- package/src/components/tour/tour.stories.tsx +66 -0
- package/src/components/tour/tour.tsx +242 -0
- package/src/components/transfer/transfer.meta.md +90 -0
- package/src/components/transfer/transfer.stories.tsx +68 -0
- package/src/components/transfer/transfer.tsx +251 -0
- package/src/components/tree/tree.meta.md +111 -0
- package/src/components/tree/tree.stories.tsx +109 -0
- package/src/components/tree/tree.tsx +367 -0
- package/src/components/tree-select/tree-select.meta.md +100 -0
- package/src/components/tree-select/tree-select.stories.tsx +80 -0
- package/src/components/tree-select/tree-select.tsx +171 -0
- package/src/components/typography/typography.meta.md +102 -0
- package/src/components/typography/typography.stories.tsx +115 -0
- package/src/components/typography/typography.tsx +245 -0
- package/src/components/upload/upload.meta.md +111 -0
- package/src/components/upload/upload.stories.tsx +75 -0
- package/src/components/upload/upload.tsx +265 -0
- package/src/components/watermark/watermark.meta.md +95 -0
- package/src/components/watermark/watermark.stories.tsx +78 -0
- package/src/components/watermark/watermark.tsx +165 -0
- package/src/utils/cn.ts +6 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: checkbox
|
|
3
|
+
name: Checkbox
|
|
4
|
+
type: component
|
|
5
|
+
category: form
|
|
6
|
+
since: 0.1.0
|
|
7
|
+
package: "@teamix-evo/ui"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Checkbox
|
|
11
|
+
|
|
12
|
+
复选框 — Radix Checkbox(原生支持 indeterminate)+ antd `Checkbox.Group`(`options` 数组驱动)。
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
- 多选场景(待提交,如表单)
|
|
17
|
+
- 单独的开关(同意条款)
|
|
18
|
+
- 列表多选 + 全选(配 indeterminate)
|
|
19
|
+
|
|
20
|
+
## When NOT to use
|
|
21
|
+
|
|
22
|
+
- 立即生效 → 用 `Switch`
|
|
23
|
+
- 互斥单选 → 用 `RadioGroup`
|
|
24
|
+
- 工具栏图标按钮 → 用 `Toggle`
|
|
25
|
+
|
|
26
|
+
## Props
|
|
27
|
+
|
|
28
|
+
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。
|
|
29
|
+
|
|
30
|
+
<!-- auto:props:begin -->
|
|
31
|
+
_(no props)_
|
|
32
|
+
<!-- auto:props:end -->
|
|
33
|
+
|
|
34
|
+
## 依赖
|
|
35
|
+
|
|
36
|
+
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
|
|
37
|
+
|
|
38
|
+
<!-- auto:deps:begin -->
|
|
39
|
+
### 同库依赖
|
|
40
|
+
|
|
41
|
+
> `teamix-evo ui add checkbox` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
42
|
+
|
|
43
|
+
| Entry | 类型 | 描述 |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
46
|
+
|
|
47
|
+
### npm 依赖
|
|
48
|
+
|
|
49
|
+
> 业务侧需要先 `pnpm add` / `npm install` 这些包。CLI 在 `ui add` 完成后会列出此提示。
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm add @radix-ui/react-checkbox@^1.1.0 lucide-react@^0.460.0
|
|
53
|
+
```
|
|
54
|
+
<!-- auto:deps:end -->
|
|
55
|
+
|
|
56
|
+
> 透传 Radix Checkbox.Root 所有 props(`checked` / `defaultChecked` / `onCheckedChange` / `disabled` / `required` / `name` / `value` 等)。
|
|
57
|
+
> 子组件 `CheckboxGroup` 的 props 详见 [`checkbox.tsx`](./checkbox.tsx) 的 `CheckboxGroupProps`。
|
|
58
|
+
|
|
59
|
+
## AI 生成纪律
|
|
60
|
+
|
|
61
|
+
- **`checked="indeterminate"` 不是布尔**:Radix 用字面量 `'indeterminate'` 表示半选,**不要**传 number 或其他值
|
|
62
|
+
- **全选 + 半选模式**:列表全选场景 — 全选用 `checked={all}`,部分选用 `checked="indeterminate"`,父级 onCheckedChange 触发批量选/全清
|
|
63
|
+
- **必带 Label**:Checkbox 单独无文字,必须 `<label>...<Checkbox /></label>` 或 `<Checkbox id /> + <Label htmlFor>`
|
|
64
|
+
- **`CheckboxGroup` options 必须有稳定的 `value`**:不要用 index 或动态值;否则 controlled diff 失效
|
|
65
|
+
- **disabled 优先级**:整组 `disabled={true}` 会覆盖单项的 `disabled={false}`
|
|
66
|
+
|
|
67
|
+
## Examples
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { Checkbox, CheckboxGroup } from '@/components/ui/checkbox';
|
|
71
|
+
|
|
72
|
+
// 单个
|
|
73
|
+
<label className="flex items-center gap-2">
|
|
74
|
+
<Checkbox /> 接受用户协议
|
|
75
|
+
</label>
|
|
76
|
+
|
|
77
|
+
// 半选(全选模式的父框)
|
|
78
|
+
const all = items.length > 0 && items.every(i => i.checked);
|
|
79
|
+
const some = items.some(i => i.checked);
|
|
80
|
+
<Checkbox
|
|
81
|
+
checked={all ? true : some ? 'indeterminate' : false}
|
|
82
|
+
onCheckedChange={(c) => setAll(c === true)}
|
|
83
|
+
/>
|
|
84
|
+
|
|
85
|
+
// Group
|
|
86
|
+
const [v, setV] = React.useState(['apple']);
|
|
87
|
+
<CheckboxGroup
|
|
88
|
+
value={v}
|
|
89
|
+
onChange={setV}
|
|
90
|
+
options={[
|
|
91
|
+
{ label: '苹果', value: 'apple' },
|
|
92
|
+
{ label: '香蕉', value: 'banana' },
|
|
93
|
+
{ label: '橘子', value: 'orange', disabled: true },
|
|
94
|
+
]}
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
// Group 纵向
|
|
98
|
+
<CheckboxGroup orientation="vertical" options={...} defaultValue={[]} />
|
|
99
|
+
```
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { Checkbox, CheckboxGroup } from './checkbox';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Checkbox> = {
|
|
6
|
+
title: '表单与输入 · Form/Checkbox',
|
|
7
|
+
component: Checkbox,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'复选框 — 在一组选项中进行多选,或单独切换某个布尔状态。基于 Radix Checkbox(原生可访问 + indeterminate 三态) + antd `Checkbox.Group` 批量管理;支持受控 / 非受控、`disabled`、中间态。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
argTypes: {
|
|
18
|
+
disabled: { control: 'boolean' },
|
|
19
|
+
required: { control: 'boolean' },
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof Checkbox>;
|
|
25
|
+
|
|
26
|
+
export const Playground: Story = {
|
|
27
|
+
args: { defaultChecked: false },
|
|
28
|
+
render: (args) => (
|
|
29
|
+
<label className="flex items-center gap-2 text-sm">
|
|
30
|
+
<Checkbox {...args} />
|
|
31
|
+
接受用户协议
|
|
32
|
+
</label>
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const States: Story = {
|
|
37
|
+
parameters: { controls: { disable: true } },
|
|
38
|
+
render: () => (
|
|
39
|
+
<div className="flex flex-col gap-2 text-sm">
|
|
40
|
+
<label className="flex items-center gap-2">
|
|
41
|
+
<Checkbox /> 默认
|
|
42
|
+
</label>
|
|
43
|
+
<label className="flex items-center gap-2">
|
|
44
|
+
<Checkbox defaultChecked /> 已选
|
|
45
|
+
</label>
|
|
46
|
+
<label className="flex items-center gap-2 opacity-60">
|
|
47
|
+
<Checkbox disabled /> 禁用
|
|
48
|
+
</label>
|
|
49
|
+
<label className="flex items-center gap-2 opacity-60">
|
|
50
|
+
<Checkbox disabled defaultChecked /> 禁用已选
|
|
51
|
+
</label>
|
|
52
|
+
</div>
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Indeterminate: Story = {
|
|
57
|
+
parameters: { controls: { disable: true } },
|
|
58
|
+
render: () => {
|
|
59
|
+
const [items, setItems] = React.useState([
|
|
60
|
+
{ id: 1, label: '苹果', checked: true },
|
|
61
|
+
{ id: 2, label: '香蕉', checked: false },
|
|
62
|
+
{ id: 3, label: '橘子', checked: true },
|
|
63
|
+
]);
|
|
64
|
+
const all = items.every((i) => i.checked);
|
|
65
|
+
const some = items.some((i) => i.checked);
|
|
66
|
+
return (
|
|
67
|
+
<div className="flex flex-col gap-2 text-sm">
|
|
68
|
+
<label className="flex items-center gap-2 font-medium">
|
|
69
|
+
<Checkbox
|
|
70
|
+
checked={all ? true : some ? 'indeterminate' : false}
|
|
71
|
+
onCheckedChange={(c) =>
|
|
72
|
+
setItems(items.map((it) => ({ ...it, checked: c === true })))
|
|
73
|
+
}
|
|
74
|
+
/>
|
|
75
|
+
全选
|
|
76
|
+
</label>
|
|
77
|
+
<div className="ml-6 flex flex-col gap-1">
|
|
78
|
+
{items.map((it) => (
|
|
79
|
+
<label key={it.id} className="flex items-center gap-2">
|
|
80
|
+
<Checkbox
|
|
81
|
+
checked={it.checked}
|
|
82
|
+
onCheckedChange={(c) =>
|
|
83
|
+
setItems(
|
|
84
|
+
items.map((x) =>
|
|
85
|
+
x.id === it.id ? { ...x, checked: c === true } : x,
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
/>
|
|
90
|
+
{it.label}
|
|
91
|
+
</label>
|
|
92
|
+
))}
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const Group: Story = {
|
|
100
|
+
parameters: { controls: { disable: true } },
|
|
101
|
+
render: () => {
|
|
102
|
+
const [v, setV] = React.useState<string[]>(['apple']);
|
|
103
|
+
return (
|
|
104
|
+
<CheckboxGroup
|
|
105
|
+
value={v}
|
|
106
|
+
onChange={setV}
|
|
107
|
+
options={[
|
|
108
|
+
{ label: '苹果', value: 'apple' },
|
|
109
|
+
{ label: '香蕉', value: 'banana' },
|
|
110
|
+
{ label: '橘子', value: 'orange', disabled: true },
|
|
111
|
+
]}
|
|
112
|
+
/>
|
|
113
|
+
);
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const VerticalGroup: Story = {
|
|
118
|
+
parameters: { controls: { disable: true } },
|
|
119
|
+
render: () => (
|
|
120
|
+
<CheckboxGroup
|
|
121
|
+
orientation="vertical"
|
|
122
|
+
defaultValue={['email']}
|
|
123
|
+
options={[
|
|
124
|
+
{ label: '邮件', value: 'email' },
|
|
125
|
+
{ label: '短信', value: 'sms' },
|
|
126
|
+
{ label: '推送', value: 'push' },
|
|
127
|
+
]}
|
|
128
|
+
/>
|
|
129
|
+
),
|
|
130
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
3
|
+
import { Check, Minus } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
import { cn } from '@/utils/cn';
|
|
6
|
+
|
|
7
|
+
export interface CheckboxProps
|
|
8
|
+
extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {}
|
|
9
|
+
|
|
10
|
+
const Checkbox = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
|
12
|
+
CheckboxProps
|
|
13
|
+
>(({ className, ...props }, ref) => (
|
|
14
|
+
<CheckboxPrimitive.Root
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={cn(
|
|
17
|
+
'peer size-4 shrink-0 rounded-sm border border-primary shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground',
|
|
18
|
+
className,
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
>
|
|
22
|
+
<CheckboxPrimitive.Indicator
|
|
23
|
+
className={cn('flex items-center justify-center text-current')}
|
|
24
|
+
>
|
|
25
|
+
{/* Radix sets data-state="indeterminate" automatically when checked === "indeterminate" */}
|
|
26
|
+
{props.checked === 'indeterminate' ? (
|
|
27
|
+
<Minus className="size-3" />
|
|
28
|
+
) : (
|
|
29
|
+
<Check className="size-3" />
|
|
30
|
+
)}
|
|
31
|
+
</CheckboxPrimitive.Indicator>
|
|
32
|
+
</CheckboxPrimitive.Root>
|
|
33
|
+
));
|
|
34
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
35
|
+
|
|
36
|
+
// ─── CheckboxGroup(antd 并集)─────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
export interface CheckboxGroupOption {
|
|
39
|
+
label: React.ReactNode;
|
|
40
|
+
value: string;
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CheckboxGroupProps
|
|
45
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> {
|
|
46
|
+
/** 选项数据。 */
|
|
47
|
+
options: CheckboxGroupOption[];
|
|
48
|
+
/** 受控值;`string[]` 表示当前选中的 value 集合。 */
|
|
49
|
+
value?: string[];
|
|
50
|
+
/** uncontrolled 初值。 */
|
|
51
|
+
defaultValue?: string[];
|
|
52
|
+
/** 整组禁用。 */
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
/** 整组的 name(submitted form 用)。 */
|
|
55
|
+
name?: string;
|
|
56
|
+
/**
|
|
57
|
+
* 排列方向。
|
|
58
|
+
* @default "horizontal"
|
|
59
|
+
*/
|
|
60
|
+
orientation?: 'horizontal' | 'vertical';
|
|
61
|
+
/** 选中变化回调。 */
|
|
62
|
+
onChange?: (next: string[]) => void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const CheckboxGroup = React.forwardRef<HTMLDivElement, CheckboxGroupProps>(
|
|
66
|
+
(
|
|
67
|
+
{
|
|
68
|
+
className,
|
|
69
|
+
options,
|
|
70
|
+
value,
|
|
71
|
+
defaultValue,
|
|
72
|
+
disabled,
|
|
73
|
+
name,
|
|
74
|
+
orientation = 'horizontal',
|
|
75
|
+
onChange,
|
|
76
|
+
...props
|
|
77
|
+
},
|
|
78
|
+
ref,
|
|
79
|
+
) => {
|
|
80
|
+
const isControlled = value !== undefined;
|
|
81
|
+
const [internal, setInternal] = React.useState<string[]>(defaultValue ?? []);
|
|
82
|
+
const current = isControlled ? value! : internal;
|
|
83
|
+
|
|
84
|
+
const toggle = (val: string, checked: boolean) => {
|
|
85
|
+
const next = checked ? [...current, val] : current.filter((v) => v !== val);
|
|
86
|
+
if (!isControlled) setInternal(next);
|
|
87
|
+
onChange?.(next);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div
|
|
92
|
+
ref={ref}
|
|
93
|
+
role="group"
|
|
94
|
+
className={cn(
|
|
95
|
+
'flex gap-4',
|
|
96
|
+
orientation === 'vertical' && 'flex-col gap-2',
|
|
97
|
+
className,
|
|
98
|
+
)}
|
|
99
|
+
{...props}
|
|
100
|
+
>
|
|
101
|
+
{options.map((opt) => (
|
|
102
|
+
<label
|
|
103
|
+
key={opt.value}
|
|
104
|
+
className={cn(
|
|
105
|
+
'flex items-center gap-2 text-sm',
|
|
106
|
+
(disabled || opt.disabled) && 'cursor-not-allowed opacity-60',
|
|
107
|
+
)}
|
|
108
|
+
>
|
|
109
|
+
<Checkbox
|
|
110
|
+
name={name}
|
|
111
|
+
value={opt.value}
|
|
112
|
+
checked={current.includes(opt.value)}
|
|
113
|
+
disabled={disabled || opt.disabled}
|
|
114
|
+
onCheckedChange={(c) => toggle(opt.value, c === true)}
|
|
115
|
+
/>
|
|
116
|
+
<span>{opt.label}</span>
|
|
117
|
+
</label>
|
|
118
|
+
))}
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
CheckboxGroup.displayName = 'CheckboxGroup';
|
|
124
|
+
|
|
125
|
+
export { Checkbox, CheckboxGroup };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: collapsible
|
|
3
|
+
name: Collapsible
|
|
4
|
+
type: component
|
|
5
|
+
category: navigation
|
|
6
|
+
since: 0.1.0
|
|
7
|
+
package: "@teamix-evo/ui"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Collapsible
|
|
11
|
+
|
|
12
|
+
单区域展开收起 — Radix Collapsible 薄包装。**shadcn-only**(antd Collapse 单 item 也可以模拟,但语义粗糙)。
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
- 详情页"查看更多 / 收起"
|
|
17
|
+
- 行内"展开评论"按钮 + 折叠区
|
|
18
|
+
- 表单的"高级选项"开关折叠
|
|
19
|
+
|
|
20
|
+
## When NOT to use
|
|
21
|
+
|
|
22
|
+
- 多个折叠项 → `Accordion`
|
|
23
|
+
- 平级 tab 切换 → `Tabs`
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。`Collapsible` 是 `CollapsibleRoot` 别名,接受 Radix 的 `open / defaultOpen / onOpenChange / disabled`。
|
|
28
|
+
|
|
29
|
+
<!-- auto:props:begin -->
|
|
30
|
+
_(组件无 `<Name>Props` interface — props 详见 [`collapsible.tsx`](./collapsible.tsx))_
|
|
31
|
+
<!-- auto:props:end -->
|
|
32
|
+
|
|
33
|
+
## 依赖
|
|
34
|
+
|
|
35
|
+
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
|
|
36
|
+
|
|
37
|
+
<!-- auto:deps:begin -->
|
|
38
|
+
### 同库依赖
|
|
39
|
+
|
|
40
|
+
_无 — 本组件不依赖其他 ui entry。_
|
|
41
|
+
|
|
42
|
+
### npm 依赖
|
|
43
|
+
|
|
44
|
+
> 业务侧需要先 `pnpm add` / `npm install` 这些包。CLI 在 `ui add` 完成后会列出此提示。
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm add @radix-ui/react-collapsible@^1.1.0
|
|
48
|
+
```
|
|
49
|
+
<!-- auto:deps:end -->
|
|
50
|
+
|
|
51
|
+
> 子组件:`Collapsible` / `CollapsibleTrigger`(触发器)/ `CollapsibleContent`(可折叠内容)。
|
|
52
|
+
|
|
53
|
+
## AI 生成纪律
|
|
54
|
+
|
|
55
|
+
- **Trigger 用 `asChild`**:把已有按钮 wrap,而不是新增层级
|
|
56
|
+
- **`defaultOpen` 给初始视觉**:首次访问就该展开的内容显式声明 `defaultOpen`
|
|
57
|
+
- **不嵌套 Collapsible**:嵌套折叠是反模式;改用 `Accordion type="multiple"`
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import {
|
|
63
|
+
Collapsible, CollapsibleTrigger, CollapsibleContent,
|
|
64
|
+
} from '@/components/ui/collapsible';
|
|
65
|
+
import { Button } from '@/components/ui/button';
|
|
66
|
+
import { ChevronsUpDown } from 'lucide-react';
|
|
67
|
+
|
|
68
|
+
<Collapsible className="w-72">
|
|
69
|
+
<CollapsibleTrigger asChild>
|
|
70
|
+
<Button variant="ghost" size="sm" className="w-full justify-between">
|
|
71
|
+
高级选项
|
|
72
|
+
<ChevronsUpDown />
|
|
73
|
+
</Button>
|
|
74
|
+
</CollapsibleTrigger>
|
|
75
|
+
<CollapsibleContent className="space-y-2 pt-2">
|
|
76
|
+
<p className="text-sm text-muted-foreground">高级配置 1</p>
|
|
77
|
+
<p className="text-sm text-muted-foreground">高级配置 2</p>
|
|
78
|
+
</CollapsibleContent>
|
|
79
|
+
</Collapsible>
|
|
80
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ChevronsUpDown } from 'lucide-react';
|
|
3
|
+
import {
|
|
4
|
+
Collapsible,
|
|
5
|
+
CollapsibleTrigger,
|
|
6
|
+
CollapsibleContent,
|
|
7
|
+
} from './collapsible';
|
|
8
|
+
import { Button } from '@/components/button/button';
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof Collapsible> = {
|
|
11
|
+
title: '导航 · Navigation/Collapsible',
|
|
12
|
+
component: Collapsible,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
type Story = StoryObj<typeof Collapsible>;
|
|
18
|
+
|
|
19
|
+
export const Default: Story = {
|
|
20
|
+
render: () => (
|
|
21
|
+
<Collapsible className="w-72">
|
|
22
|
+
<CollapsibleTrigger asChild>
|
|
23
|
+
<Button variant="ghost" size="sm" className="w-full justify-between">
|
|
24
|
+
高级选项
|
|
25
|
+
<ChevronsUpDown />
|
|
26
|
+
</Button>
|
|
27
|
+
</CollapsibleTrigger>
|
|
28
|
+
<CollapsibleContent className="space-y-2 pt-2 px-2">
|
|
29
|
+
<p className="text-sm text-muted-foreground">- 自动重启策略</p>
|
|
30
|
+
<p className="text-sm text-muted-foreground">- 容器健康检查</p>
|
|
31
|
+
<p className="text-sm text-muted-foreground">- 资源限制</p>
|
|
32
|
+
</CollapsibleContent>
|
|
33
|
+
</Collapsible>
|
|
34
|
+
),
|
|
35
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 单区域展开 / 收起 — Radix Collapsible 的薄包装。
|
|
5
|
+
*
|
|
6
|
+
* 与 `Accordion` 的差异:Accordion 是多 item 列表(支持互斥单展开 / 多展开);
|
|
7
|
+
* Collapsible 是**单个**区域,语义最简单 —— "更多内容" / "查看详情"。
|
|
8
|
+
*
|
|
9
|
+
* shadcn-only(antd Collapse 单 item 也可以模拟,但语义粗糙)。
|
|
10
|
+
*/
|
|
11
|
+
const Collapsible = CollapsiblePrimitive.Root;
|
|
12
|
+
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
|
|
13
|
+
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
|
|
14
|
+
|
|
15
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|
|
16
|
+
export type CollapsibleProps = React.ComponentPropsWithoutRef<
|
|
17
|
+
typeof CollapsiblePrimitive.Root
|
|
18
|
+
>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: color-picker
|
|
3
|
+
name: ColorPicker
|
|
4
|
+
type: component
|
|
5
|
+
category: form
|
|
6
|
+
since: 0.1.0
|
|
7
|
+
package: "@teamix-evo/ui"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# ColorPicker
|
|
11
|
+
|
|
12
|
+
颜色选择 — antd 独有补足。**等价 antd `ColorPicker`**(v5.5+)。基于原生 `<input type="color">` + alpha 滑块 + hex 文本输入 + 预设色块,提供"触发器(色块)→ 弹出面板"的标准交互。可选透明度(8 位 hex)。
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
- 主题色 / 品牌色配置
|
|
17
|
+
- 文档 / 笔记的文字 / 高亮色选择
|
|
18
|
+
- 设计工具的填充色 / 描边色
|
|
19
|
+
- 标签 / 分类的色彩自定义
|
|
20
|
+
|
|
21
|
+
## When NOT to use
|
|
22
|
+
|
|
23
|
+
- 仅几个预设色 → `RadioGroup` 配色块更简洁
|
|
24
|
+
- 渐变 / 多色阶 → 当前不支持,需配合第三方 picker
|
|
25
|
+
- HSL / RGB 各通道独立调节 → 当前仅 hex + alpha,复杂场景建议引入专业 picker
|
|
26
|
+
|
|
27
|
+
<!-- auto:props:begin -->
|
|
28
|
+
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
29
|
+
| --- | --- | --- | --- | --- |
|
|
30
|
+
| `value` | `string` | – | – | 受控值 — `#RRGGBB` 或 `#RRGGBBAA`(开 `allowAlpha` 时)。 |
|
|
31
|
+
| `defaultValue` | `string` | `"#000000"` | – | uncontrolled 初值。 |
|
|
32
|
+
| `onChange` | `(value: string) => void` | – | – | 值变化回调。 |
|
|
33
|
+
| `allowAlpha` | `boolean` | `false` | – | 是否允许透明度(antd `format=hex8` 类似行为) — 启用后展示 alpha 滑块,value 变为 8 位 hex。 |
|
|
34
|
+
| `presets` | `string[]` | – | – | 预设色块(antd `presets` 并集) — 一组常用颜色快捷选择。 |
|
|
35
|
+
| `disabled` | `boolean` | – | – | 整体禁用。 |
|
|
36
|
+
| `size` | `'sm' \| 'default' \| 'lg'` | `"default"` | – | 触发器尺寸。 |
|
|
37
|
+
| `className` | `string` | – | – | 触发器 className。 |
|
|
38
|
+
<!-- auto:props:end -->
|
|
39
|
+
|
|
40
|
+
<!-- auto:deps:begin -->
|
|
41
|
+
### 同库依赖
|
|
42
|
+
|
|
43
|
+
> `teamix-evo ui add color-picker` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
44
|
+
|
|
45
|
+
| Entry | 类型 | 描述 |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
48
|
+
| `input` | component | 文本输入 — shadcn 简洁基底 + antd prefix/suffix/clearable/showCount/addonBefore/addonAfter/size |
|
|
49
|
+
| `popover` | component | 可交互浮层 — Radix Popover + antd arrow 并集 |
|
|
50
|
+
|
|
51
|
+
### npm 依赖
|
|
52
|
+
|
|
53
|
+
_无 — 本组件不依赖任何 npm 包。_
|
|
54
|
+
<!-- auto:deps:end -->
|
|
55
|
+
|
|
56
|
+
## AI 生成纪律
|
|
57
|
+
|
|
58
|
+
- **value 必须是 `#RRGGBB`(6位)或 `#RRGGBBAA`(8位 + 透明度)** — 不接受 `rgb()` / `hsl()` / 命名色
|
|
59
|
+
- **`allowAlpha=true`** 时 value 自动变为 8 位 hex;关闭时即使有 alpha 也会被截断到 6 位
|
|
60
|
+
- **`presets`** 应是品牌色板而非随手凑数 — 6-12 个 stable 颜色为佳,避免视觉混乱
|
|
61
|
+
- **`disabled`** 是只读语义 — 配 value 展示当前选中色;**不要**用做"暂时锁定"等业务态(用 form-level 控制)
|
|
62
|
+
- **触发器是色块本身**,内部 padding 留出 2px 边框 — 不要在外面再裹一层 border
|
|
63
|
+
- **不要在 Popover 关闭时清空 value** — onChange 已是单一真值,无需 commit/cancel 区分
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { ColorPicker } from '@/components/ui/color-picker';
|
|
69
|
+
import * as React from 'react';
|
|
70
|
+
|
|
71
|
+
// 基础
|
|
72
|
+
<ColorPicker defaultValue="#f43f5e" />
|
|
73
|
+
|
|
74
|
+
// 受控 + 预设色
|
|
75
|
+
const [c, setC] = React.useState('#3b82f6');
|
|
76
|
+
<ColorPicker
|
|
77
|
+
value={c}
|
|
78
|
+
onChange={setC}
|
|
79
|
+
presets={['#ef4444', '#f59e0b', '#10b981', '#3b82f6', '#8b5cf6', '#ec4899']}
|
|
80
|
+
/>
|
|
81
|
+
|
|
82
|
+
// 带透明度
|
|
83
|
+
<ColorPicker allowAlpha defaultValue="#3b82f680" />
|
|
84
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { ColorPicker } from './color-picker';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof ColorPicker> = {
|
|
6
|
+
title: '表单与输入 · Form/ColorPicker',
|
|
7
|
+
component: ColorPicker,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'颜色选择 — 触发器色块 → Popover 面板(原生 color input + alpha + hex 输入 + 预设色板)。可选 8 位 hex(含透明度)。等价 antd `ColorPicker`(v5.5+)。视觉走 OpenTrek tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
argTypes: {
|
|
18
|
+
size: { control: 'inline-radio', options: ['sm', 'default', 'lg'] },
|
|
19
|
+
allowAlpha: { control: 'boolean' },
|
|
20
|
+
disabled: { control: 'boolean' },
|
|
21
|
+
},
|
|
22
|
+
args: { size: 'default', allowAlpha: false, disabled: false },
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
type Story = StoryObj<typeof ColorPicker>;
|
|
27
|
+
|
|
28
|
+
export const Playground: Story = {
|
|
29
|
+
render: (args) => <ColorPicker {...args} defaultValue="#f43f5e" />,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Controlled: Story = {
|
|
33
|
+
parameters: { controls: { disable: true } },
|
|
34
|
+
render: () => {
|
|
35
|
+
const [c, setC] = React.useState('#3b82f6');
|
|
36
|
+
return (
|
|
37
|
+
<div className="flex items-center gap-3">
|
|
38
|
+
<ColorPicker value={c} onChange={setC} />
|
|
39
|
+
<span className="text-sm tabular-nums">{c}</span>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const WithPresets: Story = {
|
|
46
|
+
parameters: { controls: { disable: true } },
|
|
47
|
+
render: () => (
|
|
48
|
+
<ColorPicker
|
|
49
|
+
defaultValue="#3b82f6"
|
|
50
|
+
presets={[
|
|
51
|
+
'#ef4444',
|
|
52
|
+
'#f59e0b',
|
|
53
|
+
'#eab308',
|
|
54
|
+
'#10b981',
|
|
55
|
+
'#06b6d4',
|
|
56
|
+
'#3b82f6',
|
|
57
|
+
'#8b5cf6',
|
|
58
|
+
'#ec4899',
|
|
59
|
+
'#000000',
|
|
60
|
+
'#ffffff',
|
|
61
|
+
]}
|
|
62
|
+
/>
|
|
63
|
+
),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const WithAlpha: Story = {
|
|
67
|
+
parameters: { controls: { disable: true } },
|
|
68
|
+
render: () => <ColorPicker allowAlpha defaultValue="#3b82f680" />,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const Sizes: Story = {
|
|
72
|
+
parameters: { controls: { disable: true } },
|
|
73
|
+
render: () => (
|
|
74
|
+
<div className="flex items-center gap-3">
|
|
75
|
+
<ColorPicker size="sm" defaultValue="#ef4444" />
|
|
76
|
+
<ColorPicker size="default" defaultValue="#10b981" />
|
|
77
|
+
<ColorPicker size="lg" defaultValue="#3b82f6" />
|
|
78
|
+
</div>
|
|
79
|
+
),
|
|
80
|
+
};
|