@mzc-fe/design-system 0.0.1 → 0.0.2-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/accordion.d.ts +7 -0
- package/dist/components/alert-dialog.d.ts +14 -0
- package/dist/components/alert.d.ts +9 -0
- package/dist/components/aspect-ratio.d.ts +3 -0
- package/dist/components/avatar.d.ts +6 -0
- package/dist/components/badge.d.ts +9 -0
- package/dist/components/breadcrumb.d.ts +11 -0
- package/dist/components/button-group.d.ts +11 -0
- package/dist/components/button.d.ts +10 -0
- package/dist/components/calendar.d.ts +8 -0
- package/dist/components/card.d.ts +9 -0
- package/dist/components/carousel.d.ts +19 -0
- package/dist/components/chart.d.ts +40 -0
- package/dist/components/checkbox.d.ts +4 -0
- package/dist/components/collapsible.d.ts +5 -0
- package/dist/components/command.d.ts +18 -0
- package/dist/components/context-menu.d.ts +25 -0
- package/dist/components/dialog.d.ts +15 -0
- package/dist/components/drawer.d.ts +13 -0
- package/dist/components/dropdown-menu.d.ts +25 -0
- package/dist/components/empty.d.ts +11 -0
- package/dist/components/field.d.ts +24 -0
- package/dist/components/form.d.ts +24 -0
- package/dist/components/hover-card.d.ts +6 -0
- package/dist/components/input-group.d.ts +16 -0
- package/dist/components/input-otp.d.ts +11 -0
- package/dist/components/input.d.ts +3 -0
- package/dist/components/item.d.ts +23 -0
- package/dist/components/kbd.d.ts +3 -0
- package/dist/components/label.d.ts +4 -0
- package/dist/components/menubar.d.ts +26 -0
- package/dist/components/navigation-menu.d.ts +14 -0
- package/dist/components/pagination.d.ts +13 -0
- package/dist/components/popover.d.ts +7 -0
- package/dist/components/progress.d.ts +4 -0
- package/dist/components/radio-group.d.ts +5 -0
- package/dist/components/resizable.d.ts +8 -0
- package/dist/components/scroll-area.d.ts +5 -0
- package/dist/components/select.d.ts +15 -0
- package/dist/components/separator.d.ts +4 -0
- package/dist/components/sheet.d.ts +13 -0
- package/dist/components/sidebar.d.ts +69 -0
- package/dist/components/skeleton.d.ts +2 -0
- package/dist/components/slider.d.ts +4 -0
- package/dist/components/sonner.d.ts +3 -0
- package/dist/components/spinner.d.ts +2 -0
- package/dist/components/switch.d.ts +4 -0
- package/dist/components/table.d.ts +10 -0
- package/dist/components/tabs.d.ts +7 -0
- package/dist/components/textarea.d.ts +3 -0
- package/dist/components/toggle-group.d.ts +9 -0
- package/dist/components/toggle.d.ts +9 -0
- package/dist/components/tooltip.d.ts +7 -0
- package/dist/design-system.css +1 -0
- package/dist/design-system.es.js +30200 -0
- package/dist/design-system.umd.js +260 -0
- package/dist/foundations/ThemeProvider.d.ts +13 -0
- package/dist/hooks/use-mobile.d.ts +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/lib/utils.d.ts +2 -0
- package/package.json +14 -1
- package/.husky/pre-push +0 -21
- package/.storybook/main.ts +0 -11
- package/.storybook/preview.tsx +0 -30
- package/.vscode/settings.json +0 -12
- package/.vscode/tailwind.json +0 -105
- package/bitbucket-pipelines.yml +0 -50
- package/components.json +0 -21
- package/eslint.config.js +0 -38
- package/src/components/accordion.stories.tsx +0 -258
- package/src/components/accordion.test.tsx +0 -390
- package/src/components/accordion.tsx +0 -64
- package/src/components/alert-dialog.stories.tsx +0 -213
- package/src/components/alert-dialog.test.tsx +0 -80
- package/src/components/alert-dialog.tsx +0 -155
- package/src/components/alert.stories.tsx +0 -84
- package/src/components/alert.test.tsx +0 -35
- package/src/components/alert.tsx +0 -66
- package/src/components/aspect-ratio.stories.tsx +0 -97
- package/src/components/aspect-ratio.test.tsx +0 -47
- package/src/components/aspect-ratio.tsx +0 -11
- package/src/components/avatar.stories.tsx +0 -76
- package/src/components/avatar.test.tsx +0 -50
- package/src/components/avatar.tsx +0 -51
- package/src/components/badge.stories.tsx +0 -64
- package/src/components/badge.test.tsx +0 -34
- package/src/components/badge.tsx +0 -46
- package/src/components/breadcrumb.stories.tsx +0 -86
- package/src/components/breadcrumb.test.tsx +0 -74
- package/src/components/breadcrumb.tsx +0 -109
- package/src/components/button-group.stories.tsx +0 -62
- package/src/components/button-group.tsx +0 -83
- package/src/components/button.stories.tsx +0 -118
- package/src/components/button.test.tsx +0 -64
- package/src/components/button.tsx +0 -62
- package/src/components/calendar.stories.tsx +0 -81
- package/src/components/calendar.tsx +0 -220
- package/src/components/card.stories.tsx +0 -110
- package/src/components/card.test.tsx +0 -56
- package/src/components/card.tsx +0 -92
- package/src/components/carousel.stories.tsx +0 -90
- package/src/components/carousel.tsx +0 -239
- package/src/components/chart.tsx +0 -357
- package/src/components/checkbox.stories.tsx +0 -108
- package/src/components/checkbox.test.tsx +0 -67
- package/src/components/checkbox.tsx +0 -32
- package/src/components/collapsible.stories.tsx +0 -106
- package/src/components/collapsible.test.tsx +0 -92
- package/src/components/collapsible.tsx +0 -31
- package/src/components/command.stories.tsx +0 -90
- package/src/components/command.tsx +0 -182
- package/src/components/context-menu.stories.tsx +0 -63
- package/src/components/context-menu.tsx +0 -252
- package/src/components/dialog.stories.tsx +0 -128
- package/src/components/dialog.tsx +0 -141
- package/src/components/drawer.stories.tsx +0 -104
- package/src/components/drawer.tsx +0 -135
- package/src/components/dropdown-menu.stories.tsx +0 -97
- package/src/components/dropdown-menu.tsx +0 -255
- package/src/components/empty.stories.tsx +0 -90
- package/src/components/empty.test.tsx +0 -55
- package/src/components/empty.tsx +0 -104
- package/src/components/field.tsx +0 -246
- package/src/components/form.tsx +0 -168
- package/src/components/hover-card.stories.tsx +0 -66
- package/src/components/hover-card.tsx +0 -44
- package/src/components/input-group.stories.tsx +0 -57
- package/src/components/input-group.test.tsx +0 -40
- package/src/components/input-group.tsx +0 -170
- package/src/components/input-otp.stories.tsx +0 -94
- package/src/components/input-otp.test.tsx +0 -60
- package/src/components/input-otp.tsx +0 -75
- package/src/components/input.stories.tsx +0 -94
- package/src/components/input.test.tsx +0 -53
- package/src/components/input.tsx +0 -21
- package/src/components/item.tsx +0 -193
- package/src/components/kbd.stories.tsx +0 -100
- package/src/components/kbd.test.tsx +0 -28
- package/src/components/kbd.tsx +0 -28
- package/src/components/label.stories.tsx +0 -48
- package/src/components/label.test.tsx +0 -28
- package/src/components/label.tsx +0 -24
- package/src/components/menubar.tsx +0 -274
- package/src/components/navigation-menu.tsx +0 -168
- package/src/components/pagination.stories.tsx +0 -107
- package/src/components/pagination.tsx +0 -127
- package/src/components/popover.stories.tsx +0 -102
- package/src/components/popover.tsx +0 -48
- package/src/components/progress.stories.tsx +0 -76
- package/src/components/progress.test.tsx +0 -36
- package/src/components/progress.tsx +0 -29
- package/src/components/radio-group.stories.tsx +0 -73
- package/src/components/radio-group.test.tsx +0 -74
- package/src/components/radio-group.tsx +0 -45
- package/src/components/resizable.stories.tsx +0 -120
- package/src/components/resizable.tsx +0 -54
- package/src/components/scroll-area.stories.tsx +0 -64
- package/src/components/scroll-area.test.tsx +0 -46
- package/src/components/scroll-area.tsx +0 -58
- package/src/components/select.stories.tsx +0 -111
- package/src/components/select.test.tsx +0 -90
- package/src/components/select.tsx +0 -188
- package/src/components/separator.stories.tsx +0 -76
- package/src/components/separator.test.tsx +0 -24
- package/src/components/separator.tsx +0 -28
- package/src/components/sheet.stories.tsx +0 -122
- package/src/components/sheet.tsx +0 -137
- package/src/components/sidebar.tsx +0 -726
- package/src/components/skeleton.stories.tsx +0 -53
- package/src/components/skeleton.test.tsx +0 -24
- package/src/components/skeleton.tsx +0 -13
- package/src/components/slider.stories.tsx +0 -97
- package/src/components/slider.test.tsx +0 -49
- package/src/components/slider.tsx +0 -63
- package/src/components/sonner.stories.tsx +0 -96
- package/src/components/sonner.tsx +0 -38
- package/src/components/spinner.stories.tsx +0 -54
- package/src/components/spinner.test.tsx +0 -30
- package/src/components/spinner.tsx +0 -16
- package/src/components/switch.stories.tsx +0 -108
- package/src/components/switch.test.tsx +0 -62
- package/src/components/switch.tsx +0 -31
- package/src/components/table.stories.tsx +0 -139
- package/src/components/table.test.tsx +0 -85
- package/src/components/table.tsx +0 -114
- package/src/components/tabs.stories.tsx +0 -99
- package/src/components/tabs.test.tsx +0 -64
- package/src/components/tabs.tsx +0 -66
- package/src/components/textarea.stories.tsx +0 -89
- package/src/components/textarea.test.tsx +0 -53
- package/src/components/textarea.tsx +0 -18
- package/src/components/toggle-group.stories.tsx +0 -108
- package/src/components/toggle-group.test.tsx +0 -66
- package/src/components/toggle-group.tsx +0 -81
- package/src/components/toggle.stories.tsx +0 -98
- package/src/components/toggle.test.tsx +0 -42
- package/src/components/toggle.tsx +0 -45
- package/src/components/tooltip.stories.tsx +0 -111
- package/src/components/tooltip.tsx +0 -61
- package/src/foundations/README.md +0 -141
- package/src/foundations/ThemeProvider.tsx +0 -77
- package/src/foundations/color.css +0 -232
- package/src/foundations/color.stories.tsx +0 -719
- package/src/foundations/palette.css +0 -249
- package/src/foundations/spacing.css +0 -8
- package/src/foundations/typography.css +0 -143
- package/src/foundations/typography.stories.tsx +0 -17
- package/src/hooks/use-mobile.ts +0 -19
- package/src/index.css +0 -176
- package/src/index.ts +0 -336
- package/src/lib/utils.ts +0 -6
- package/src/test/setup.ts +0 -8
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.app.json +0 -33
- package/tsconfig.json +0 -13
- package/tsconfig.node.json +0 -25
- package/vite.config.ts +0 -30
- package/vitest.config.ts +0 -25
- /package/{public → dist}/vite.svg +0 -0
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Textarea } from "./textarea";
|
|
3
|
-
import { Label } from "./label";
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: "Components/Textarea",
|
|
7
|
-
component: Textarea,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: "padded",
|
|
10
|
-
},
|
|
11
|
-
tags: ["autodocs"],
|
|
12
|
-
argTypes: {
|
|
13
|
-
disabled: {
|
|
14
|
-
control: "boolean",
|
|
15
|
-
description: "Whether the textarea is disabled.",
|
|
16
|
-
},
|
|
17
|
-
placeholder: {
|
|
18
|
-
control: "text",
|
|
19
|
-
description: "Placeholder text.",
|
|
20
|
-
},
|
|
21
|
-
rows: {
|
|
22
|
-
control: "number",
|
|
23
|
-
description: "Number of visible text lines.",
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
} satisfies Meta<typeof Textarea>;
|
|
27
|
-
|
|
28
|
-
export default meta;
|
|
29
|
-
type Story = StoryObj<typeof meta>;
|
|
30
|
-
|
|
31
|
-
export const Default: Story = {
|
|
32
|
-
args: {
|
|
33
|
-
placeholder: "Type your message here...",
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const WithLabel: Story = {
|
|
38
|
-
render: () => (
|
|
39
|
-
<div className="space-y-2 w-[350px]">
|
|
40
|
-
<Label htmlFor="message">Message</Label>
|
|
41
|
-
<Textarea id="message" placeholder="Type your message here..." />
|
|
42
|
-
</div>
|
|
43
|
-
),
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const Sizes: Story = {
|
|
47
|
-
render: () => (
|
|
48
|
-
<div className="space-y-4 w-[350px]">
|
|
49
|
-
<div className="space-y-2">
|
|
50
|
-
<Label>Small (3 rows)</Label>
|
|
51
|
-
<Textarea rows={3} placeholder="Small textarea..." />
|
|
52
|
-
</div>
|
|
53
|
-
<div className="space-y-2">
|
|
54
|
-
<Label>Medium (5 rows)</Label>
|
|
55
|
-
<Textarea rows={5} placeholder="Medium textarea..." />
|
|
56
|
-
</div>
|
|
57
|
-
<div className="space-y-2">
|
|
58
|
-
<Label>Large (10 rows)</Label>
|
|
59
|
-
<Textarea rows={10} placeholder="Large textarea..." />
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
),
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const Disabled: Story = {
|
|
66
|
-
render: () => (
|
|
67
|
-
<div className="space-y-2 w-[350px]">
|
|
68
|
-
<Label>Disabled</Label>
|
|
69
|
-
<Textarea disabled placeholder="This textarea is disabled" />
|
|
70
|
-
</div>
|
|
71
|
-
),
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export const WithError: Story = {
|
|
75
|
-
render: () => (
|
|
76
|
-
<div className="space-y-2 w-[350px]">
|
|
77
|
-
<Label htmlFor="error">Message</Label>
|
|
78
|
-
<Textarea
|
|
79
|
-
id="error"
|
|
80
|
-
placeholder="Type your message here..."
|
|
81
|
-
aria-invalid="true"
|
|
82
|
-
/>
|
|
83
|
-
<p className="text-sm text-destructive">
|
|
84
|
-
Message must be at least 10 characters.
|
|
85
|
-
</p>
|
|
86
|
-
</div>
|
|
87
|
-
),
|
|
88
|
-
};
|
|
89
|
-
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import userEvent from "@testing-library/user-event";
|
|
4
|
-
import { Textarea } from "./textarea";
|
|
5
|
-
|
|
6
|
-
describe("Textarea", () => {
|
|
7
|
-
it("should render textarea element", () => {
|
|
8
|
-
const { container } = render(<Textarea />);
|
|
9
|
-
const textarea = container.querySelector('[data-slot="textarea"]');
|
|
10
|
-
expect(textarea).toBeInTheDocument();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("should display placeholder text", () => {
|
|
14
|
-
const { getByPlaceholderText } = render(
|
|
15
|
-
<Textarea placeholder="Enter your message..." />
|
|
16
|
-
);
|
|
17
|
-
expect(getByPlaceholderText("Enter your message...")).toBeInTheDocument();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("should accept and display value", () => {
|
|
21
|
-
const { container } = render(<Textarea value="test value" readOnly />);
|
|
22
|
-
const textarea = container.querySelector('[data-slot="textarea"]') as HTMLTextAreaElement;
|
|
23
|
-
expect(textarea.value).toBe("test value");
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should be disabled when disabled prop is true", () => {
|
|
27
|
-
const { container } = render(<Textarea disabled />);
|
|
28
|
-
const textarea = container.querySelector('[data-slot="textarea"]') as HTMLTextAreaElement;
|
|
29
|
-
expect(textarea).toBeDisabled();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("should call onChange handler when value changes", async () => {
|
|
33
|
-
const user = userEvent.setup();
|
|
34
|
-
const handleChange = vi.fn();
|
|
35
|
-
const { container } = render(<Textarea onChange={handleChange} />);
|
|
36
|
-
const textarea = container.querySelector('[data-slot="textarea"]') as HTMLTextAreaElement;
|
|
37
|
-
await user.type(textarea, "test");
|
|
38
|
-
expect(handleChange).toHaveBeenCalled();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("should apply aria-invalid attribute when invalid", () => {
|
|
42
|
-
const { container } = render(<Textarea aria-invalid="true" />);
|
|
43
|
-
const textarea = container.querySelector('[data-slot="textarea"]');
|
|
44
|
-
expect(textarea).toHaveAttribute("aria-invalid", "true");
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("should support rows attribute", () => {
|
|
48
|
-
const { container } = render(<Textarea rows={5} />);
|
|
49
|
-
const textarea = container.querySelector('[data-slot="textarea"]') as HTMLTextAreaElement;
|
|
50
|
-
expect(textarea.rows).toBe(5);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
|
|
3
|
-
import { cn } from "@/lib/utils"
|
|
4
|
-
|
|
5
|
-
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|
6
|
-
return (
|
|
7
|
-
<textarea
|
|
8
|
-
data-slot="textarea"
|
|
9
|
-
className={cn(
|
|
10
|
-
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
11
|
-
className
|
|
12
|
-
)}
|
|
13
|
-
{...props}
|
|
14
|
-
/>
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export { Textarea }
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { ToggleGroup, ToggleGroupItem } from "./toggle-group";
|
|
3
|
-
import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react";
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: "Components/ToggleGroup",
|
|
7
|
-
component: ToggleGroup,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: "padded",
|
|
10
|
-
},
|
|
11
|
-
tags: ["autodocs"],
|
|
12
|
-
argTypes: {
|
|
13
|
-
type: {
|
|
14
|
-
control: "select",
|
|
15
|
-
options: ["single", "multiple"],
|
|
16
|
-
description: "The type of toggle group.",
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
} satisfies Meta<typeof ToggleGroup>;
|
|
20
|
-
|
|
21
|
-
export default meta;
|
|
22
|
-
type Story = StoryObj<typeof meta>;
|
|
23
|
-
|
|
24
|
-
export const Default: Story = {
|
|
25
|
-
args: {
|
|
26
|
-
type: "single",
|
|
27
|
-
},
|
|
28
|
-
render: () => (
|
|
29
|
-
<ToggleGroup type="single">
|
|
30
|
-
<ToggleGroupItem value="bold" aria-label="Toggle bold">
|
|
31
|
-
<BoldIcon />
|
|
32
|
-
</ToggleGroupItem>
|
|
33
|
-
<ToggleGroupItem value="italic" aria-label="Toggle italic">
|
|
34
|
-
<ItalicIcon />
|
|
35
|
-
</ToggleGroupItem>
|
|
36
|
-
<ToggleGroupItem value="underline" aria-label="Toggle underline">
|
|
37
|
-
<UnderlineIcon />
|
|
38
|
-
</ToggleGroupItem>
|
|
39
|
-
</ToggleGroup>
|
|
40
|
-
),
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const Multiple: Story = {
|
|
44
|
-
args: {
|
|
45
|
-
type: "multiple",
|
|
46
|
-
},
|
|
47
|
-
render: () => (
|
|
48
|
-
<ToggleGroup type="multiple">
|
|
49
|
-
<ToggleGroupItem value="bold" aria-label="Toggle bold">
|
|
50
|
-
<BoldIcon />
|
|
51
|
-
</ToggleGroupItem>
|
|
52
|
-
<ToggleGroupItem value="italic" aria-label="Toggle italic">
|
|
53
|
-
<ItalicIcon />
|
|
54
|
-
</ToggleGroupItem>
|
|
55
|
-
<ToggleGroupItem value="underline" aria-label="Toggle underline">
|
|
56
|
-
<UnderlineIcon />
|
|
57
|
-
</ToggleGroupItem>
|
|
58
|
-
</ToggleGroup>
|
|
59
|
-
),
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export const WithText: Story = {
|
|
63
|
-
args: {
|
|
64
|
-
type: "single",
|
|
65
|
-
defaultValue: "center",
|
|
66
|
-
},
|
|
67
|
-
render: () => (
|
|
68
|
-
<ToggleGroup type="single" defaultValue="center">
|
|
69
|
-
<ToggleGroupItem value="left">Left</ToggleGroupItem>
|
|
70
|
-
<ToggleGroupItem value="center">Center</ToggleGroupItem>
|
|
71
|
-
<ToggleGroupItem value="right">Right</ToggleGroupItem>
|
|
72
|
-
</ToggleGroup>
|
|
73
|
-
),
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export const Variants: Story = {
|
|
77
|
-
args: {
|
|
78
|
-
type: "single",
|
|
79
|
-
},
|
|
80
|
-
render: () => (
|
|
81
|
-
<div className="flex flex-col gap-4">
|
|
82
|
-
<ToggleGroup type="single" variant="default">
|
|
83
|
-
<ToggleGroupItem value="1">Option 1</ToggleGroupItem>
|
|
84
|
-
<ToggleGroupItem value="2">Option 2</ToggleGroupItem>
|
|
85
|
-
<ToggleGroupItem value="3">Option 3</ToggleGroupItem>
|
|
86
|
-
</ToggleGroup>
|
|
87
|
-
<ToggleGroup type="single" variant="outline">
|
|
88
|
-
<ToggleGroupItem value="1">Option 1</ToggleGroupItem>
|
|
89
|
-
<ToggleGroupItem value="2">Option 2</ToggleGroupItem>
|
|
90
|
-
<ToggleGroupItem value="3">Option 3</ToggleGroupItem>
|
|
91
|
-
</ToggleGroup>
|
|
92
|
-
</div>
|
|
93
|
-
),
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export const Disabled: Story = {
|
|
97
|
-
args: {
|
|
98
|
-
type: "single",
|
|
99
|
-
disabled: true,
|
|
100
|
-
},
|
|
101
|
-
render: () => (
|
|
102
|
-
<ToggleGroup type="single" disabled>
|
|
103
|
-
<ToggleGroupItem value="1">Option 1</ToggleGroupItem>
|
|
104
|
-
<ToggleGroupItem value="2">Option 2</ToggleGroupItem>
|
|
105
|
-
<ToggleGroupItem value="3">Option 3</ToggleGroupItem>
|
|
106
|
-
</ToggleGroup>
|
|
107
|
-
),
|
|
108
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import userEvent from "@testing-library/user-event";
|
|
4
|
-
import { ToggleGroup, ToggleGroupItem } from "./toggle-group";
|
|
5
|
-
|
|
6
|
-
describe("ToggleGroup", () => {
|
|
7
|
-
it("should render toggle group", () => {
|
|
8
|
-
const { container } = render(
|
|
9
|
-
<ToggleGroup type="single">
|
|
10
|
-
<ToggleGroupItem value="item1">Item 1</ToggleGroupItem>
|
|
11
|
-
</ToggleGroup>
|
|
12
|
-
);
|
|
13
|
-
const group = container.querySelector('[data-slot="toggle-group"]');
|
|
14
|
-
expect(group).toBeInTheDocument();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("should render toggle group items", () => {
|
|
18
|
-
const { getByText } = render(
|
|
19
|
-
<ToggleGroup type="single">
|
|
20
|
-
<ToggleGroupItem value="item1">Item 1</ToggleGroupItem>
|
|
21
|
-
<ToggleGroupItem value="item2">Item 2</ToggleGroupItem>
|
|
22
|
-
</ToggleGroup>
|
|
23
|
-
);
|
|
24
|
-
expect(getByText("Item 1")).toBeInTheDocument();
|
|
25
|
-
expect(getByText("Item 2")).toBeInTheDocument();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("should call onValueChange when item is clicked in single mode", async () => {
|
|
29
|
-
const user = userEvent.setup();
|
|
30
|
-
const handleChange = vi.fn();
|
|
31
|
-
const { getByText } = render(
|
|
32
|
-
<ToggleGroup type="single" onValueChange={handleChange}>
|
|
33
|
-
<ToggleGroupItem value="item1">Item 1</ToggleGroupItem>
|
|
34
|
-
<ToggleGroupItem value="item2">Item 2</ToggleGroupItem>
|
|
35
|
-
</ToggleGroup>
|
|
36
|
-
);
|
|
37
|
-
await user.click(getByText("Item 2"));
|
|
38
|
-
expect(handleChange).toHaveBeenCalledWith("item2");
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("should support multiple selection", async () => {
|
|
42
|
-
const user = userEvent.setup();
|
|
43
|
-
const handleChange = vi.fn();
|
|
44
|
-
const { getByText } = render(
|
|
45
|
-
<ToggleGroup type="multiple" onValueChange={handleChange}>
|
|
46
|
-
<ToggleGroupItem value="item1">Item 1</ToggleGroupItem>
|
|
47
|
-
<ToggleGroupItem value="item2">Item 2</ToggleGroupItem>
|
|
48
|
-
</ToggleGroup>
|
|
49
|
-
);
|
|
50
|
-
await user.click(getByText("Item 1"));
|
|
51
|
-
await user.click(getByText("Item 2"));
|
|
52
|
-
expect(handleChange).toHaveBeenCalledTimes(2);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("should be disabled when disabled prop is true", () => {
|
|
56
|
-
const { container } = render(
|
|
57
|
-
<ToggleGroup type="single" disabled>
|
|
58
|
-
<ToggleGroupItem value="item1">Item 1</ToggleGroupItem>
|
|
59
|
-
</ToggleGroup>
|
|
60
|
-
);
|
|
61
|
-
const group = container.querySelector('[data-slot="toggle-group"]');
|
|
62
|
-
// Radix UI toggle group may use aria-disabled or data-disabled
|
|
63
|
-
expect(group).toBeInTheDocument();
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
|
|
3
|
-
import { type VariantProps } from "class-variance-authority";
|
|
4
|
-
|
|
5
|
-
import { cn } from "@/lib/utils";
|
|
6
|
-
import { toggleVariants } from "@/components/toggle";
|
|
7
|
-
|
|
8
|
-
const ToggleGroupContext = React.createContext<
|
|
9
|
-
VariantProps<typeof toggleVariants> & {
|
|
10
|
-
spacing?: number;
|
|
11
|
-
}
|
|
12
|
-
>({
|
|
13
|
-
size: "default",
|
|
14
|
-
variant: "default",
|
|
15
|
-
spacing: 0,
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
function ToggleGroup({
|
|
19
|
-
className,
|
|
20
|
-
variant,
|
|
21
|
-
size,
|
|
22
|
-
spacing = 0,
|
|
23
|
-
children,
|
|
24
|
-
...props
|
|
25
|
-
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
|
|
26
|
-
VariantProps<typeof toggleVariants> & {
|
|
27
|
-
spacing?: number;
|
|
28
|
-
}) {
|
|
29
|
-
return (
|
|
30
|
-
<ToggleGroupPrimitive.Root
|
|
31
|
-
data-slot="toggle-group"
|
|
32
|
-
data-variant={variant}
|
|
33
|
-
data-size={size}
|
|
34
|
-
data-spacing={spacing}
|
|
35
|
-
style={{ "--gap": spacing } as React.CSSProperties}
|
|
36
|
-
className={cn(
|
|
37
|
-
"group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",
|
|
38
|
-
className
|
|
39
|
-
)}
|
|
40
|
-
{...props}
|
|
41
|
-
>
|
|
42
|
-
<ToggleGroupContext.Provider value={{ variant, size, spacing }}>
|
|
43
|
-
{children}
|
|
44
|
-
</ToggleGroupContext.Provider>
|
|
45
|
-
</ToggleGroupPrimitive.Root>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function ToggleGroupItem({
|
|
50
|
-
className,
|
|
51
|
-
children,
|
|
52
|
-
variant,
|
|
53
|
-
size,
|
|
54
|
-
...props
|
|
55
|
-
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
|
|
56
|
-
VariantProps<typeof toggleVariants>) {
|
|
57
|
-
const context = React.useContext(ToggleGroupContext);
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<ToggleGroupPrimitive.Item
|
|
61
|
-
data-slot="toggle-group-item"
|
|
62
|
-
data-variant={context.variant || variant}
|
|
63
|
-
data-size={context.size || size}
|
|
64
|
-
data-spacing={context.spacing}
|
|
65
|
-
className={cn(
|
|
66
|
-
toggleVariants({
|
|
67
|
-
variant: context.variant || variant,
|
|
68
|
-
size: context.size || size,
|
|
69
|
-
}),
|
|
70
|
-
"w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
|
|
71
|
-
"data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l",
|
|
72
|
-
className
|
|
73
|
-
)}
|
|
74
|
-
{...props}
|
|
75
|
-
>
|
|
76
|
-
{children}
|
|
77
|
-
</ToggleGroupPrimitive.Item>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export { ToggleGroup, ToggleGroupItem };
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Toggle } from "./toggle";
|
|
3
|
-
import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react";
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: "Components/Toggle",
|
|
7
|
-
component: Toggle,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: "padded",
|
|
10
|
-
},
|
|
11
|
-
tags: ["autodocs"],
|
|
12
|
-
argTypes: {
|
|
13
|
-
variant: {
|
|
14
|
-
control: "select",
|
|
15
|
-
options: ["default", "outline"],
|
|
16
|
-
description: "The visual style variant of the toggle.",
|
|
17
|
-
},
|
|
18
|
-
size: {
|
|
19
|
-
control: "select",
|
|
20
|
-
options: ["default", "sm", "lg"],
|
|
21
|
-
description: "The size of the toggle.",
|
|
22
|
-
},
|
|
23
|
-
pressed: {
|
|
24
|
-
control: "boolean",
|
|
25
|
-
description: "Whether the toggle is pressed.",
|
|
26
|
-
},
|
|
27
|
-
disabled: {
|
|
28
|
-
control: "boolean",
|
|
29
|
-
description: "Whether the toggle is disabled.",
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
} satisfies Meta<typeof Toggle>;
|
|
33
|
-
|
|
34
|
-
export default meta;
|
|
35
|
-
type Story = StoryObj<typeof meta>;
|
|
36
|
-
|
|
37
|
-
export const Default: Story = {
|
|
38
|
-
args: {
|
|
39
|
-
children: "Toggle",
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const WithIcon: Story = {
|
|
44
|
-
render: () => (
|
|
45
|
-
<div className="flex gap-2">
|
|
46
|
-
<Toggle aria-label="Toggle bold">
|
|
47
|
-
<BoldIcon />
|
|
48
|
-
</Toggle>
|
|
49
|
-
<Toggle aria-label="Toggle italic">
|
|
50
|
-
<ItalicIcon />
|
|
51
|
-
</Toggle>
|
|
52
|
-
<Toggle aria-label="Toggle underline">
|
|
53
|
-
<UnderlineIcon />
|
|
54
|
-
</Toggle>
|
|
55
|
-
</div>
|
|
56
|
-
),
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export const Variants: Story = {
|
|
60
|
-
render: () => (
|
|
61
|
-
<div className="flex flex-col gap-4">
|
|
62
|
-
<div className="flex gap-2">
|
|
63
|
-
<Toggle variant="default">Default</Toggle>
|
|
64
|
-
<Toggle variant="outline">Outline</Toggle>
|
|
65
|
-
</div>
|
|
66
|
-
<div className="flex gap-2">
|
|
67
|
-
<Toggle variant="default" pressed>
|
|
68
|
-
Default Pressed
|
|
69
|
-
</Toggle>
|
|
70
|
-
<Toggle variant="outline" pressed>
|
|
71
|
-
Outline Pressed
|
|
72
|
-
</Toggle>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
),
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const Sizes: Story = {
|
|
79
|
-
render: () => (
|
|
80
|
-
<div className="flex items-center gap-4">
|
|
81
|
-
<Toggle size="sm">Small</Toggle>
|
|
82
|
-
<Toggle size="default">Default</Toggle>
|
|
83
|
-
<Toggle size="lg">Large</Toggle>
|
|
84
|
-
</div>
|
|
85
|
-
),
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export const Disabled: Story = {
|
|
89
|
-
render: () => (
|
|
90
|
-
<div className="flex gap-2">
|
|
91
|
-
<Toggle disabled>Disabled</Toggle>
|
|
92
|
-
<Toggle disabled pressed>
|
|
93
|
-
Disabled Pressed
|
|
94
|
-
</Toggle>
|
|
95
|
-
</div>
|
|
96
|
-
),
|
|
97
|
-
};
|
|
98
|
-
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import userEvent from "@testing-library/user-event";
|
|
4
|
-
import { Toggle } from "./toggle";
|
|
5
|
-
|
|
6
|
-
describe("Toggle", () => {
|
|
7
|
-
it("should render toggle", () => {
|
|
8
|
-
const { container } = render(<Toggle>Toggle</Toggle>);
|
|
9
|
-
const toggle = container.querySelector('[data-slot="toggle"]');
|
|
10
|
-
expect(toggle).toBeInTheDocument();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("should be pressed when pressed prop is true", () => {
|
|
14
|
-
const { container } = render(<Toggle pressed>Toggle</Toggle>);
|
|
15
|
-
const toggle = container.querySelector('[data-slot="toggle"]');
|
|
16
|
-
expect(toggle).toHaveAttribute("data-state", "on");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("should call onPressedChange when clicked", async () => {
|
|
20
|
-
const user = userEvent.setup();
|
|
21
|
-
const handleChange = vi.fn();
|
|
22
|
-
const { container } = render(
|
|
23
|
-
<Toggle onPressedChange={handleChange}>Toggle</Toggle>
|
|
24
|
-
);
|
|
25
|
-
const toggle = container.querySelector('[data-slot="toggle"]') as HTMLElement;
|
|
26
|
-
await user.click(toggle);
|
|
27
|
-
expect(handleChange).toHaveBeenCalled();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("should be disabled when disabled prop is true", () => {
|
|
31
|
-
const { container } = render(<Toggle disabled>Toggle</Toggle>);
|
|
32
|
-
const toggle = container.querySelector('[data-slot="toggle"]');
|
|
33
|
-
expect(toggle).toHaveAttribute("data-disabled");
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("should apply variant classes", () => {
|
|
37
|
-
const { container } = render(<Toggle variant="outline">Toggle</Toggle>);
|
|
38
|
-
const toggle = container.querySelector('[data-slot="toggle"]');
|
|
39
|
-
expect(toggle).toBeInTheDocument();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import * as TogglePrimitive from "@radix-ui/react-toggle"
|
|
3
|
-
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
-
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
|
|
7
|
-
const toggleVariants = cva(
|
|
8
|
-
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
|
|
9
|
-
{
|
|
10
|
-
variants: {
|
|
11
|
-
variant: {
|
|
12
|
-
default: "bg-transparent",
|
|
13
|
-
outline:
|
|
14
|
-
"border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
|
|
15
|
-
},
|
|
16
|
-
size: {
|
|
17
|
-
default: "h-9 px-2 min-w-9",
|
|
18
|
-
sm: "h-8 px-1.5 min-w-8",
|
|
19
|
-
lg: "h-10 px-2.5 min-w-10",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
defaultVariants: {
|
|
23
|
-
variant: "default",
|
|
24
|
-
size: "default",
|
|
25
|
-
},
|
|
26
|
-
}
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
function Toggle({
|
|
30
|
-
className,
|
|
31
|
-
variant,
|
|
32
|
-
size,
|
|
33
|
-
...props
|
|
34
|
-
}: React.ComponentProps<typeof TogglePrimitive.Root> &
|
|
35
|
-
VariantProps<typeof toggleVariants>) {
|
|
36
|
-
return (
|
|
37
|
-
<TogglePrimitive.Root
|
|
38
|
-
data-slot="toggle"
|
|
39
|
-
className={cn(toggleVariants({ variant, size, className }))}
|
|
40
|
-
{...props}
|
|
41
|
-
/>
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export { Toggle, toggleVariants }
|