@boxcustodia/library 2.0.0-alpha.14 → 2.0.0-alpha.16
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/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +8 -10
- package/dist/index.es.js +1189 -1209
- package/package.json +1 -1
- package/src/__doc__/Changelog.mdx +6 -6
- package/src/__doc__/V2.mdx +8 -9
- package/src/components/auto-complete/auto-complete.stories.tsx +0 -1
- package/src/components/button/button.stories.tsx +31 -14
- package/src/components/button/button.tsx +10 -34
- package/src/components/button/components/base-button.tsx +8 -13
- package/src/components/calendar/calendar.tsx +1 -1
- package/src/components/card/card.stories.tsx +0 -1
- package/src/components/combobox/combobox.tsx +1 -1
- package/src/components/date-picker/date-input.tsx +1 -1
- package/src/components/date-picker/date-picker.tsx +1 -1
- package/src/components/dropzone/dropzone.stories.tsx +0 -1
- package/src/components/empty/empty.stories.tsx +0 -1
- package/src/components/input/input.tsx +1 -1
- package/src/components/menu/menu.stories.tsx +0 -1
- package/src/components/menu/menu.tsx +4 -4
- package/src/components/number-input/number-input.tsx +4 -4
- package/src/components/pagination/pagination.stories.tsx +0 -1
- package/src/components/password/password.tsx +1 -1
- package/src/components/stepper/stepper.stories.tsx +0 -1
- package/src/components/tabs/tabs.stories.tsx +0 -1
- package/src/components/tag/tag.stories.tsx +20 -27
- package/src/components/tag/tag.tsx +5 -1
- package/src/components/timeline/timeline.stories.tsx +0 -1
- package/src/components/tree/tree.stories.tsx +0 -1
- package/src/utils/form.tsx +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
-
import { ChangelogViewer } from "./Examples";
|
|
3
|
-
|
|
4
|
-
<Meta title="Documentation/Changelog" />
|
|
5
|
-
|
|
6
|
-
<ChangelogViewer />
|
|
1
|
+
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
import { ChangelogViewer } from "./Examples";
|
|
3
|
+
|
|
4
|
+
<Meta title="Documentation/Changelog" />
|
|
5
|
+
|
|
6
|
+
<ChangelogViewer />
|
package/src/__doc__/V2.mdx
CHANGED
|
@@ -283,15 +283,16 @@ import { buttonVariants } from "@boxcustodia/library";
|
|
|
283
283
|
+ <Button onClick={() => { void save(); }}>Guardar</Button>
|
|
284
284
|
```
|
|
285
285
|
|
|
286
|
-
|
|
286
|
+
**Props `icon` y `iconPosition` eliminadas.** Los íconos se componen directamente como `children` y la posición la define el orden en el JSX. Sin atributos extra ni configuración:
|
|
287
287
|
|
|
288
288
|
```diff
|
|
289
|
+
- <Button icon={<TrashIcon />}>Borrar</Button>
|
|
290
|
+
+ <Button><TrashIcon />Borrar</Button>
|
|
291
|
+
|
|
289
292
|
- <Button icon={<TrashIcon />} iconPosition="inline-end">Borrar</Button>
|
|
290
|
-
+ <Button
|
|
293
|
+
+ <Button>Borrar<TrashIcon /></Button>
|
|
291
294
|
```
|
|
292
295
|
|
|
293
|
-
Valores aceptados: `inline-start` (default) o `inline-end`.
|
|
294
|
-
|
|
295
296
|
**`shape` eliminado.** Para esquinas custom, override con `className="rounded-..."`.
|
|
296
297
|
|
|
297
298
|
**`loaderReplace` y `append` eliminados.** El loader siempre **reemplaza** el contenido (efecto antes conocido como `loaderReplace`). El efecto `append` (loader al lado del contenido) ya no se soporta.
|
|
@@ -973,15 +974,13 @@ Para comportamientos que `classNames` no cubre (handlers en `<tr>`, refs, custom
|
|
|
973
974
|
+ <Tag className="bg-success/10 text-success">Done</Tag>
|
|
974
975
|
```
|
|
975
976
|
|
|
976
|
-
**`icon` eliminado.** v1 tenía slot dedicado para ícono. v2 acepta el ícono como children
|
|
977
|
+
**`icon` eliminado.** v1 tenía slot dedicado para ícono. v2 acepta el ícono como children — la posición la define el orden en el JSX:
|
|
977
978
|
|
|
978
979
|
```diff
|
|
979
980
|
- <Tag icon={<Check />}>Approved</Tag>
|
|
980
|
-
+ <Tag><Check
|
|
981
|
+
+ <Tag><Check /> Approved</Tag>
|
|
981
982
|
```
|
|
982
983
|
|
|
983
|
-
Valores aceptados: `inline-start` (antes del texto) o `inline-end` (después).
|
|
984
|
-
|
|
985
984
|
**`rounded` eliminado.** v2 siempre renderea pill (rounded total). Para otros radios usá `className`:
|
|
986
985
|
|
|
987
986
|
```diff
|
|
@@ -1002,7 +1001,7 @@ Valores aceptados: `inline-start` (antes del texto) o `inline-end` (después).
|
|
|
1002
1001
|
- <Tag closable onClose={handleRemove}>Item</Tag>
|
|
1003
1002
|
+ <Tag>
|
|
1004
1003
|
+ Item
|
|
1005
|
-
+ <button
|
|
1004
|
+
+ <button onClick={handleRemove}>
|
|
1006
1005
|
+ <XIcon />
|
|
1007
1006
|
+ </button>
|
|
1008
1007
|
+ </Tag>
|
|
@@ -24,7 +24,6 @@ const meta: Meta<typeof Button> = {
|
|
|
24
24
|
args: {
|
|
25
25
|
children: "Click me",
|
|
26
26
|
},
|
|
27
|
-
tags: ["beta"],
|
|
28
27
|
parameters: { layout: "centered" },
|
|
29
28
|
};
|
|
30
29
|
|
|
@@ -87,30 +86,42 @@ export const Sizes: Story = {
|
|
|
87
86
|
};
|
|
88
87
|
|
|
89
88
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
89
|
+
* Compose icons directly as children. Position is determined by JSX order —
|
|
90
|
+
* place the icon before or after the label. Use an icon-only size (`icon`,
|
|
91
|
+
* `icon-sm`, etc.) for square icon buttons.
|
|
93
92
|
*/
|
|
94
93
|
export const WithIcon: Story = {
|
|
95
94
|
render: (args) => (
|
|
96
95
|
<div className="flex flex-wrap items-center gap-4">
|
|
97
|
-
<Button {...args}
|
|
96
|
+
<Button {...args}>
|
|
97
|
+
<SearchIcon />
|
|
98
98
|
Search
|
|
99
99
|
</Button>
|
|
100
|
-
<Button {...args}
|
|
100
|
+
<Button {...args}>
|
|
101
101
|
Search
|
|
102
|
+
<SearchIcon />
|
|
103
|
+
</Button>
|
|
104
|
+
<Button size="icon">
|
|
105
|
+
<SearchIcon />
|
|
102
106
|
</Button>
|
|
103
|
-
<Button icon={<SearchIcon />} size="icon" />
|
|
104
107
|
</div>
|
|
105
108
|
),
|
|
106
109
|
parameters: {
|
|
107
110
|
docs: {
|
|
108
111
|
source: {
|
|
109
|
-
code: `<Button
|
|
112
|
+
code: `<Button>
|
|
113
|
+
<SearchIcon />
|
|
114
|
+
Search
|
|
115
|
+
</Button>
|
|
110
116
|
|
|
111
|
-
<Button
|
|
117
|
+
<Button>
|
|
118
|
+
Search
|
|
119
|
+
<SearchIcon />
|
|
120
|
+
</Button>
|
|
112
121
|
|
|
113
|
-
<Button
|
|
122
|
+
<Button size="icon">
|
|
123
|
+
<SearchIcon />
|
|
124
|
+
</Button>`,
|
|
114
125
|
},
|
|
115
126
|
},
|
|
116
127
|
},
|
|
@@ -139,10 +150,13 @@ export const Loading: Story = {
|
|
|
139
150
|
</p>
|
|
140
151
|
<div className="flex flex-wrap items-center gap-3">
|
|
141
152
|
<Button onClick={sleep}>Save</Button>
|
|
142
|
-
<Button onClick={sleep}
|
|
153
|
+
<Button onClick={sleep}>
|
|
154
|
+
<SearchIcon />
|
|
143
155
|
Search
|
|
144
156
|
</Button>
|
|
145
|
-
<Button onClick={sleep}
|
|
157
|
+
<Button onClick={sleep} size="icon">
|
|
158
|
+
<SearchIcon />
|
|
159
|
+
</Button>
|
|
146
160
|
</div>
|
|
147
161
|
</section>
|
|
148
162
|
|
|
@@ -154,10 +168,13 @@ export const Loading: Story = {
|
|
|
154
168
|
</p>
|
|
155
169
|
<div className="flex flex-wrap items-center gap-3">
|
|
156
170
|
<Button loading>Save</Button>
|
|
157
|
-
<Button loading
|
|
171
|
+
<Button loading>
|
|
172
|
+
<SearchIcon />
|
|
158
173
|
Search
|
|
159
174
|
</Button>
|
|
160
|
-
<Button loading
|
|
175
|
+
<Button loading size="icon">
|
|
176
|
+
<SearchIcon />
|
|
177
|
+
</Button>
|
|
161
178
|
</div>
|
|
162
179
|
</section>
|
|
163
180
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
-
import { type ComponentProps
|
|
2
|
+
import { type ComponentProps } from "react";
|
|
3
3
|
import { cn } from "../../lib";
|
|
4
4
|
import { BaseButton } from "./components/base-button";
|
|
5
5
|
|
|
6
6
|
const buttonVariants = cva(
|
|
7
7
|
[
|
|
8
|
-
"group/button relative inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding",
|
|
8
|
+
"group/button relative inline-flex shrink-0 items-center justify-center gap-1 rounded-lg border border-transparent bg-clip-padding",
|
|
9
9
|
"text-sm font-medium whitespace-nowrap transition-all outline-none select-none",
|
|
10
10
|
"focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
|
|
11
11
|
"active:not-aria-[haspopup]:translate-y-px",
|
|
12
12
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
13
13
|
"aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
14
14
|
"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
15
|
-
"[&[data-loading]
|
|
15
|
+
"[&[data-loading]>[data-content]]:invisible",
|
|
16
16
|
"[&[data-loading]]:pointer-events-none",
|
|
17
17
|
],
|
|
18
18
|
{
|
|
@@ -31,11 +31,10 @@ const buttonVariants = cva(
|
|
|
31
31
|
link: "text-primary underline-offset-4 hover:underline",
|
|
32
32
|
},
|
|
33
33
|
size: {
|
|
34
|
-
default:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
lg: "h-9 [--btn-gap:0.375rem] px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
34
|
+
default: "h-8 px-2.5",
|
|
35
|
+
xs: "h-6 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
36
|
+
sm: "h-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3.5",
|
|
37
|
+
lg: "h-9 px-2.5",
|
|
39
38
|
icon: "size-8",
|
|
40
39
|
"icon-xs":
|
|
41
40
|
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
@@ -52,38 +51,15 @@ const buttonVariants = cva(
|
|
|
52
51
|
);
|
|
53
52
|
|
|
54
53
|
type BaseButtonProps = ComponentProps<typeof BaseButton>;
|
|
55
|
-
type Props = BaseButtonProps &
|
|
56
|
-
VariantProps<typeof buttonVariants> & {
|
|
57
|
-
icon?: ReactElement;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const Button = ({
|
|
61
|
-
variant,
|
|
62
|
-
size,
|
|
63
|
-
className,
|
|
64
|
-
icon,
|
|
65
|
-
children,
|
|
66
|
-
...rest
|
|
67
|
-
}: Props) => {
|
|
68
|
-
const iconPosition =
|
|
69
|
-
(icon?.props as { "data-icon"?: string } | undefined)?.["data-icon"] ??
|
|
70
|
-
"inline-start";
|
|
71
|
-
const iconEl = icon
|
|
72
|
-
? cloneElement(icon as ReactElement<{ "data-icon"?: string }>, {
|
|
73
|
-
"data-icon": iconPosition,
|
|
74
|
-
})
|
|
75
|
-
: null;
|
|
54
|
+
type Props = BaseButtonProps & VariantProps<typeof buttonVariants>;
|
|
76
55
|
|
|
56
|
+
const Button = ({ variant, size, className, ...rest }: Props) => {
|
|
77
57
|
return (
|
|
78
58
|
<BaseButton
|
|
79
59
|
{...rest}
|
|
80
60
|
className={cn(buttonVariants({ variant, size }), className)}
|
|
81
61
|
data-variant={variant || "default"}
|
|
82
|
-
|
|
83
|
-
{iconEl && iconPosition !== "inline-end" && iconEl}
|
|
84
|
-
{children}
|
|
85
|
-
{iconEl && iconPosition === "inline-end" && iconEl}
|
|
86
|
-
</BaseButton>
|
|
62
|
+
/>
|
|
87
63
|
);
|
|
88
64
|
};
|
|
89
65
|
|
|
@@ -2,7 +2,6 @@ import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
|
2
2
|
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
3
3
|
import { LoaderCircle } from "lucide-react";
|
|
4
4
|
import { type ComponentProps } from "react";
|
|
5
|
-
import { cn } from "../../../lib";
|
|
6
5
|
|
|
7
6
|
interface Props extends ComponentProps<typeof ButtonPrimitive> {
|
|
8
7
|
loading?: boolean;
|
|
@@ -44,20 +43,16 @@ export const BaseButton = ({
|
|
|
44
43
|
onClick={handleClick}
|
|
45
44
|
style={style}
|
|
46
45
|
>
|
|
47
|
-
<span className="
|
|
46
|
+
<span data-content className="contents">
|
|
48
47
|
{children}
|
|
49
48
|
</span>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"group-data-[loading]/button:inset-0",
|
|
58
|
-
"group-data-[loading]/button:m-auto",
|
|
59
|
-
)}
|
|
60
|
-
/>
|
|
49
|
+
{loading && (
|
|
50
|
+
<LoaderCircle
|
|
51
|
+
data-loader
|
|
52
|
+
data-testid="btn-loader"
|
|
53
|
+
className="absolute inset-0 m-auto size-4 animate-spin"
|
|
54
|
+
/>
|
|
55
|
+
)}
|
|
61
56
|
</ButtonPrimitive>
|
|
62
57
|
);
|
|
63
58
|
};
|
|
@@ -530,7 +530,7 @@ export function ComboboxChip({
|
|
|
530
530
|
}): React.ReactElement {
|
|
531
531
|
return (
|
|
532
532
|
<ComboboxPrimitive.Chip
|
|
533
|
-
className="flex items-center pl-1 rounded-[calc(var(--radius-md)-1px)] bg-accent font-medium text-accent-foreground text-sm outline-none sm:text-xs/(--text-xs--line-height) [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5"
|
|
533
|
+
className="flex my-auto items-center pl-1 rounded-[calc(var(--radius-md)-1px)] bg-accent font-medium text-accent-foreground text-sm outline-none sm:text-xs/(--text-xs--line-height) [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5 h-6"
|
|
534
534
|
data-slot="combobox-chip"
|
|
535
535
|
{...props}
|
|
536
536
|
>
|
|
@@ -88,7 +88,7 @@ export const DateInput = (props: DateInputProps) => {
|
|
|
88
88
|
<div
|
|
89
89
|
className={cn(
|
|
90
90
|
inputBaseClasses,
|
|
91
|
-
"flex items-center gap-2 h-
|
|
91
|
+
"flex items-center gap-2 h-8",
|
|
92
92
|
"has-[:focus-visible]:border-ring",
|
|
93
93
|
"aria-invalid:border-error has-[:focus-visible]:aria-invalid:ring-error/20",
|
|
94
94
|
"has-aria-invalid:border-error has-[:focus-visible]:has-aria-invalid:ring-error/20",
|
|
@@ -75,7 +75,7 @@ const PickerShell = ({
|
|
|
75
75
|
disabled={disabled}
|
|
76
76
|
className={cn(
|
|
77
77
|
inputBaseClasses,
|
|
78
|
-
"inline-flex items-center gap-2 h-
|
|
78
|
+
"inline-flex items-center gap-2 h-8 cursor-pointer text-left",
|
|
79
79
|
"focus-visible:border-ring",
|
|
80
80
|
"aria-invalid:border-error focus-visible:aria-invalid:ring-error/20",
|
|
81
81
|
"group-data-[invalid]:border-error focus-visible:group-data-[invalid]:ring-error/20",
|
|
@@ -3,7 +3,7 @@ import { type ChangeEvent, type ComponentPropsWithoutRef } from "react";
|
|
|
3
3
|
import { cn } from "../../lib";
|
|
4
4
|
|
|
5
5
|
export const inputBaseClasses =
|
|
6
|
-
"h-
|
|
6
|
+
"h-8 w-full px-3 rounded-md border border-input bg-background text-sm outline-none transition-shadow placeholder:text-muted-foreground";
|
|
7
7
|
|
|
8
8
|
// ── Composite ─────────────────────────────────────────────────────────────────
|
|
9
9
|
|
|
@@ -22,19 +22,19 @@ type MenuItemItem = {
|
|
|
22
22
|
type: "item";
|
|
23
23
|
label: React.ReactNode;
|
|
24
24
|
shortcut?: string;
|
|
25
|
-
} & Omit<React.ComponentProps<typeof MenuItem>, "children">;
|
|
25
|
+
} & Omit<React.ComponentProps<typeof MenuItem>, "children" | "label">;
|
|
26
26
|
|
|
27
27
|
type MenuItemCheckbox = {
|
|
28
28
|
type: "checkbox";
|
|
29
29
|
label: React.ReactNode;
|
|
30
30
|
shortcut?: string;
|
|
31
|
-
} & Omit<React.ComponentProps<typeof MenuCheckboxItem>, "children">;
|
|
31
|
+
} & Omit<React.ComponentProps<typeof MenuCheckboxItem>, "children" | "label">;
|
|
32
32
|
|
|
33
33
|
type MenuItemRadio = {
|
|
34
34
|
type: "radio";
|
|
35
35
|
label: React.ReactNode;
|
|
36
36
|
shortcut?: string;
|
|
37
|
-
} & Omit<React.ComponentProps<typeof MenuRadioItem>, "children">;
|
|
37
|
+
} & Omit<React.ComponentProps<typeof MenuRadioItem>, "children" | "label">;
|
|
38
38
|
|
|
39
39
|
type MenuItemRadioGroup = {
|
|
40
40
|
type: "radio-group";
|
|
@@ -62,7 +62,7 @@ type MenuItemSubmenu = {
|
|
|
62
62
|
type: "submenu";
|
|
63
63
|
label: React.ReactNode;
|
|
64
64
|
items: MenuItemType[];
|
|
65
|
-
} & Omit<React.ComponentProps<typeof MenuSubTrigger>, "children">;
|
|
65
|
+
} & Omit<React.ComponentProps<typeof MenuSubTrigger>, "children" | "label">;
|
|
66
66
|
|
|
67
67
|
export type MenuItemType =
|
|
68
68
|
| MenuItemItem
|
|
@@ -32,7 +32,7 @@ export function NumberInputGroup({
|
|
|
32
32
|
return (
|
|
33
33
|
<NumberFieldPrimitive.Group
|
|
34
34
|
className={cn(
|
|
35
|
-
"flex h-
|
|
35
|
+
"flex h-8 w-full items-center overflow-hidden rounded-md bg-background text-sm transition-shadow",
|
|
36
36
|
"outline outline-1 outline-input [outline-offset:-1px]",
|
|
37
37
|
"focus-within:outline-ring",
|
|
38
38
|
"aria-invalid:outline-error focus-within:aria-invalid:ring-error/20",
|
|
@@ -55,7 +55,7 @@ export function NumberInputInput({
|
|
|
55
55
|
return (
|
|
56
56
|
<NumberFieldPrimitive.Input
|
|
57
57
|
className={cn(
|
|
58
|
-
"min-w-0 flex-1 bg-transparent px-3
|
|
58
|
+
"min-w-0 flex-1 bg-transparent px-3 text-left tabular-nums outline-none",
|
|
59
59
|
"placeholder:text-muted-foreground",
|
|
60
60
|
className,
|
|
61
61
|
)}
|
|
@@ -73,7 +73,7 @@ export function NumberInputDecrement({
|
|
|
73
73
|
return (
|
|
74
74
|
<NumberFieldPrimitive.Decrement
|
|
75
75
|
className={cn(
|
|
76
|
-
"flex shrink-0 cursor-pointer items-center justify-center border-r border-input px-2
|
|
76
|
+
"flex shrink-0 cursor-pointer items-center justify-center border-r border-input px-2 text-muted-foreground transition-colors",
|
|
77
77
|
"hover:bg-accent hover:text-foreground",
|
|
78
78
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
79
79
|
className,
|
|
@@ -94,7 +94,7 @@ export function NumberInputIncrement({
|
|
|
94
94
|
return (
|
|
95
95
|
<NumberFieldPrimitive.Increment
|
|
96
96
|
className={cn(
|
|
97
|
-
"flex shrink-0 cursor-pointer items-center justify-center border-l border-input px-2
|
|
97
|
+
"flex shrink-0 cursor-pointer items-center justify-center border-l border-input px-2 text-muted-foreground transition-colors",
|
|
98
98
|
"hover:bg-accent hover:text-foreground",
|
|
99
99
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
100
100
|
className,
|
|
@@ -45,7 +45,7 @@ export function Password({
|
|
|
45
45
|
return (
|
|
46
46
|
<div
|
|
47
47
|
className={cn(
|
|
48
|
-
"relative inline-flex h-
|
|
48
|
+
"relative inline-flex h-8 w-full items-center text-sm",
|
|
49
49
|
"rounded-md border border-input bg-background transition-shadow",
|
|
50
50
|
"focus-within:border-ring",
|
|
51
51
|
"aria-invalid:border-error focus-within:aria-invalid:ring-error/20",
|
|
@@ -18,7 +18,6 @@ const meta: Meta<typeof Tag> = {
|
|
|
18
18
|
args: {
|
|
19
19
|
children: "Tag",
|
|
20
20
|
},
|
|
21
|
-
tags: ["beta"],
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
export default meta;
|
|
@@ -35,6 +34,8 @@ export const Variants: Story = {
|
|
|
35
34
|
<Tag>Default</Tag>
|
|
36
35
|
<Tag variant="secondary">Secondary</Tag>
|
|
37
36
|
<Tag variant="error">Error</Tag>
|
|
37
|
+
<Tag variant="success">Success</Tag>
|
|
38
|
+
<Tag variant="warning">Warning</Tag>
|
|
38
39
|
<Tag variant="outline">Outline</Tag>
|
|
39
40
|
<Tag variant="ghost">Ghost</Tag>
|
|
40
41
|
<Tag variant="link">Link</Tag>
|
|
@@ -43,12 +44,11 @@ export const Variants: Story = {
|
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
*
|
|
47
|
-
* to adjust the lateral padding automatically.
|
|
47
|
+
* Compose icons directly as children — JSX order determines position.
|
|
48
48
|
*
|
|
49
49
|
* ```tsx
|
|
50
50
|
* <Tag>
|
|
51
|
-
* <BadgeCheck
|
|
51
|
+
* <BadgeCheck />
|
|
52
52
|
* Verified
|
|
53
53
|
* </Tag>
|
|
54
54
|
* ```
|
|
@@ -57,15 +57,15 @@ export const WithIcon: Story = {
|
|
|
57
57
|
render: () => (
|
|
58
58
|
<div className="flex flex-wrap items-center gap-2">
|
|
59
59
|
<Tag>
|
|
60
|
-
<BadgeCheck
|
|
60
|
+
<BadgeCheck />
|
|
61
61
|
Verified
|
|
62
62
|
</Tag>
|
|
63
63
|
<Tag variant="secondary">
|
|
64
64
|
8.5
|
|
65
|
-
<CheckIcon
|
|
65
|
+
<CheckIcon />
|
|
66
66
|
</Tag>
|
|
67
67
|
<Tag variant="error">
|
|
68
|
-
<X
|
|
68
|
+
<X />
|
|
69
69
|
Rejected
|
|
70
70
|
</Tag>
|
|
71
71
|
</div>
|
|
@@ -73,22 +73,18 @@ export const WithIcon: Story = {
|
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
76
|
+
* Drop a `Loader` as a child to indicate async state. Same composition
|
|
77
|
+
* rules as any other icon — JSX order determines position.
|
|
78
78
|
*/
|
|
79
79
|
export const WithSpinner: Story = {
|
|
80
80
|
render: () => (
|
|
81
81
|
<div className="flex flex-wrap items-center gap-2">
|
|
82
82
|
<Tag>
|
|
83
|
-
<Loader
|
|
84
|
-
data-icon="inline-start"
|
|
85
|
-
size="xs"
|
|
86
|
-
className="text-primary-foreground"
|
|
87
|
-
/>
|
|
83
|
+
<Loader size="xs" className="text-primary-foreground" />
|
|
88
84
|
Processing
|
|
89
85
|
</Tag>
|
|
90
86
|
<Tag variant="secondary">
|
|
91
|
-
<Loader
|
|
87
|
+
<Loader size="xs" variant="ghost" />
|
|
92
88
|
Loading
|
|
93
89
|
</Tag>
|
|
94
90
|
</div>
|
|
@@ -125,14 +121,13 @@ export const Link: Story = {
|
|
|
125
121
|
};
|
|
126
122
|
|
|
127
123
|
/**
|
|
128
|
-
* The `closable` and `onClose` props were removed in v2. Dismissal is now
|
|
129
|
-
* by composing a `<button>` child with
|
|
130
|
-
* padding automatically via the `has-data-[icon]` selector.
|
|
124
|
+
* The `closable` and `onClose` props were removed in v2. Dismissal is now
|
|
125
|
+
* achieved by composing a `<button>` child with the close icon.
|
|
131
126
|
*
|
|
132
127
|
* ```tsx
|
|
133
128
|
* <Tag>
|
|
134
129
|
* Closable tag
|
|
135
|
-
* <button type="button"
|
|
130
|
+
* <button type="button" onClick={onClose}>
|
|
136
131
|
* <X className="size-3" />
|
|
137
132
|
* </button>
|
|
138
133
|
* </Tag>
|
|
@@ -158,7 +153,6 @@ export const Closable: Story = {
|
|
|
158
153
|
{t.label}
|
|
159
154
|
<button
|
|
160
155
|
type="button"
|
|
161
|
-
data-icon="inline-end"
|
|
162
156
|
className="cursor-pointer"
|
|
163
157
|
onClick={() =>
|
|
164
158
|
setVisible((prev) => prev.filter((id) => id !== t.id))
|
|
@@ -190,16 +184,15 @@ export const Closable: Story = {
|
|
|
190
184
|
export const CustomColors: Story = {
|
|
191
185
|
render: () => (
|
|
192
186
|
<div className="flex flex-wrap items-center gap-2">
|
|
193
|
-
<Tag className="bg-green-50 text-green-700 dark:bg-green-800/40 dark:text-green-200">
|
|
194
|
-
<BadgeCheck data-icon="inline-start" />
|
|
195
|
-
Success
|
|
196
|
-
</Tag>
|
|
197
|
-
<Tag className="bg-amber-50 text-amber-700 dark:bg-amber-800/40 dark:text-amber-200">
|
|
198
|
-
Pending
|
|
199
|
-
</Tag>
|
|
200
187
|
<Tag className="bg-blue-50 text-blue-700 dark:bg-blue-800/40 dark:text-blue-200">
|
|
201
188
|
Info
|
|
202
189
|
</Tag>
|
|
190
|
+
<Tag className="bg-purple-50 text-purple-700 dark:bg-purple-800/40 dark:text-purple-200">
|
|
191
|
+
Beta
|
|
192
|
+
</Tag>
|
|
193
|
+
<Tag className="bg-fuchsia-50 text-fuchsia-700 dark:bg-fuchsia-800/40 dark:text-fuchsia-200">
|
|
194
|
+
New
|
|
195
|
+
</Tag>
|
|
203
196
|
</div>
|
|
204
197
|
),
|
|
205
198
|
};
|
|
@@ -4,7 +4,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|
|
4
4
|
import { cn } from "../../lib";
|
|
5
5
|
|
|
6
6
|
const tagVariants = cva(
|
|
7
|
-
"group/tag inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50
|
|
7
|
+
"group/tag inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-error aria-invalid:ring-error/20 dark:aria-invalid:ring-error/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
@@ -13,6 +13,10 @@ const tagVariants = cva(
|
|
|
13
13
|
"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
14
14
|
error:
|
|
15
15
|
"bg-error/10 text-error focus-visible:ring-error/20 dark:bg-error/20 dark:focus-visible:ring-error/40 [a]:hover:bg-error/20",
|
|
16
|
+
success:
|
|
17
|
+
"bg-success/10 text-success focus-visible:ring-success/20 dark:bg-success/20 dark:focus-visible:ring-success/40 [a]:hover:bg-success/20",
|
|
18
|
+
warning:
|
|
19
|
+
"bg-warning/10 text-warning focus-visible:ring-warning/20 dark:bg-warning/20 dark:focus-visible:ring-warning/40 [a]:hover:bg-warning/20",
|
|
16
20
|
outline:
|
|
17
21
|
"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
|
18
22
|
ghost:
|