@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
|
@@ -63,7 +63,7 @@ export const WithTrailingIcon: Story = {
|
|
|
63
63
|
* 仅当 value 非空时显示清除按钮。
|
|
64
64
|
*/
|
|
65
65
|
export const Search: Story = {
|
|
66
|
-
render:
|
|
66
|
+
render: () => {
|
|
67
67
|
const [value, setValue] = useState('');
|
|
68
68
|
return (
|
|
69
69
|
<InputGroup className="w-64">
|
|
@@ -93,7 +93,7 @@ export const Search: Story = {
|
|
|
93
93
|
* 仅当 `visible` 为 true 时渲染,点击由父级清空 `value`。
|
|
94
94
|
*/
|
|
95
95
|
export const Clear: Story = {
|
|
96
|
-
render:
|
|
96
|
+
render: () => {
|
|
97
97
|
const [value, setValue] = useState('hello world');
|
|
98
98
|
return (
|
|
99
99
|
<InputGroup className="w-64">
|
|
@@ -117,7 +117,7 @@ export const Clear: Story = {
|
|
|
117
117
|
* 密码输入:使用 `InputGroupPasswordToggle` 受控版,由父级同时控制 `type` 与 `visible`。
|
|
118
118
|
*/
|
|
119
119
|
export const Password: Story = {
|
|
120
|
-
render:
|
|
120
|
+
render: () => {
|
|
121
121
|
const [visible, setVisible] = useState(false);
|
|
122
122
|
return (
|
|
123
123
|
<InputGroup className="w-64">
|
|
@@ -138,7 +138,7 @@ export const Password: Story = {
|
|
|
138
138
|
|
|
139
139
|
/** 金额输入:后置货币符号,展示带格式化的数值输入。 */
|
|
140
140
|
export const Currency: Story = {
|
|
141
|
-
render:
|
|
141
|
+
render: () => {
|
|
142
142
|
const [value, setValue] = useState('1234.56');
|
|
143
143
|
const format = (v: string) => {
|
|
144
144
|
const num = parseFloat(v.replace(/,/g, ''));
|
|
@@ -199,7 +199,7 @@ export const Loading: Story = {
|
|
|
199
199
|
* 超过 maxLength 时计数自动转 destructive 色。
|
|
200
200
|
*/
|
|
201
201
|
export const WithCount: Story = {
|
|
202
|
-
render:
|
|
202
|
+
render: () => {
|
|
203
203
|
const [value, setValue] = useState('');
|
|
204
204
|
const max = 20;
|
|
205
205
|
return (
|
|
@@ -223,7 +223,7 @@ export const WithCount: Story = {
|
|
|
223
223
|
* 对齐 cloud-design `hasLimitHint` 的视觉位置。
|
|
224
224
|
*/
|
|
225
225
|
export const MultilineWithCount: Story = {
|
|
226
|
-
render:
|
|
226
|
+
render: () => {
|
|
227
227
|
const [value, setValue] = useState('');
|
|
228
228
|
const max = 100;
|
|
229
229
|
return (
|
|
@@ -224,7 +224,7 @@ const InputIP = React.forwardRef<HTMLDivElement, InputIPProps>(
|
|
|
224
224
|
{octets.map((octet, i) => (
|
|
225
225
|
<React.Fragment key={i}>
|
|
226
226
|
{i > 0 && (
|
|
227
|
-
<span className="
|
|
227
|
+
<span className="text-muted-foreground select-none">.</span>
|
|
228
228
|
)}
|
|
229
229
|
<input
|
|
230
230
|
ref={(el) => {
|
|
@@ -248,7 +248,7 @@ const InputIP = React.forwardRef<HTMLDivElement, InputIPProps>(
|
|
|
248
248
|
))}
|
|
249
249
|
{showCidr && (
|
|
250
250
|
<>
|
|
251
|
-
<span className="
|
|
251
|
+
<span className="px-0.5 text-muted-foreground select-none">/</span>
|
|
252
252
|
<Select
|
|
253
253
|
value={cidr || undefined}
|
|
254
254
|
onValueChange={handleCidrChange}
|
|
@@ -27,6 +27,28 @@ IP 地址输入框 InputIP
|
|
|
27
27
|
|
|
28
28
|
## 示例
|
|
29
29
|
|
|
30
|
+
### Controlled
|
|
31
|
+
|
|
32
|
+
受控模式,外部管理 value。
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<div className="flex flex-col gap-2">
|
|
36
|
+
<InputIP value={value} onChange={setValue} />
|
|
37
|
+
<span className="text-xs text-muted-foreground">当前值:{value}</span>
|
|
38
|
+
</div>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### WithCidr
|
|
42
|
+
|
|
43
|
+
带 CIDR 前缀选择的网段输入。右侧 CIDR 选择器使用 ui Select。
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<div className="flex flex-col gap-2">
|
|
47
|
+
<InputIP showCidr value={value} onChange={setValue} />
|
|
48
|
+
<span className="text-xs text-muted-foreground">当前值:{value}</span>
|
|
49
|
+
</div>
|
|
50
|
+
```
|
|
51
|
+
|
|
30
52
|
### Sizes
|
|
31
53
|
|
|
32
54
|
三种尺寸。
|
|
@@ -39,6 +61,14 @@ IP 地址输入框 InputIP
|
|
|
39
61
|
</div>
|
|
40
62
|
```
|
|
41
63
|
|
|
64
|
+
### Disabled
|
|
65
|
+
|
|
66
|
+
禁用态。
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<InputIP className="w-52" defaultValue="10.0.0.1" disabled />
|
|
70
|
+
```
|
|
71
|
+
|
|
42
72
|
### Invalid
|
|
43
73
|
|
|
44
74
|
错误态(校验失败)。
|
|
@@ -21,7 +21,7 @@ export const Default: Story = {
|
|
|
21
21
|
|
|
22
22
|
/** 受控模式,外部管理 value。 */
|
|
23
23
|
export const Controlled: Story = {
|
|
24
|
-
render:
|
|
24
|
+
render: () => {
|
|
25
25
|
const [value, setValue] = useState('192.168.1.1');
|
|
26
26
|
return (
|
|
27
27
|
<div className="flex flex-col gap-2">
|
|
@@ -34,7 +34,7 @@ export const Controlled: Story = {
|
|
|
34
34
|
|
|
35
35
|
/** 带 CIDR 前缀选择的网段输入。右侧 CIDR 选择器使用 ui Select。 */
|
|
36
36
|
export const WithCidr: Story = {
|
|
37
|
-
render:
|
|
37
|
+
render: () => {
|
|
38
38
|
const [value, setValue] = useState('192.168.1.0/24');
|
|
39
39
|
return (
|
|
40
40
|
<div className="flex flex-col gap-2">
|
|
@@ -304,7 +304,7 @@ const InputNumber = React.forwardRef<HTMLInputElement, InputNumberProps>(
|
|
|
304
304
|
onWheel={handleWheel}
|
|
305
305
|
data-slot="input-number-control"
|
|
306
306
|
className={cn(
|
|
307
|
-
'w-full bg-transparent px-2.5 text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed
|
|
307
|
+
'w-full bg-transparent px-2.5 text-foreground placeholder:text-muted-foreground read-only:cursor-default focus-visible:outline-none disabled:cursor-not-allowed',
|
|
308
308
|
variant === 'inline' && 'text-center',
|
|
309
309
|
)}
|
|
310
310
|
{...props}
|
|
@@ -325,7 +325,8 @@ const InputNumber = React.forwardRef<HTMLInputElement, InputNumberProps>(
|
|
|
325
325
|
{controls && variant === 'default' ? (
|
|
326
326
|
<div
|
|
327
327
|
data-slot="input-number-handlers"
|
|
328
|
-
|
|
328
|
+
// eslint-disable-next-line tailwindcss/no-contradicting-classname -- divide-color ≠ border-color
|
|
329
|
+
className="flex flex-col divide-y divide-input border-l border-input opacity-0 transition-opacity group-focus-within/input-number:opacity-100 group-hover/input-number:opacity-100"
|
|
329
330
|
>
|
|
330
331
|
<button
|
|
331
332
|
type="button"
|
|
@@ -125,6 +125,14 @@
|
|
|
125
125
|
</div>
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
### ReadOnly
|
|
129
|
+
|
|
130
|
+
`readOnly` 只读:可聚焦/复制但不可编辑、不可步进。
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
<InputNumber readOnly defaultValue={42} className="w-40" />
|
|
134
|
+
```
|
|
135
|
+
|
|
128
136
|
### Inline
|
|
129
137
|
|
|
130
138
|
`variant="inline"` 两侧加减按钮,适合紧凑场景。
|
|
@@ -147,6 +155,38 @@
|
|
|
147
155
|
<InputNumber controls={false} placeholder="纯输入" className="w-40" />
|
|
148
156
|
```
|
|
149
157
|
|
|
158
|
+
### ChangeOnBlur
|
|
159
|
+
|
|
160
|
+
`changeOnBlur={false}` 让 onChange 在每次有效输入时触发,否则仅 blur/Enter 提交。
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<div className="flex flex-col gap-3 text-xs">
|
|
164
|
+
<div className="flex items-center gap-3">
|
|
165
|
+
<InputNumber value={a} onChange={setA} className="w-40" />
|
|
166
|
+
<span className="text-muted-foreground">
|
|
167
|
+
默认(仅 blur/Enter 触发):{String(a)}
|
|
168
|
+
</span>
|
|
169
|
+
</div>
|
|
170
|
+
<div className="flex items-center gap-3">
|
|
171
|
+
<InputNumber
|
|
172
|
+
value={b}
|
|
173
|
+
onChange={setB}
|
|
174
|
+
changeOnBlur={false}
|
|
175
|
+
className="w-40"
|
|
176
|
+
/>
|
|
177
|
+
<span className="text-muted-foreground">实时触发:{String(b)}</span>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### ChangeOnWheel
|
|
183
|
+
|
|
184
|
+
`changeOnWheel` 启用滚轮调整(仅在聚焦时生效,默认关闭防误触)。
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<InputNumber changeOnWheel defaultValue={0} className="w-40" />
|
|
188
|
+
```
|
|
189
|
+
|
|
150
190
|
### Keyboard
|
|
151
191
|
|
|
152
192
|
`keyboard={false}` 关闭键盘 ↑↓ 步进。
|
|
@@ -154,3 +194,30 @@
|
|
|
154
194
|
```tsx
|
|
155
195
|
<InputNumber keyboard={false} defaultValue={0} className="w-40" />
|
|
156
196
|
```
|
|
197
|
+
|
|
198
|
+
### Invalid
|
|
199
|
+
|
|
200
|
+
`aria-invalid` 视觉与 Input 一致。
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
<InputNumber aria-invalid defaultValue={42} className="w-40" />
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Disabled
|
|
207
|
+
|
|
208
|
+
禁用状态。
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
<InputNumber disabled defaultValue={42} className="w-40" />
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Controlled
|
|
215
|
+
|
|
216
|
+
受控模式。
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
<div className="flex items-center gap-3">
|
|
220
|
+
<InputNumber value={val} onChange={setVal} className="w-40" />
|
|
221
|
+
<span className="text-xs text-muted-foreground">值: {String(val)}</span>
|
|
222
|
+
</div>
|
|
223
|
+
```
|
|
@@ -126,7 +126,7 @@ export const NoControls: Story = {
|
|
|
126
126
|
|
|
127
127
|
/** `changeOnBlur={false}` 让 onChange 在每次有效输入时触发,否则仅 blur/Enter 提交。 */
|
|
128
128
|
export const ChangeOnBlur: Story = {
|
|
129
|
-
render:
|
|
129
|
+
render: () => {
|
|
130
130
|
const [a, setA] = useState<number | string | null>(0);
|
|
131
131
|
const [b, setB] = useState<number | string | null>(0);
|
|
132
132
|
return (
|
|
@@ -175,7 +175,7 @@ export const Disabled: Story = {
|
|
|
175
175
|
|
|
176
176
|
/** 受控模式。 */
|
|
177
177
|
export const Controlled: Story = {
|
|
178
|
-
render:
|
|
178
|
+
render: () => {
|
|
179
179
|
const [val, setVal] = useState<number | string | null>(10);
|
|
180
180
|
return (
|
|
181
181
|
<div className="flex items-center gap-3">
|
|
@@ -66,7 +66,7 @@ function ItemGroupHeader({ className, ...props }: ItemGroupHeaderProps) {
|
|
|
66
66
|
<div
|
|
67
67
|
data-slot="item-group-header"
|
|
68
68
|
className={cn(
|
|
69
|
-
'flex items-center px-3 py-2.5 text-sm font-medium
|
|
69
|
+
'flex items-center border-b border-border px-3 py-2.5 text-sm font-medium',
|
|
70
70
|
className,
|
|
71
71
|
)}
|
|
72
72
|
{...props}
|
|
@@ -83,7 +83,7 @@ function ItemGroupFooter({ className, ...props }: ItemGroupFooterProps) {
|
|
|
83
83
|
<div
|
|
84
84
|
data-slot="item-group-footer"
|
|
85
85
|
className={cn(
|
|
86
|
-
'flex items-center px-3 py-2.5 text-xs text-muted-foreground
|
|
86
|
+
'flex items-center border-t border-border px-3 py-2.5 text-xs text-muted-foreground',
|
|
87
87
|
className,
|
|
88
88
|
)}
|
|
89
89
|
{...props}
|
|
@@ -94,7 +94,7 @@ function ItemGroupFooter({ className, ...props }: ItemGroupFooterProps) {
|
|
|
94
94
|
// ─── Item ─────────────────────────────────────────────────────────────────────
|
|
95
95
|
|
|
96
96
|
const itemVariants = cva(
|
|
97
|
-
'group/item flex w-full items-center text-xs
|
|
97
|
+
'group/item flex w-full items-center text-xs transition-colors duration-100 outline-none focus-visible:ring-1 focus-visible:ring-ring',
|
|
98
98
|
{
|
|
99
99
|
variants: {
|
|
100
100
|
variant: {
|
|
@@ -103,7 +103,7 @@ const itemVariants = cva(
|
|
|
103
103
|
muted: 'rounded-md bg-muted/50',
|
|
104
104
|
},
|
|
105
105
|
size: {
|
|
106
|
-
default: 'gap-3
|
|
106
|
+
default: 'gap-3 p-3',
|
|
107
107
|
sm: 'gap-2.5 px-3 py-2.5',
|
|
108
108
|
xs: 'gap-2 px-2.5 py-2',
|
|
109
109
|
},
|
|
@@ -63,6 +63,21 @@
|
|
|
63
63
|
</div>
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### AsyncSearch
|
|
67
|
+
|
|
68
|
+
通过 `onSearch` 配合 `filterOption={false}` 实现服务端搜索。
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<Mentions
|
|
72
|
+
options={opts}
|
|
73
|
+
loading={loading}
|
|
74
|
+
filterOption={false}
|
|
75
|
+
onSearch={handleSearch}
|
|
76
|
+
placeholder="输入 @ 远程搜索用户"
|
|
77
|
+
className="max-w-sm"
|
|
78
|
+
/>
|
|
79
|
+
```
|
|
80
|
+
|
|
66
81
|
### PlacementTop
|
|
67
82
|
|
|
68
83
|
浮层向上展开,适合靠近底部的输入区。
|
|
@@ -132,7 +132,7 @@ function MenubarItem({
|
|
|
132
132
|
data-inset={inset}
|
|
133
133
|
data-variant={variant}
|
|
134
134
|
className={cn(
|
|
135
|
-
'group/menubar-item relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-1 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive
|
|
135
|
+
'group/menubar-item relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-1 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive!',
|
|
136
136
|
className,
|
|
137
137
|
)}
|
|
138
138
|
{...props}
|
|
@@ -154,7 +154,7 @@ function MenubarCheckboxItem({
|
|
|
154
154
|
data-slot="menubar-checkbox-item"
|
|
155
155
|
data-inset={inset}
|
|
156
156
|
className={cn(
|
|
157
|
-
'relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-
|
|
157
|
+
'relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
158
158
|
className,
|
|
159
159
|
)}
|
|
160
160
|
checked={checked}
|
|
@@ -183,7 +183,7 @@ function MenubarRadioItem({
|
|
|
183
183
|
data-slot="menubar-radio-item"
|
|
184
184
|
data-inset={inset}
|
|
185
185
|
className={cn(
|
|
186
|
-
'relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-
|
|
186
|
+
'relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4',
|
|
187
187
|
className,
|
|
188
188
|
)}
|
|
189
189
|
{...props}
|
|
@@ -285,7 +285,7 @@ function MenubarSubContent({
|
|
|
285
285
|
<MenubarPrimitive.SubContent
|
|
286
286
|
data-slot="menubar-sub-content"
|
|
287
287
|
className={cn(
|
|
288
|
-
'z-50 min-w-32 origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=
|
|
288
|
+
'z-50 min-w-32 origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
|
289
289
|
className,
|
|
290
290
|
)}
|
|
291
291
|
{...props}
|
|
@@ -120,7 +120,7 @@ function NavigationMenuTrigger({
|
|
|
120
120
|
>
|
|
121
121
|
{children}{' '}
|
|
122
122
|
<ChevronDownIcon
|
|
123
|
-
className="relative top-px ml-1 size-3 transition duration-300 group-data-
|
|
123
|
+
className="relative top-px ml-1 size-3 transition duration-300 group-data-open/navigation-menu-trigger:rotate-180 group-data-popup-open/navigation-menu-trigger:rotate-180"
|
|
124
124
|
aria-hidden="true"
|
|
125
125
|
/>
|
|
126
126
|
</NavigationMenuPrimitive.Trigger>
|
|
@@ -136,7 +136,7 @@ function NavigationMenuContent({
|
|
|
136
136
|
<NavigationMenuPrimitive.Content
|
|
137
137
|
data-slot="navigation-menu-content"
|
|
138
138
|
className={cn(
|
|
139
|
-
'top-0 left-0 w-full p-1 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:ring-foreground/10 group-data-[viewport=false]/navigation-menu:duration-300 data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 data-[motion^=from-]:animate-in data-[motion^=from-]:fade-in data-[motion^=to-]:animate-out data-[motion^=to-]:fade-out **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none
|
|
139
|
+
'top-0 left-0 w-full p-1 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:ring-foreground/10 group-data-[viewport=false]/navigation-menu:duration-300 data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 data-[motion^=from-]:animate-in data-[motion^=from-]:fade-in data-[motion^=to-]:animate-out data-[motion^=to-]:fade-out **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 md:absolute md:w-auto',
|
|
140
140
|
className,
|
|
141
141
|
)}
|
|
142
142
|
{...props}
|
|
@@ -158,7 +158,7 @@ function NavigationMenuViewport({
|
|
|
158
158
|
<NavigationMenuPrimitive.Viewport
|
|
159
159
|
data-slot="navigation-menu-viewport"
|
|
160
160
|
className={cn(
|
|
161
|
-
'origin-top-center relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden rounded-md bg-popover text-popover-foreground shadow ring-1 ring-foreground/10 duration-100
|
|
161
|
+
'origin-top-center relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden rounded-md bg-popover text-popover-foreground shadow ring-1 ring-foreground/10 duration-100 data-[state=closed]:animate-out data-[state=closed]:zoom-out-90 data-[state=open]:animate-in data-[state=open]:zoom-in-90 md:w-(--radix-navigation-menu-viewport-width)',
|
|
162
162
|
className,
|
|
163
163
|
)}
|
|
164
164
|
{...props}
|
|
@@ -198,7 +198,7 @@ function NavigationMenuIndicator({
|
|
|
198
198
|
)}
|
|
199
199
|
{...props}
|
|
200
200
|
>
|
|
201
|
-
<div className="relative top-3/5
|
|
201
|
+
<div className="relative top-3/5 size-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
|
202
202
|
</NavigationMenuPrimitive.Indicator>
|
|
203
203
|
);
|
|
204
204
|
}
|
|
@@ -102,7 +102,7 @@ const PageHeaderHeading = React.forwardRef<
|
|
|
102
102
|
aria-label="返回"
|
|
103
103
|
className={cn(
|
|
104
104
|
'inline-flex shrink-0 cursor-pointer items-center justify-center rounded-sm text-muted-foreground transition-colors',
|
|
105
|
-
'hover:text-foreground focus-visible:
|
|
105
|
+
'hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',
|
|
106
106
|
)}
|
|
107
107
|
>
|
|
108
108
|
<ArrowLeft className="size-6" aria-hidden="true" />
|
|
@@ -166,7 +166,7 @@ const PageHeaderDescription = React.forwardRef<
|
|
|
166
166
|
<p
|
|
167
167
|
ref={ref}
|
|
168
168
|
data-slot="page-header-description"
|
|
169
|
-
className={cn('
|
|
169
|
+
className={cn('mt-2 text-xs text-muted-foreground', className)}
|
|
170
170
|
{...props}
|
|
171
171
|
/>
|
|
172
172
|
));
|
|
@@ -23,6 +23,151 @@
|
|
|
23
23
|
|
|
24
24
|
## 示例
|
|
25
25
|
|
|
26
|
+
### WithDescription
|
|
27
|
+
|
|
28
|
+
标题 + 描述:标题下方附加一行描述文字。
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<PageHeader>
|
|
32
|
+
<PageHeaderContent>
|
|
33
|
+
<div className="flex flex-col">
|
|
34
|
+
<PageHeaderHeading>
|
|
35
|
+
<PageHeaderTitle>页面标题</PageHeaderTitle>
|
|
36
|
+
</PageHeaderHeading>
|
|
37
|
+
<PageHeaderDescription>
|
|
38
|
+
页面描述页面描述页面描述页面描述页面描述页面描述页面描述
|
|
39
|
+
</PageHeaderDescription>
|
|
40
|
+
</div>
|
|
41
|
+
</PageHeaderContent>
|
|
42
|
+
</PageHeader>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### OnlyBreadcrumb
|
|
46
|
+
|
|
47
|
+
仅面包屑:只有面包屑导航,无标题。
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<PageHeader>
|
|
51
|
+
<PageHeaderNav>
|
|
52
|
+
<Breadcrumb>
|
|
53
|
+
<BreadcrumbList>
|
|
54
|
+
<BreadcrumbItem>
|
|
55
|
+
<BreadcrumbLink href="#">首页</BreadcrumbLink>
|
|
56
|
+
</BreadcrumbItem>
|
|
57
|
+
<BreadcrumbSeparator />
|
|
58
|
+
<BreadcrumbItem>
|
|
59
|
+
<BreadcrumbLink href="#">实例列表</BreadcrumbLink>
|
|
60
|
+
</BreadcrumbItem>
|
|
61
|
+
<BreadcrumbSeparator />
|
|
62
|
+
<BreadcrumbItem>
|
|
63
|
+
<BreadcrumbPage>实例详情</BreadcrumbPage>
|
|
64
|
+
</BreadcrumbItem>
|
|
65
|
+
</BreadcrumbList>
|
|
66
|
+
</Breadcrumb>
|
|
67
|
+
</PageHeaderNav>
|
|
68
|
+
</PageHeader>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### WithBreadcrumb
|
|
72
|
+
|
|
73
|
+
面包屑 + 标题:面包屑导航 + 标题,常见于二级页面。
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
<PageHeader>
|
|
77
|
+
<PageHeaderNav>
|
|
78
|
+
<Breadcrumb>
|
|
79
|
+
<BreadcrumbList>
|
|
80
|
+
<BreadcrumbItem>
|
|
81
|
+
<BreadcrumbLink href="#">首页</BreadcrumbLink>
|
|
82
|
+
</BreadcrumbItem>
|
|
83
|
+
<BreadcrumbSeparator />
|
|
84
|
+
<BreadcrumbItem>
|
|
85
|
+
<BreadcrumbLink href="#">实例列表</BreadcrumbLink>
|
|
86
|
+
</BreadcrumbItem>
|
|
87
|
+
<BreadcrumbSeparator />
|
|
88
|
+
<BreadcrumbItem>
|
|
89
|
+
<BreadcrumbPage>实例详情</BreadcrumbPage>
|
|
90
|
+
</BreadcrumbItem>
|
|
91
|
+
</BreadcrumbList>
|
|
92
|
+
</Breadcrumb>
|
|
93
|
+
</PageHeaderNav>
|
|
94
|
+
<PageHeaderContent>
|
|
95
|
+
<PageHeaderHeading>
|
|
96
|
+
<PageHeaderTitle>实例详情</PageHeaderTitle>
|
|
97
|
+
</PageHeaderHeading>
|
|
98
|
+
</PageHeaderContent>
|
|
99
|
+
</PageHeader>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Full
|
|
103
|
+
|
|
104
|
+
完整版页头:面包屑 + 帮助链接 + 返回 + 主图标 + 标题(含 ⓘ) + 描述 + 多操作。
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
<PageHeader>
|
|
108
|
+
<PageHeaderNav>
|
|
109
|
+
<Breadcrumb>
|
|
110
|
+
<BreadcrumbList>
|
|
111
|
+
<BreadcrumbItem>
|
|
112
|
+
<BreadcrumbLink href="#">首页</BreadcrumbLink>
|
|
113
|
+
</BreadcrumbItem>
|
|
114
|
+
<BreadcrumbSeparator />
|
|
115
|
+
<BreadcrumbItem>
|
|
116
|
+
<BreadcrumbLink href="#">实例列表</BreadcrumbLink>
|
|
117
|
+
</BreadcrumbItem>
|
|
118
|
+
<BreadcrumbSeparator />
|
|
119
|
+
<BreadcrumbItem>
|
|
120
|
+
<BreadcrumbPage>实例详情</BreadcrumbPage>
|
|
121
|
+
</BreadcrumbItem>
|
|
122
|
+
</BreadcrumbList>
|
|
123
|
+
</Breadcrumb>
|
|
124
|
+
<div className="flex items-center gap-4">
|
|
125
|
+
<a
|
|
126
|
+
href="#"
|
|
127
|
+
className="inline-flex items-center gap-1 text-muted-foreground hover:text-foreground"
|
|
128
|
+
>
|
|
129
|
+
<BookOpen className="size-3.5" aria-hidden="true" />
|
|
130
|
+
帮助文档
|
|
131
|
+
</a>
|
|
132
|
+
<a href="#" className="text-muted-foreground hover:text-foreground">
|
|
133
|
+
切换实例
|
|
134
|
+
</a>
|
|
135
|
+
</div>
|
|
136
|
+
</PageHeaderNav>
|
|
137
|
+
<PageHeaderContent>
|
|
138
|
+
<div className="flex flex-col">
|
|
139
|
+
<PageHeaderHeading goBack onBack={() => alert('返回')}>
|
|
140
|
+
<span
|
|
141
|
+
aria-hidden="true"
|
|
142
|
+
className="flex size-8 shrink-0 items-center justify-center rounded-md bg-primary text-primary-foreground"
|
|
143
|
+
>
|
|
144
|
+
<Boxes className="size-5" />
|
|
145
|
+
</span>
|
|
146
|
+
<PageHeaderTitle tooltip="该实例为生产环境,建议谨慎操作。">
|
|
147
|
+
页面标题
|
|
148
|
+
</PageHeaderTitle>
|
|
149
|
+
<Tag variant="solid" color="success" size="lg">
|
|
150
|
+
标签一
|
|
151
|
+
</Tag>
|
|
152
|
+
<Tag variant="solid" color="primary" size="lg">
|
|
153
|
+
标签二
|
|
154
|
+
</Tag>
|
|
155
|
+
<Tag variant="solid" color="destructive" size="lg">
|
|
156
|
+
标签三
|
|
157
|
+
</Tag>
|
|
158
|
+
</PageHeaderHeading>
|
|
159
|
+
<PageHeaderDescription>
|
|
160
|
+
页面描述页面描述页面描述页面描述页面描述页面描述页面描述
|
|
161
|
+
</PageHeaderDescription>
|
|
162
|
+
</div>
|
|
163
|
+
<PageHeaderActions>
|
|
164
|
+
<Button variant="outline">普通按钮</Button>
|
|
165
|
+
<Button>主要按钮</Button>
|
|
166
|
+
</PageHeaderActions>
|
|
167
|
+
</PageHeaderContent>
|
|
168
|
+
</PageHeader>
|
|
169
|
+
```
|
|
170
|
+
|
|
26
171
|
### WithStatistic
|
|
27
172
|
|
|
28
173
|
带数据概览:右侧使用 Statistic 组件展示 KPI 指标。
|
|
@@ -93,7 +93,7 @@ function PageShell({
|
|
|
93
93
|
// 受限容器(如 storybook `LayoutSandbox`)通过外级注入 `min-height: 0; height: 100%` 重置。
|
|
94
94
|
// 说明:传入的 sidebar 如果是默认 collapsible="offcanvas",其内部使用 `position: fixed`、
|
|
95
95
|
// 高度 100svh,适用于全屏页面;在受限容器中需使用 `collapsible="none"` 退出 fixed 布局。
|
|
96
|
-
className={cn('!flex-col', className)}
|
|
96
|
+
className={cn('!h-svh !flex-col', className)}
|
|
97
97
|
style={
|
|
98
98
|
{
|
|
99
99
|
'--sidebar-width': sidebarWidth,
|
|
@@ -103,11 +103,11 @@ function PageShell({
|
|
|
103
103
|
{...props}
|
|
104
104
|
>
|
|
105
105
|
{header}
|
|
106
|
-
<div className="flex w-full flex-1
|
|
106
|
+
<div className="flex min-h-0 w-full flex-1">
|
|
107
107
|
{sidebar}
|
|
108
108
|
<SidebarInset
|
|
109
109
|
data-slot="page-shell-content"
|
|
110
|
-
className={cn('!min-h-0 overflow-
|
|
110
|
+
className={cn('!min-h-0 overflow-hidden', bgClass)}
|
|
111
111
|
>
|
|
112
112
|
{children}
|
|
113
113
|
</SidebarInset>
|