@teamix-evo/ui 0.7.0 → 0.7.2
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/manifest.json +16 -7
- package/package.json +4 -4
- package/src/_design-system/theme-tokens/stories.tsx +2 -2
- package/src/components/accordion/index.tsx +1 -1
- package/src/components/affix/meta.md +26 -0
- package/src/components/alert/index.tsx +2 -2
- package/src/components/alert-dialog/index.tsx +3 -3
- package/src/components/alert-dialog/meta.md +52 -0
- package/src/components/alert-dialog/stories.tsx +45 -48
- package/src/components/avatar/index.tsx +1 -1
- package/src/components/badge/index.tsx +2 -2
- package/src/components/badge/meta.md +48 -0
- package/src/components/button/index.tsx +2 -2
- package/src/components/button/meta.md +15 -0
- package/src/components/button/stories.tsx +1 -1
- package/src/components/calendar/index.tsx +2 -2
- package/src/components/card/index.tsx +1 -1
- package/src/components/carousel/index.tsx +2 -2
- package/src/components/carousel/meta.md +34 -2
- package/src/components/carousel/stories.tsx +2 -2
- package/src/components/cascader-select/index.tsx +2 -1
- package/src/components/cascader-select/meta.md +46 -0
- package/src/components/checkbox/meta.md +47 -0
- package/src/components/color-picker/index.tsx +3 -3
- package/src/components/color-picker/meta.md +80 -0
- package/src/components/combobox/index.tsx +2 -2
- package/src/components/combobox/meta.md +130 -0
- package/src/components/data-table/index.tsx +3 -3
- package/src/components/data-table/meta.md +419 -0
- package/src/components/data-table/stories.tsx +4 -4
- package/src/components/date-picker/meta.md +91 -0
- package/src/components/descriptions/index.tsx +1 -1
- package/src/components/descriptions/meta.md +245 -0
- package/src/components/dialog/index.tsx +4 -4
- package/src/components/dialog/meta.md +47 -1
- package/src/components/dialog/stories.tsx +38 -41
- package/src/components/dropdown-menu/index.tsx +5 -5
- package/src/components/empty/index.tsx +2 -2
- package/src/components/field/index.tsx +4 -4
- package/src/components/filter-bar/index.tsx +6 -6
- package/src/components/filter-bar/meta.md +323 -0
- package/src/components/float-button/index.tsx +2 -2
- package/src/components/form/index.tsx +1 -1
- package/src/components/form/meta.md +119 -0
- package/src/components/hover-card/index.tsx +1 -1
- package/src/components/hover-card/meta.md +21 -0
- package/src/components/input/meta.md +16 -0
- package/src/components/input-group/index.tsx +1 -1
- package/src/components/input-group/meta.md +118 -0
- package/src/components/input-group/stories.tsx +6 -6
- package/src/components/input-ip/index.tsx +2 -2
- package/src/components/input-ip/meta.md +30 -0
- package/src/components/input-ip/stories.tsx +2 -2
- package/src/components/input-number/index.tsx +3 -2
- package/src/components/input-number/meta.md +67 -0
- package/src/components/input-number/stories.tsx +2 -2
- package/src/components/item/index.tsx +4 -4
- package/src/components/label/meta.md +8 -0
- package/src/components/mentions/meta.md +15 -0
- package/src/components/menubar/index.tsx +4 -4
- package/src/components/navigation-menu/index.tsx +4 -4
- package/src/components/page-header/index.tsx +2 -2
- package/src/components/page-header/meta.md +145 -0
- package/src/components/page-shell/index.tsx +3 -3
- package/src/components/pagination/index.tsx +1 -1
- package/src/components/pagination/meta.md +203 -0
- package/src/components/popconfirm/meta.md +45 -0
- package/src/components/popover/index.tsx +2 -2
- package/src/components/popover/meta.md +47 -0
- package/src/components/progress/index.tsx +1 -1
- package/src/components/progress/meta.md +36 -0
- package/src/components/progress/stories.tsx +1 -1
- package/src/components/radio-group/meta.md +69 -0
- package/src/components/rate/index.tsx +1 -1
- package/src/components/rate/meta.md +50 -0
- package/src/components/resizable/index.tsx +1 -1
- package/src/components/select/index.tsx +2 -2
- package/src/components/select/meta.md +20 -0
- package/src/components/separator/index.tsx +1 -1
- package/src/components/sheet/index.tsx +13 -14
- package/src/components/sheet/meta.md +124 -0
- package/src/components/sheet/stories.tsx +110 -119
- package/src/components/sidebar/index.tsx +5 -5
- package/src/components/sidebar/meta.md +383 -0
- package/src/components/skeleton/meta.md +13 -0
- package/src/components/slider/index.tsx +2 -2
- package/src/components/sonner/meta.md +86 -0
- package/src/components/spinner/meta.md +46 -0
- package/src/components/spinner/stories.tsx +2 -2
- package/src/components/steps/meta.md +20 -0
- package/src/components/steps/stories.tsx +1 -1
- package/src/components/switch/index.tsx +2 -2
- package/src/components/switch/meta.md +33 -0
- package/src/components/table/index.tsx +4 -4
- package/src/components/table/meta.md +11 -0
- package/src/components/tabs/index.tsx +7 -7
- package/src/components/tabs/meta.md +52 -0
- package/src/components/tag/index.tsx +8 -8
- package/src/components/tag/meta.md +194 -0
- package/src/components/textarea/index.tsx +1 -1
- package/src/components/textarea/meta.md +27 -0
- package/src/components/textarea/stories.tsx +1 -1
- package/src/components/time-picker/index.tsx +3 -3
- package/src/components/time-picker/meta.md +76 -0
- package/src/components/timeline/index.tsx +1 -0
- package/src/components/toggle/index.tsx +1 -1
- package/src/components/toggle-group/index.tsx +1 -1
- package/src/components/tooltip/index.tsx +1 -1
- package/src/components/tooltip/meta.md +23 -0
- package/src/components/transfer/index.tsx +2 -2
- package/src/components/transfer/meta.md +97 -0
- package/src/components/tree/index.tsx +245 -15
- package/src/components/tree/meta.md +151 -0
- package/src/components/tree-select/index.tsx +16 -2
- package/src/components/tree-select/meta.md +150 -0
- package/src/components/typography/index.tsx +3 -3
- package/src/components/upload/index.tsx +3 -3
- package/src/components/upload/meta.md +82 -0
- package/src/components/tree/utils.ts +0 -269
- package/src/examples/built-in-assets/stories.tsx +0 -572
- package/src/examples/evaluators/stories.tsx +0 -502
|
@@ -12,3 +12,386 @@
|
|
|
12
12
|
- 管理后台布局侧边导航
|
|
13
13
|
- 需要可收缩的菜单导航
|
|
14
14
|
- 配合 SidebarProvider 与页面布局使用
|
|
15
|
+
|
|
16
|
+
## 示例
|
|
17
|
+
|
|
18
|
+
### CollapsibleIcon
|
|
19
|
+
|
|
20
|
+
折叠态 + 自动 Tooltip:默认收起,hover icon 弹出文字
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<SidebarProvider open={!collapsed} onOpenChange={(o) => setCollapsed(!o)}>
|
|
24
|
+
<Sidebar {...args}>
|
|
25
|
+
<SidebarHeader>
|
|
26
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
27
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
28
|
+
Teamix Evo
|
|
29
|
+
</h1>
|
|
30
|
+
<SidebarTrigger />
|
|
31
|
+
</div>
|
|
32
|
+
</SidebarHeader>
|
|
33
|
+
<SidebarContent>
|
|
34
|
+
<SidebarGroup>
|
|
35
|
+
<SidebarGroupLabel>导航</SidebarGroupLabel>
|
|
36
|
+
<SidebarGroupContent>
|
|
37
|
+
<SidebarMenu>
|
|
38
|
+
{navItems.map((it) => (
|
|
39
|
+
<SidebarMenuItem key={it.title}>
|
|
40
|
+
<SidebarMenuButton asChild tooltip={it.title}>
|
|
41
|
+
<a href={it.url} onClick={(e) => e.preventDefault()}>
|
|
42
|
+
<it.icon />
|
|
43
|
+
<span>{it.title}</span>
|
|
44
|
+
</a>
|
|
45
|
+
</SidebarMenuButton>
|
|
46
|
+
</SidebarMenuItem>
|
|
47
|
+
))}
|
|
48
|
+
</SidebarMenu>
|
|
49
|
+
</SidebarGroupContent>
|
|
50
|
+
</SidebarGroup>
|
|
51
|
+
</SidebarContent>
|
|
52
|
+
</Sidebar>
|
|
53
|
+
<MainContent>
|
|
54
|
+
<p>
|
|
55
|
+
当前折叠状态:<strong>{collapsed ? '已折叠' : '已展开'}</strong>
|
|
56
|
+
</p>
|
|
57
|
+
<p className="mt-2">
|
|
58
|
+
折叠后 hover 任一 icon,会看到 Tooltip 弹出对应文字。
|
|
59
|
+
</p>
|
|
60
|
+
</MainContent>
|
|
61
|
+
</SidebarProvider>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### WithSubMenus
|
|
65
|
+
|
|
66
|
+
二级菜单:配合 Collapsible 实现展开/收起,折叠态自动隐藏
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<SidebarProvider>
|
|
70
|
+
<Sidebar {...args}>
|
|
71
|
+
<SidebarHeader>
|
|
72
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
73
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
74
|
+
Teamix Evo
|
|
75
|
+
</h1>
|
|
76
|
+
<SidebarTrigger />
|
|
77
|
+
</div>
|
|
78
|
+
</SidebarHeader>
|
|
79
|
+
<SidebarContent>
|
|
80
|
+
<SidebarGroup>
|
|
81
|
+
<SidebarGroupLabel>导航</SidebarGroupLabel>
|
|
82
|
+
<SidebarMenu>
|
|
83
|
+
<SidebarMenuItem>
|
|
84
|
+
<SidebarMenuButton asChild tooltip="首页">
|
|
85
|
+
<a href="#home" onClick={(e) => e.preventDefault()}>
|
|
86
|
+
<Home />
|
|
87
|
+
<span>首页</span>
|
|
88
|
+
</a>
|
|
89
|
+
</SidebarMenuButton>
|
|
90
|
+
</SidebarMenuItem>
|
|
91
|
+
{/* 知识库 + 二级 */}
|
|
92
|
+
<Collapsible defaultOpen asChild className="group/collapsible">
|
|
93
|
+
<SidebarMenuItem>
|
|
94
|
+
<CollapsibleTrigger asChild>
|
|
95
|
+
<SidebarMenuButton tooltip="知识库">
|
|
96
|
+
<BookOpen />
|
|
97
|
+
<span>知识库</span>
|
|
98
|
+
<ChevronRight className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
|
|
99
|
+
</SidebarMenuButton>
|
|
100
|
+
</CollapsibleTrigger>
|
|
101
|
+
<CollapsibleContent>
|
|
102
|
+
<SidebarMenuSub>
|
|
103
|
+
{kbSubItems.map((s) => (
|
|
104
|
+
<SidebarMenuSubItem key={s.title}>
|
|
105
|
+
<SidebarMenuSubButton
|
|
106
|
+
href={s.url}
|
|
107
|
+
isActive={s.url === '#kb-public'}
|
|
108
|
+
onClick={(e) => e.preventDefault()}
|
|
109
|
+
>
|
|
110
|
+
<span>{s.title}</span>
|
|
111
|
+
</SidebarMenuSubButton>
|
|
112
|
+
</SidebarMenuSubItem>
|
|
113
|
+
))}
|
|
114
|
+
</SidebarMenuSub>
|
|
115
|
+
</CollapsibleContent>
|
|
116
|
+
</SidebarMenuItem>
|
|
117
|
+
</Collapsible>
|
|
118
|
+
<SidebarMenuItem>
|
|
119
|
+
<SidebarMenuButton asChild tooltip="设置">
|
|
120
|
+
<a href="#settings" onClick={(e) => e.preventDefault()}>
|
|
121
|
+
<Settings />
|
|
122
|
+
<span>设置</span>
|
|
123
|
+
</a>
|
|
124
|
+
</SidebarMenuButton>
|
|
125
|
+
</SidebarMenuItem>
|
|
126
|
+
</SidebarMenu>
|
|
127
|
+
</SidebarGroup>
|
|
128
|
+
</SidebarContent>
|
|
129
|
+
</Sidebar>
|
|
130
|
+
<MainContent>
|
|
131
|
+
知识库展开后,折叠 Sidebar — 二级菜单会自动隐藏。
|
|
132
|
+
</MainContent>
|
|
133
|
+
</SidebarProvider>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### WithBadgeAndAction
|
|
137
|
+
|
|
138
|
+
徽标 + hover 操作:MenuBadge 显示数字,MenuAction 仅 hover 浮现
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<SidebarProvider>
|
|
142
|
+
<Sidebar {...args}>
|
|
143
|
+
<SidebarHeader>
|
|
144
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
145
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
146
|
+
Teamix Evo
|
|
147
|
+
</h1>
|
|
148
|
+
<SidebarTrigger />
|
|
149
|
+
</div>
|
|
150
|
+
</SidebarHeader>
|
|
151
|
+
<SidebarContent>
|
|
152
|
+
<SidebarGroup>
|
|
153
|
+
<SidebarGroupLabel>导航</SidebarGroupLabel>
|
|
154
|
+
<SidebarMenu>
|
|
155
|
+
{navItems.map((it) => (
|
|
156
|
+
<SidebarMenuItem key={it.title}>
|
|
157
|
+
<SidebarMenuButton asChild tooltip={it.title}>
|
|
158
|
+
<a href={it.url} onClick={(e) => e.preventDefault()}>
|
|
159
|
+
<it.icon />
|
|
160
|
+
<span>{it.title}</span>
|
|
161
|
+
</a>
|
|
162
|
+
</SidebarMenuButton>
|
|
163
|
+
{it.title === '收件箱' && (
|
|
164
|
+
<SidebarMenuBadge>5</SidebarMenuBadge>
|
|
165
|
+
)}
|
|
166
|
+
<SidebarMenuAction
|
|
167
|
+
showOnHover
|
|
168
|
+
aria-label="更多"
|
|
169
|
+
onClick={(e) => e.preventDefault()}
|
|
170
|
+
>
|
|
171
|
+
<MoreHorizontal />
|
|
172
|
+
</SidebarMenuAction>
|
|
173
|
+
</SidebarMenuItem>
|
|
174
|
+
))}
|
|
175
|
+
</SidebarMenu>
|
|
176
|
+
</SidebarGroup>
|
|
177
|
+
</SidebarContent>
|
|
178
|
+
</Sidebar>
|
|
179
|
+
<MainContent>
|
|
180
|
+
鼠标移到菜单项 — 右侧浮现「⋯」操作按钮;收件箱有未读徽标。
|
|
181
|
+
</MainContent>
|
|
182
|
+
</SidebarProvider>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### VariantFloating
|
|
186
|
+
|
|
187
|
+
浮起变体:Sidebar 脱离边缘,带圆角和阴影
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
<SidebarProvider>
|
|
191
|
+
<Sidebar {...args}>
|
|
192
|
+
<SidebarHeader>
|
|
193
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
194
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
195
|
+
Teamix Evo
|
|
196
|
+
</h1>
|
|
197
|
+
<SidebarTrigger />
|
|
198
|
+
</div>
|
|
199
|
+
</SidebarHeader>
|
|
200
|
+
<SidebarContent>
|
|
201
|
+
<SidebarGroup>
|
|
202
|
+
<SidebarGroupLabel>导航</SidebarGroupLabel>
|
|
203
|
+
<SidebarMenu>
|
|
204
|
+
{navItems.map((it) => (
|
|
205
|
+
<SidebarMenuItem key={it.title}>
|
|
206
|
+
<SidebarMenuButton asChild tooltip={it.title}>
|
|
207
|
+
<a href={it.url} onClick={(e) => e.preventDefault()}>
|
|
208
|
+
<it.icon />
|
|
209
|
+
<span>{it.title}</span>
|
|
210
|
+
</a>
|
|
211
|
+
</SidebarMenuButton>
|
|
212
|
+
</SidebarMenuItem>
|
|
213
|
+
))}
|
|
214
|
+
</SidebarMenu>
|
|
215
|
+
</SidebarGroup>
|
|
216
|
+
</SidebarContent>
|
|
217
|
+
</Sidebar>
|
|
218
|
+
<MainContent>
|
|
219
|
+
variant="floating" — 浮起、圆角、阴影。
|
|
220
|
+
</MainContent>
|
|
221
|
+
</SidebarProvider>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### VariantInset
|
|
225
|
+
|
|
226
|
+
内嵌变体:主内容区圆角内缩
|
|
227
|
+
|
|
228
|
+
```tsx
|
|
229
|
+
<SidebarProvider>
|
|
230
|
+
<Sidebar {...args}>
|
|
231
|
+
<SidebarHeader>
|
|
232
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
233
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
234
|
+
Teamix Evo
|
|
235
|
+
</h1>
|
|
236
|
+
<SidebarTrigger />
|
|
237
|
+
</div>
|
|
238
|
+
</SidebarHeader>
|
|
239
|
+
<SidebarContent>
|
|
240
|
+
<SidebarGroup>
|
|
241
|
+
<SidebarGroupLabel>导航</SidebarGroupLabel>
|
|
242
|
+
<SidebarMenu>
|
|
243
|
+
{navItems.map((it) => (
|
|
244
|
+
<SidebarMenuItem key={it.title}>
|
|
245
|
+
<SidebarMenuButton asChild tooltip={it.title}>
|
|
246
|
+
<a href={it.url} onClick={(e) => e.preventDefault()}>
|
|
247
|
+
<it.icon />
|
|
248
|
+
<span>{it.title}</span>
|
|
249
|
+
</a>
|
|
250
|
+
</SidebarMenuButton>
|
|
251
|
+
</SidebarMenuItem>
|
|
252
|
+
))}
|
|
253
|
+
</SidebarMenu>
|
|
254
|
+
</SidebarGroup>
|
|
255
|
+
</SidebarContent>
|
|
256
|
+
</Sidebar>
|
|
257
|
+
<MainContent>
|
|
258
|
+
variant="inset" — 主内容区域圆角内嵌。
|
|
259
|
+
</MainContent>
|
|
260
|
+
</SidebarProvider>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### WithRail
|
|
264
|
+
|
|
265
|
+
Rail 拖拽收合:Sidebar 右边缘 hover 出线条,点击切换
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
<SidebarProvider>
|
|
269
|
+
<Sidebar {...args}>
|
|
270
|
+
<SidebarHeader>
|
|
271
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
272
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
273
|
+
Teamix Evo
|
|
274
|
+
</h1>
|
|
275
|
+
<SidebarTrigger />
|
|
276
|
+
</div>
|
|
277
|
+
</SidebarHeader>
|
|
278
|
+
<SidebarContent>
|
|
279
|
+
<SidebarGroup>
|
|
280
|
+
<SidebarGroupLabel>导航</SidebarGroupLabel>
|
|
281
|
+
<SidebarMenu>
|
|
282
|
+
{navItems.map((it) => (
|
|
283
|
+
<SidebarMenuItem key={it.title}>
|
|
284
|
+
<SidebarMenuButton asChild tooltip={it.title}>
|
|
285
|
+
<a href={it.url} onClick={(e) => e.preventDefault()}>
|
|
286
|
+
<it.icon />
|
|
287
|
+
<span>{it.title}</span>
|
|
288
|
+
</a>
|
|
289
|
+
</SidebarMenuButton>
|
|
290
|
+
</SidebarMenuItem>
|
|
291
|
+
))}
|
|
292
|
+
</SidebarMenu>
|
|
293
|
+
</SidebarGroup>
|
|
294
|
+
</SidebarContent>
|
|
295
|
+
<SidebarRail />
|
|
296
|
+
</Sidebar>
|
|
297
|
+
<MainContent>
|
|
298
|
+
鼠标移到 Sidebar 右边缘 — 出现窄拖拽柄,点击切换折叠。
|
|
299
|
+
</MainContent>
|
|
300
|
+
</SidebarProvider>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### WithInputAndGroupAction
|
|
304
|
+
|
|
305
|
+
搜索输入 + 分组操作:SidebarInput + GroupAction
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
<SidebarProvider>
|
|
309
|
+
<Sidebar {...args}>
|
|
310
|
+
<SidebarHeader>
|
|
311
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
312
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
313
|
+
Teamix Evo
|
|
314
|
+
</h1>
|
|
315
|
+
<SidebarTrigger />
|
|
316
|
+
</div>
|
|
317
|
+
<SidebarInput placeholder="搜索…" />
|
|
318
|
+
</SidebarHeader>
|
|
319
|
+
<SidebarContent>
|
|
320
|
+
<SidebarGroup>
|
|
321
|
+
<SidebarGroupLabel>导航</SidebarGroupLabel>
|
|
322
|
+
<SidebarMenu>
|
|
323
|
+
{navItems.slice(0, 3).map((it) => (
|
|
324
|
+
<SidebarMenuItem key={it.title}>
|
|
325
|
+
<SidebarMenuButton asChild tooltip={it.title}>
|
|
326
|
+
<a href={it.url} onClick={(e) => e.preventDefault()}>
|
|
327
|
+
<it.icon />
|
|
328
|
+
<span>{it.title}</span>
|
|
329
|
+
</a>
|
|
330
|
+
</SidebarMenuButton>
|
|
331
|
+
</SidebarMenuItem>
|
|
332
|
+
))}
|
|
333
|
+
</SidebarMenu>
|
|
334
|
+
</SidebarGroup>
|
|
335
|
+
|
|
336
|
+
<SidebarSeparator />
|
|
337
|
+
|
|
338
|
+
<SidebarGroup>
|
|
339
|
+
<SidebarGroupLabel>收藏</SidebarGroupLabel>
|
|
340
|
+
<SidebarGroupAction
|
|
341
|
+
aria-label="管理收藏"
|
|
342
|
+
onClick={(e) => e.preventDefault()}
|
|
343
|
+
>
|
|
344
|
+
<MoreHorizontal />
|
|
345
|
+
</SidebarGroupAction>
|
|
346
|
+
<SidebarMenu>
|
|
347
|
+
{favoriteItems.map((f) => (
|
|
348
|
+
<SidebarMenuItem key={f.title}>
|
|
349
|
+
<SidebarMenuButton asChild tooltip={f.title} size="sm">
|
|
350
|
+
<a href={f.url} onClick={(e) => e.preventDefault()}>
|
|
351
|
+
<Star />
|
|
352
|
+
<span>{f.title}</span>
|
|
353
|
+
</a>
|
|
354
|
+
</SidebarMenuButton>
|
|
355
|
+
</SidebarMenuItem>
|
|
356
|
+
))}
|
|
357
|
+
</SidebarMenu>
|
|
358
|
+
</SidebarGroup>
|
|
359
|
+
</SidebarContent>
|
|
360
|
+
</Sidebar>
|
|
361
|
+
<MainContent>
|
|
362
|
+
顶部 SidebarInput 搜索 + 收藏分组头部「⋯」管理操作。
|
|
363
|
+
</MainContent>
|
|
364
|
+
</SidebarProvider>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### LoadingSkeleton
|
|
368
|
+
|
|
369
|
+
加载骨架:异步数据 ready 前的占位
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
<SidebarProvider>
|
|
373
|
+
<Sidebar {...args}>
|
|
374
|
+
<SidebarHeader>
|
|
375
|
+
<div className="flex items-center group-data-[collapsible=icon]:justify-center">
|
|
376
|
+
<h1 className="flex-1 px-2 text-sm font-semibold group-data-[collapsible=icon]:hidden">
|
|
377
|
+
Teamix Evo
|
|
378
|
+
</h1>
|
|
379
|
+
<SidebarTrigger />
|
|
380
|
+
</div>
|
|
381
|
+
</SidebarHeader>
|
|
382
|
+
<SidebarContent>
|
|
383
|
+
<SidebarGroup>
|
|
384
|
+
<SidebarGroupLabel>导航(加载中)</SidebarGroupLabel>
|
|
385
|
+
<SidebarMenu>
|
|
386
|
+
{Array.from({ length: 5 }).map((_, i) => (
|
|
387
|
+
<SidebarMenuItem key={i}>
|
|
388
|
+
<SidebarMenuSkeleton showIcon />
|
|
389
|
+
</SidebarMenuItem>
|
|
390
|
+
))}
|
|
391
|
+
</SidebarMenu>
|
|
392
|
+
</SidebarGroup>
|
|
393
|
+
</SidebarContent>
|
|
394
|
+
</Sidebar>
|
|
395
|
+
<MainContent>真实业务中骨架会在数据 ready 后切换为 Menu。</MainContent>
|
|
396
|
+
</SidebarProvider>
|
|
397
|
+
```
|
|
@@ -99,6 +99,19 @@ pulse / none 两种动画对照。
|
|
|
99
99
|
</div>
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
+
### Loading
|
|
103
|
+
|
|
104
|
+
loading + children 条件渲染:loading=false 时直接显示真实内容。
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
<div className="flex flex-col gap-3">
|
|
108
|
+
<Button onClick={() => setLoading((v) => !v)}>切换</Button>
|
|
109
|
+
<Skeleton loading={loading} className="h-8 w-64">
|
|
110
|
+
<span className="text-xs text-foreground">真实内容已加载</span>
|
|
111
|
+
</Skeleton>
|
|
112
|
+
</div>
|
|
113
|
+
```
|
|
114
|
+
|
|
102
115
|
### Avatar
|
|
103
116
|
|
|
104
117
|
头像骨架:三档尺寸 + 两种形状。
|
|
@@ -215,7 +215,7 @@ function Slider({
|
|
|
215
215
|
>
|
|
216
216
|
<SliderPrimitive.Range
|
|
217
217
|
data-slot="slider-range"
|
|
218
|
-
className="absolute bg-primary group-data-[reverse=true]/slider:bg-muted
|
|
218
|
+
className="absolute bg-primary select-none group-data-[reverse=true]/slider:bg-muted data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
|
|
219
219
|
/>
|
|
220
220
|
{parsedMarks.map((m) => (
|
|
221
221
|
<span
|
|
@@ -235,7 +235,7 @@ function Slider({
|
|
|
235
235
|
key={`label-${m.value}`}
|
|
236
236
|
data-slot="slider-mark-label"
|
|
237
237
|
style={labelStyle(m.value)}
|
|
238
|
-
className="pointer-events-none absolute whitespace-nowrap text-
|
|
238
|
+
className="pointer-events-none absolute text-xs whitespace-nowrap text-muted-foreground"
|
|
239
239
|
>
|
|
240
240
|
{m.label}
|
|
241
241
|
</span>
|
|
@@ -111,6 +111,27 @@
|
|
|
111
111
|
</>
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
### PromiseToast
|
|
115
|
+
|
|
116
|
+
Promise 链式更新 — 一次声明 loading / success / error 三态文案,自动跟随 Promise 状态。
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
<>
|
|
120
|
+
<Button
|
|
121
|
+
onClick={() =>
|
|
122
|
+
toast.promise(mockRequest(), {
|
|
123
|
+
loading: '正在提交订单...',
|
|
124
|
+
success: (data) => `${data.name} 已提交`,
|
|
125
|
+
error: (err: Error) => `提交失败:${err.message}`,
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
>
|
|
129
|
+
触发
|
|
130
|
+
</Button>
|
|
131
|
+
<Toaster />
|
|
132
|
+
</>
|
|
133
|
+
```
|
|
134
|
+
|
|
114
135
|
### Duration
|
|
115
136
|
|
|
116
137
|
持续时长 — `duration` 控制关闭延迟,`Infinity` 持久不关。对应 cloud-design `duration: 0`。
|
|
@@ -137,6 +158,30 @@
|
|
|
137
158
|
</div>
|
|
138
159
|
```
|
|
139
160
|
|
|
161
|
+
### Placement
|
|
162
|
+
|
|
163
|
+
容器位置 — `placement` 6 档形态,对应 cloud-design `Notification.config({ placement })`。
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
<div className="flex flex-col gap-3">
|
|
167
|
+
<div className="flex flex-wrap gap-2">
|
|
168
|
+
{placements.map((p) => (
|
|
169
|
+
<Button
|
|
170
|
+
key={p}
|
|
171
|
+
variant={p === placement ? 'default' : 'outline'}
|
|
172
|
+
onClick={() => {
|
|
173
|
+
setPlacement(p);
|
|
174
|
+
toast.success(`位置:${p}`);
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
{p}
|
|
178
|
+
</Button>
|
|
179
|
+
))}
|
|
180
|
+
</div>
|
|
181
|
+
<Toaster placement={placement} />
|
|
182
|
+
</div>
|
|
183
|
+
```
|
|
184
|
+
|
|
140
185
|
### Custom
|
|
141
186
|
|
|
142
187
|
自定义渲染 — `toast.custom` 完全接管节点,用于嵌入富内容卡片。
|
|
@@ -170,3 +215,44 @@
|
|
|
170
215
|
<Toaster />
|
|
171
216
|
</>
|
|
172
217
|
```
|
|
218
|
+
|
|
219
|
+
### DismissProgrammatic
|
|
220
|
+
|
|
221
|
+
主动关闭 — `toast.dismiss(id)` 关闭指定通知,`toast.dismiss()` 清空全部。
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
<div className="flex flex-wrap gap-2">
|
|
225
|
+
<Button
|
|
226
|
+
onClick={() => {
|
|
227
|
+
idRef.current = toast('一条可被定向关闭的通知', {
|
|
228
|
+
description: '保留这条 id,再点“关闭它”按钮。',
|
|
229
|
+
duration: Infinity,
|
|
230
|
+
});
|
|
231
|
+
}}
|
|
232
|
+
>
|
|
233
|
+
打开 1 条
|
|
234
|
+
</Button>
|
|
235
|
+
<Button
|
|
236
|
+
variant="outline"
|
|
237
|
+
onClick={() => {
|
|
238
|
+
for (let i = 0; i < 3; i += 1) {
|
|
239
|
+
toast.info(`批量通知 ${i + 1}`);
|
|
240
|
+
}
|
|
241
|
+
}}
|
|
242
|
+
>
|
|
243
|
+
打开 3 条
|
|
244
|
+
</Button>
|
|
245
|
+
<Button
|
|
246
|
+
variant="destructive"
|
|
247
|
+
onClick={() => {
|
|
248
|
+
if (idRef.current !== undefined) toast.dismiss(idRef.current);
|
|
249
|
+
}}
|
|
250
|
+
>
|
|
251
|
+
关闭它(按 id)
|
|
252
|
+
</Button>
|
|
253
|
+
<Button variant="destructive" onClick={() => toast.dismiss()}>
|
|
254
|
+
全部关闭
|
|
255
|
+
</Button>
|
|
256
|
+
<Toaster />
|
|
257
|
+
</div>
|
|
258
|
+
```
|
|
@@ -136,6 +136,37 @@ tip 位置:right(行内) 与 bottom(堆叠)。
|
|
|
136
136
|
</div>
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
+
### OverlayControlled
|
|
140
|
+
|
|
141
|
+
受控 visible + 100ms 防闪:短任务 (800ms) 不闪烁,长任务 (2000ms) 正常展示。
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
<div className="flex flex-col gap-4">
|
|
145
|
+
<Button
|
|
146
|
+
onClick={() => {
|
|
147
|
+
setVisible1(true);
|
|
148
|
+
setVisible2(true);
|
|
149
|
+
setTimeout(() => setVisible1(false), 800);
|
|
150
|
+
setTimeout(() => setVisible2(false), 2000);
|
|
151
|
+
}}
|
|
152
|
+
>
|
|
153
|
+
开始加载
|
|
154
|
+
</Button>
|
|
155
|
+
<div className="flex gap-6">
|
|
156
|
+
<SpinnerOverlay visible={visible1} tip="800ms 快任务">
|
|
157
|
+
<div className="h-20 w-40 rounded border border-border p-4 text-xs">
|
|
158
|
+
面板 1
|
|
159
|
+
</div>
|
|
160
|
+
</SpinnerOverlay>
|
|
161
|
+
<SpinnerOverlay visible={visible2} tip="2000ms 慢任务">
|
|
162
|
+
<div className="h-20 w-40 rounded border border-border p-4 text-xs">
|
|
163
|
+
面板 2
|
|
164
|
+
</div>
|
|
165
|
+
</SpinnerOverlay>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
```
|
|
169
|
+
|
|
139
170
|
### OverlayCustomIndicator
|
|
140
171
|
|
|
141
172
|
自定义 indicator 替换默认 Spinner。
|
|
@@ -148,6 +179,21 @@ tip 位置:right(行内) 与 bottom(堆叠)。
|
|
|
148
179
|
</SpinnerOverlay>
|
|
149
180
|
```
|
|
150
181
|
|
|
182
|
+
### Fullscreen
|
|
183
|
+
|
|
184
|
+
全屏遮罩 + Portal 投放 + Esc 关闭。
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<div>
|
|
188
|
+
<Button onClick={() => setVisible(true)}>打开全屏 Loading</Button>
|
|
189
|
+
<SpinnerFullscreen
|
|
190
|
+
visible={visible}
|
|
191
|
+
tip="加载中,按 Esc 关闭"
|
|
192
|
+
onVisibleChange={setVisible}
|
|
193
|
+
/>
|
|
194
|
+
</div>
|
|
195
|
+
```
|
|
196
|
+
|
|
151
197
|
### DotsDefault
|
|
152
198
|
|
|
153
199
|
SpinnerDots 三档尺寸:四点沿弧线轨道位移动画。
|
|
@@ -113,7 +113,7 @@ export const OverlayTipAlign: Story = {
|
|
|
113
113
|
|
|
114
114
|
/** 受控 visible + 100ms 防闪:短任务 (800ms) 不闪烁,长任务 (2000ms) 正常展示。 */
|
|
115
115
|
export const OverlayControlled: Story = {
|
|
116
|
-
render:
|
|
116
|
+
render: () => {
|
|
117
117
|
const [visible1, setVisible1] = React.useState(false);
|
|
118
118
|
const [visible2, setVisible2] = React.useState(false);
|
|
119
119
|
return (
|
|
@@ -158,7 +158,7 @@ export const OverlayCustomIndicator: Story = {
|
|
|
158
158
|
|
|
159
159
|
/** 全屏遮罩 + Portal 投放 + Esc 关闭。 */
|
|
160
160
|
export const Fullscreen: Story = {
|
|
161
|
-
render:
|
|
161
|
+
render: () => {
|
|
162
162
|
const [visible, setVisible] = React.useState(false);
|
|
163
163
|
return (
|
|
164
164
|
<div>
|
|
@@ -197,6 +197,26 @@ labelPlacement="horizontal"——标签在指示器右侧水平排列。
|
|
|
197
197
|
</div>
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
+
### Clickable
|
|
201
|
+
|
|
202
|
+
可点击步骤——传入 onChange 后步骤可交互切换。
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
<div className="flex flex-col gap-6">
|
|
206
|
+
<Steps
|
|
207
|
+
shape="circle"
|
|
208
|
+
current={current}
|
|
209
|
+
onChange={setCurrent}
|
|
210
|
+
items={[
|
|
211
|
+
{ title: '选择类型', description: '点击可跳转' },
|
|
212
|
+
{ title: '填写内容', description: '点击可跳转' },
|
|
213
|
+
{ title: '确认发布', description: '点击可跳转' },
|
|
214
|
+
]}
|
|
215
|
+
/>
|
|
216
|
+
<p className="text-xs text-muted-foreground">当前步骤:{current + 1}</p>
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
200
220
|
### AllStatuses
|
|
201
221
|
|
|
202
222
|
所有状态一览。
|
|
@@ -221,7 +221,7 @@ export const Small: Story = {
|
|
|
221
221
|
|
|
222
222
|
/** 可点击步骤——传入 onChange 后步骤可交互切换。 */
|
|
223
223
|
export const Clickable: Story = {
|
|
224
|
-
render:
|
|
224
|
+
render: () => {
|
|
225
225
|
const [current, setCurrent] = useState(0);
|
|
226
226
|
return (
|
|
227
227
|
<div className="flex flex-col gap-6">
|
|
@@ -23,7 +23,7 @@ import { cn } from '@/lib/utils';
|
|
|
23
23
|
// ─── cva ────────────────────────────────────────────────────────────────────
|
|
24
24
|
|
|
25
25
|
const switchVariants = cva(
|
|
26
|
-
'peer group/switch relative inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-ring/20 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 data-
|
|
26
|
+
'peer group/switch relative inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-ring/20 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 data-disabled:cursor-not-allowed data-disabled:opacity-50 data-[loading=true]:pointer-events-none data-[loading=true]:opacity-70 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
|
27
27
|
{
|
|
28
28
|
variants: {
|
|
29
29
|
size: {
|
|
@@ -80,7 +80,7 @@ const thumbVariants = cva(
|
|
|
80
80
|
|
|
81
81
|
const textVariants = cva(
|
|
82
82
|
// padding 与 order 跟随 root data-state 切换:满足"thumb 紧贴边缘"规范(root 不加 px)
|
|
83
|
-
'inline-flex
|
|
83
|
+
'inline-flex items-center justify-center leading-none whitespace-nowrap transition-colors select-none group-data-[state=checked]/switch:order-1 group-data-[state=checked]/switch:text-primary-foreground group-data-[state=unchecked]/switch:order-2 group-data-[state=unchecked]/switch:text-muted-foreground',
|
|
84
84
|
{
|
|
85
85
|
variants: {
|
|
86
86
|
size: {
|