@mzc-fe/design-system 0.0.1 → 0.0.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/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,50 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import { Avatar, AvatarImage, AvatarFallback } from "./avatar";
|
|
4
|
-
|
|
5
|
-
describe("Avatar", () => {
|
|
6
|
-
it("should render avatar", () => {
|
|
7
|
-
const { container } = render(
|
|
8
|
-
<Avatar>
|
|
9
|
-
<AvatarFallback>JD</AvatarFallback>
|
|
10
|
-
</Avatar>
|
|
11
|
-
);
|
|
12
|
-
const avatar = container.querySelector('[data-slot="avatar"]');
|
|
13
|
-
expect(avatar).toBeInTheDocument();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("should render avatar image when src is provided", () => {
|
|
17
|
-
const { container } = render(
|
|
18
|
-
<Avatar>
|
|
19
|
-
<AvatarImage src="http://placecats.com/100/100" alt="User" />
|
|
20
|
-
<AvatarFallback>JD</AvatarFallback>
|
|
21
|
-
</Avatar>
|
|
22
|
-
);
|
|
23
|
-
const avatar = container.querySelector('[data-slot="avatar"]');
|
|
24
|
-
expect(avatar).toBeInTheDocument();
|
|
25
|
-
// Radix UI Avatar may not render the image element immediately
|
|
26
|
-
// The image element will be rendered when the image loads
|
|
27
|
-
// We verify that the Avatar component structure is correct
|
|
28
|
-
// The image element may be null initially, but the avatar container exists
|
|
29
|
-
expect(avatar).toBeTruthy();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("should render fallback when image fails to load", () => {
|
|
33
|
-
const { getByText } = render(
|
|
34
|
-
<Avatar>
|
|
35
|
-
<AvatarImage src="invalid-url" alt="User" />
|
|
36
|
-
<AvatarFallback>JD</AvatarFallback>
|
|
37
|
-
</Avatar>
|
|
38
|
-
);
|
|
39
|
-
expect(getByText("JD")).toBeInTheDocument();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("should render fallback when no image is provided", () => {
|
|
43
|
-
const { getByText } = render(
|
|
44
|
-
<Avatar>
|
|
45
|
-
<AvatarFallback>AB</AvatarFallback>
|
|
46
|
-
</Avatar>
|
|
47
|
-
);
|
|
48
|
-
expect(getByText("AB")).toBeInTheDocument();
|
|
49
|
-
});
|
|
50
|
-
});
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
|
3
|
-
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
5
|
-
|
|
6
|
-
function Avatar({
|
|
7
|
-
className,
|
|
8
|
-
...props
|
|
9
|
-
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
|
|
10
|
-
return (
|
|
11
|
-
<AvatarPrimitive.Root
|
|
12
|
-
data-slot="avatar"
|
|
13
|
-
className={cn(
|
|
14
|
-
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
|
15
|
-
className
|
|
16
|
-
)}
|
|
17
|
-
{...props}
|
|
18
|
-
/>
|
|
19
|
-
)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function AvatarImage({
|
|
23
|
-
className,
|
|
24
|
-
...props
|
|
25
|
-
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
|
|
26
|
-
return (
|
|
27
|
-
<AvatarPrimitive.Image
|
|
28
|
-
data-slot="avatar-image"
|
|
29
|
-
className={cn("aspect-square size-full", className)}
|
|
30
|
-
{...props}
|
|
31
|
-
/>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function AvatarFallback({
|
|
36
|
-
className,
|
|
37
|
-
...props
|
|
38
|
-
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
|
|
39
|
-
return (
|
|
40
|
-
<AvatarPrimitive.Fallback
|
|
41
|
-
data-slot="avatar-fallback"
|
|
42
|
-
className={cn(
|
|
43
|
-
"bg-muted flex size-full items-center justify-center rounded-full",
|
|
44
|
-
className
|
|
45
|
-
)}
|
|
46
|
-
{...props}
|
|
47
|
-
/>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export { Avatar, AvatarImage, AvatarFallback }
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Badge } from "./badge";
|
|
3
|
-
|
|
4
|
-
const meta = {
|
|
5
|
-
title: "Components/Badge",
|
|
6
|
-
component: Badge,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "padded",
|
|
9
|
-
},
|
|
10
|
-
tags: ["autodocs"],
|
|
11
|
-
argTypes: {
|
|
12
|
-
variant: {
|
|
13
|
-
control: "select",
|
|
14
|
-
options: ["default", "secondary", "destructive", "outline"],
|
|
15
|
-
description: "The visual style variant of the badge.",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
} satisfies Meta<typeof Badge>;
|
|
19
|
-
|
|
20
|
-
export default meta;
|
|
21
|
-
type Story = StoryObj<typeof meta>;
|
|
22
|
-
|
|
23
|
-
export const Default: Story = {
|
|
24
|
-
args: {
|
|
25
|
-
children: "Badge",
|
|
26
|
-
variant: "default",
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const Variants: Story = {
|
|
31
|
-
render: () => (
|
|
32
|
-
<div className="flex flex-wrap gap-4">
|
|
33
|
-
<Badge variant="default">Default</Badge>
|
|
34
|
-
<Badge variant="secondary">Secondary</Badge>
|
|
35
|
-
<Badge variant="destructive">Destructive</Badge>
|
|
36
|
-
<Badge variant="outline">Outline</Badge>
|
|
37
|
-
</div>
|
|
38
|
-
),
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const WithNumbers: Story = {
|
|
42
|
-
render: () => (
|
|
43
|
-
<div className="flex flex-wrap gap-4">
|
|
44
|
-
<Badge>1</Badge>
|
|
45
|
-
<Badge variant="secondary">42</Badge>
|
|
46
|
-
<Badge variant="destructive">999+</Badge>
|
|
47
|
-
<Badge variant="outline">12</Badge>
|
|
48
|
-
</div>
|
|
49
|
-
),
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export const AsLink: Story = {
|
|
53
|
-
render: () => (
|
|
54
|
-
<div className="flex flex-wrap gap-4">
|
|
55
|
-
<Badge asChild>
|
|
56
|
-
<a href="#">Link Badge</a>
|
|
57
|
-
</Badge>
|
|
58
|
-
<Badge variant="secondary" asChild>
|
|
59
|
-
<a href="#">Secondary Link</a>
|
|
60
|
-
</Badge>
|
|
61
|
-
</div>
|
|
62
|
-
),
|
|
63
|
-
};
|
|
64
|
-
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import { Badge } from "./badge";
|
|
4
|
-
|
|
5
|
-
describe("Badge", () => {
|
|
6
|
-
it("should render badge with text", () => {
|
|
7
|
-
const { getByText } = render(<Badge>New</Badge>);
|
|
8
|
-
expect(getByText("New")).toBeInTheDocument();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("should apply variant classes", () => {
|
|
12
|
-
const { container } = render(<Badge variant="destructive">Error</Badge>);
|
|
13
|
-
const badge = container.querySelector('[data-slot="badge"]');
|
|
14
|
-
expect(badge).toBeInTheDocument();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("should render with default variant", () => {
|
|
18
|
-
const { container } = render(<Badge>Default</Badge>);
|
|
19
|
-
const badge = container.querySelector('[data-slot="badge"]');
|
|
20
|
-
expect(badge).toBeInTheDocument();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("should render as link when asChild is true", () => {
|
|
24
|
-
const { container } = render(
|
|
25
|
-
<Badge asChild>
|
|
26
|
-
<a href="/test">Link Badge</a>
|
|
27
|
-
</Badge>
|
|
28
|
-
);
|
|
29
|
-
const link = container.querySelector("a");
|
|
30
|
-
expect(link).toBeInTheDocument();
|
|
31
|
-
expect(link).toHaveTextContent("Link Badge");
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
|
package/src/components/badge.tsx
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import { Slot } from "@radix-ui/react-slot"
|
|
3
|
-
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
-
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
|
|
7
|
-
const badgeVariants = cva(
|
|
8
|
-
"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
|
9
|
-
{
|
|
10
|
-
variants: {
|
|
11
|
-
variant: {
|
|
12
|
-
default:
|
|
13
|
-
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
14
|
-
secondary:
|
|
15
|
-
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
16
|
-
destructive:
|
|
17
|
-
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
18
|
-
outline:
|
|
19
|
-
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
defaultVariants: {
|
|
23
|
-
variant: "default",
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
function Badge({
|
|
29
|
-
className,
|
|
30
|
-
variant,
|
|
31
|
-
asChild = false,
|
|
32
|
-
...props
|
|
33
|
-
}: React.ComponentProps<"span"> &
|
|
34
|
-
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
|
35
|
-
const Comp = asChild ? Slot : "span"
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<Comp
|
|
39
|
-
data-slot="badge"
|
|
40
|
-
className={cn(badgeVariants({ variant }), className)}
|
|
41
|
-
{...props}
|
|
42
|
-
/>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export { Badge, badgeVariants }
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import {
|
|
3
|
-
Breadcrumb,
|
|
4
|
-
BreadcrumbList,
|
|
5
|
-
BreadcrumbItem,
|
|
6
|
-
BreadcrumbLink,
|
|
7
|
-
BreadcrumbPage,
|
|
8
|
-
BreadcrumbSeparator,
|
|
9
|
-
} from "./breadcrumb";
|
|
10
|
-
|
|
11
|
-
const meta = {
|
|
12
|
-
title: "Components/Breadcrumb",
|
|
13
|
-
component: Breadcrumb,
|
|
14
|
-
parameters: {
|
|
15
|
-
layout: "padded",
|
|
16
|
-
},
|
|
17
|
-
tags: ["autodocs"],
|
|
18
|
-
} satisfies Meta<typeof Breadcrumb>;
|
|
19
|
-
|
|
20
|
-
export default meta;
|
|
21
|
-
type Story = StoryObj<typeof meta>;
|
|
22
|
-
|
|
23
|
-
export const Default: Story = {
|
|
24
|
-
render: () => (
|
|
25
|
-
<Breadcrumb>
|
|
26
|
-
<BreadcrumbList>
|
|
27
|
-
<BreadcrumbItem>
|
|
28
|
-
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
|
29
|
-
</BreadcrumbItem>
|
|
30
|
-
<BreadcrumbSeparator />
|
|
31
|
-
<BreadcrumbItem>
|
|
32
|
-
<BreadcrumbLink href="#">Components</BreadcrumbLink>
|
|
33
|
-
</BreadcrumbItem>
|
|
34
|
-
<BreadcrumbSeparator />
|
|
35
|
-
<BreadcrumbItem>
|
|
36
|
-
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
|
37
|
-
</BreadcrumbItem>
|
|
38
|
-
</BreadcrumbList>
|
|
39
|
-
</Breadcrumb>
|
|
40
|
-
),
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const LongPath: Story = {
|
|
44
|
-
render: () => (
|
|
45
|
-
<Breadcrumb>
|
|
46
|
-
<BreadcrumbList>
|
|
47
|
-
<BreadcrumbItem>
|
|
48
|
-
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
|
49
|
-
</BreadcrumbItem>
|
|
50
|
-
<BreadcrumbSeparator />
|
|
51
|
-
<BreadcrumbItem>
|
|
52
|
-
<BreadcrumbLink href="#">Products</BreadcrumbLink>
|
|
53
|
-
</BreadcrumbItem>
|
|
54
|
-
<BreadcrumbSeparator />
|
|
55
|
-
<BreadcrumbItem>
|
|
56
|
-
<BreadcrumbLink href="#">Electronics</BreadcrumbLink>
|
|
57
|
-
</BreadcrumbItem>
|
|
58
|
-
<BreadcrumbSeparator />
|
|
59
|
-
<BreadcrumbItem>
|
|
60
|
-
<BreadcrumbLink href="#">Computers</BreadcrumbLink>
|
|
61
|
-
</BreadcrumbItem>
|
|
62
|
-
<BreadcrumbSeparator />
|
|
63
|
-
<BreadcrumbItem>
|
|
64
|
-
<BreadcrumbPage>Laptops</BreadcrumbPage>
|
|
65
|
-
</BreadcrumbItem>
|
|
66
|
-
</BreadcrumbList>
|
|
67
|
-
</Breadcrumb>
|
|
68
|
-
),
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
export const Simple: Story = {
|
|
72
|
-
render: () => (
|
|
73
|
-
<Breadcrumb>
|
|
74
|
-
<BreadcrumbList>
|
|
75
|
-
<BreadcrumbItem>
|
|
76
|
-
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
|
77
|
-
</BreadcrumbItem>
|
|
78
|
-
<BreadcrumbSeparator />
|
|
79
|
-
<BreadcrumbItem>
|
|
80
|
-
<BreadcrumbPage>Current Page</BreadcrumbPage>
|
|
81
|
-
</BreadcrumbItem>
|
|
82
|
-
</BreadcrumbList>
|
|
83
|
-
</Breadcrumb>
|
|
84
|
-
),
|
|
85
|
-
};
|
|
86
|
-
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import {
|
|
4
|
-
Breadcrumb,
|
|
5
|
-
BreadcrumbList,
|
|
6
|
-
BreadcrumbItem,
|
|
7
|
-
BreadcrumbLink,
|
|
8
|
-
BreadcrumbPage,
|
|
9
|
-
BreadcrumbSeparator,
|
|
10
|
-
} from "./breadcrumb";
|
|
11
|
-
|
|
12
|
-
describe("Breadcrumb", () => {
|
|
13
|
-
it("should render breadcrumb", () => {
|
|
14
|
-
const { container } = render(
|
|
15
|
-
<Breadcrumb>
|
|
16
|
-
<BreadcrumbList>
|
|
17
|
-
<BreadcrumbItem>
|
|
18
|
-
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
|
19
|
-
</BreadcrumbItem>
|
|
20
|
-
</BreadcrumbList>
|
|
21
|
-
</Breadcrumb>
|
|
22
|
-
);
|
|
23
|
-
const breadcrumb = container.querySelector('[data-slot="breadcrumb"]');
|
|
24
|
-
expect(breadcrumb).toBeInTheDocument();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("should render breadcrumb list", () => {
|
|
28
|
-
const { container } = render(
|
|
29
|
-
<Breadcrumb>
|
|
30
|
-
<BreadcrumbList>
|
|
31
|
-
<BreadcrumbItem>
|
|
32
|
-
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
|
33
|
-
</BreadcrumbItem>
|
|
34
|
-
</BreadcrumbList>
|
|
35
|
-
</Breadcrumb>
|
|
36
|
-
);
|
|
37
|
-
const list = container.querySelector('[data-slot="breadcrumb-list"]');
|
|
38
|
-
expect(list).toBeInTheDocument();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("should render breadcrumb items", () => {
|
|
42
|
-
const { getByText } = render(
|
|
43
|
-
<Breadcrumb>
|
|
44
|
-
<BreadcrumbList>
|
|
45
|
-
<BreadcrumbItem>
|
|
46
|
-
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
|
47
|
-
</BreadcrumbItem>
|
|
48
|
-
<BreadcrumbSeparator />
|
|
49
|
-
<BreadcrumbItem>
|
|
50
|
-
<BreadcrumbPage>Current</BreadcrumbPage>
|
|
51
|
-
</BreadcrumbItem>
|
|
52
|
-
</BreadcrumbList>
|
|
53
|
-
</Breadcrumb>
|
|
54
|
-
);
|
|
55
|
-
expect(getByText("Home")).toBeInTheDocument();
|
|
56
|
-
expect(getByText("Current")).toBeInTheDocument();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should render breadcrumb separator", () => {
|
|
60
|
-
const { container } = render(
|
|
61
|
-
<Breadcrumb>
|
|
62
|
-
<BreadcrumbList>
|
|
63
|
-
<BreadcrumbItem>
|
|
64
|
-
<BreadcrumbLink href="#">Home</BreadcrumbLink>
|
|
65
|
-
</BreadcrumbItem>
|
|
66
|
-
<BreadcrumbSeparator />
|
|
67
|
-
</BreadcrumbList>
|
|
68
|
-
</Breadcrumb>
|
|
69
|
-
);
|
|
70
|
-
const separator = container.querySelector('[data-slot="breadcrumb-separator"]');
|
|
71
|
-
expect(separator).toBeInTheDocument();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import { Slot } from "@radix-ui/react-slot"
|
|
3
|
-
import { ChevronRight, MoreHorizontal } from "lucide-react"
|
|
4
|
-
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
|
|
7
|
-
function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
|
|
8
|
-
return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
|
12
|
-
return (
|
|
13
|
-
<ol
|
|
14
|
-
data-slot="breadcrumb-list"
|
|
15
|
-
className={cn(
|
|
16
|
-
"text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
|
|
17
|
-
className
|
|
18
|
-
)}
|
|
19
|
-
{...props}
|
|
20
|
-
/>
|
|
21
|
-
)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
25
|
-
return (
|
|
26
|
-
<li
|
|
27
|
-
data-slot="breadcrumb-item"
|
|
28
|
-
className={cn("inline-flex items-center gap-1.5", className)}
|
|
29
|
-
{...props}
|
|
30
|
-
/>
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function BreadcrumbLink({
|
|
35
|
-
asChild,
|
|
36
|
-
className,
|
|
37
|
-
...props
|
|
38
|
-
}: React.ComponentProps<"a"> & {
|
|
39
|
-
asChild?: boolean
|
|
40
|
-
}) {
|
|
41
|
-
const Comp = asChild ? Slot : "a"
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<Comp
|
|
45
|
-
data-slot="breadcrumb-link"
|
|
46
|
-
className={cn("hover:text-foreground transition-colors", className)}
|
|
47
|
-
{...props}
|
|
48
|
-
/>
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
|
53
|
-
return (
|
|
54
|
-
<span
|
|
55
|
-
data-slot="breadcrumb-page"
|
|
56
|
-
role="link"
|
|
57
|
-
aria-disabled="true"
|
|
58
|
-
aria-current="page"
|
|
59
|
-
className={cn("text-foreground font-normal", className)}
|
|
60
|
-
{...props}
|
|
61
|
-
/>
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function BreadcrumbSeparator({
|
|
66
|
-
children,
|
|
67
|
-
className,
|
|
68
|
-
...props
|
|
69
|
-
}: React.ComponentProps<"li">) {
|
|
70
|
-
return (
|
|
71
|
-
<li
|
|
72
|
-
data-slot="breadcrumb-separator"
|
|
73
|
-
role="presentation"
|
|
74
|
-
aria-hidden="true"
|
|
75
|
-
className={cn("[&>svg]:size-3.5", className)}
|
|
76
|
-
{...props}
|
|
77
|
-
>
|
|
78
|
-
{children ?? <ChevronRight />}
|
|
79
|
-
</li>
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function BreadcrumbEllipsis({
|
|
84
|
-
className,
|
|
85
|
-
...props
|
|
86
|
-
}: React.ComponentProps<"span">) {
|
|
87
|
-
return (
|
|
88
|
-
<span
|
|
89
|
-
data-slot="breadcrumb-ellipsis"
|
|
90
|
-
role="presentation"
|
|
91
|
-
aria-hidden="true"
|
|
92
|
-
className={cn("flex size-9 items-center justify-center", className)}
|
|
93
|
-
{...props}
|
|
94
|
-
>
|
|
95
|
-
<MoreHorizontal className="size-4" />
|
|
96
|
-
<span className="sr-only">More</span>
|
|
97
|
-
</span>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export {
|
|
102
|
-
Breadcrumb,
|
|
103
|
-
BreadcrumbList,
|
|
104
|
-
BreadcrumbItem,
|
|
105
|
-
BreadcrumbLink,
|
|
106
|
-
BreadcrumbPage,
|
|
107
|
-
BreadcrumbSeparator,
|
|
108
|
-
BreadcrumbEllipsis,
|
|
109
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { ButtonGroup, ButtonGroupText } from "./button-group";
|
|
3
|
-
import { Button } from "./button";
|
|
4
|
-
import { Input } from "./input";
|
|
5
|
-
|
|
6
|
-
const meta = {
|
|
7
|
-
title: "Components/ButtonGroup",
|
|
8
|
-
component: ButtonGroup,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: "padded",
|
|
11
|
-
},
|
|
12
|
-
tags: ["autodocs"],
|
|
13
|
-
argTypes: {
|
|
14
|
-
orientation: {
|
|
15
|
-
control: "select",
|
|
16
|
-
options: ["horizontal", "vertical"],
|
|
17
|
-
description: "The orientation of the button group.",
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
} satisfies Meta<typeof ButtonGroup>;
|
|
21
|
-
|
|
22
|
-
export default meta;
|
|
23
|
-
type Story = StoryObj<typeof meta>;
|
|
24
|
-
|
|
25
|
-
export const Default: Story = {
|
|
26
|
-
render: () => (
|
|
27
|
-
<ButtonGroup>
|
|
28
|
-
<Button>One</Button>
|
|
29
|
-
<Button>Two</Button>
|
|
30
|
-
<Button>Three</Button>
|
|
31
|
-
</ButtonGroup>
|
|
32
|
-
),
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const WithInput: Story = {
|
|
36
|
-
render: () => (
|
|
37
|
-
<ButtonGroup>
|
|
38
|
-
<Input placeholder="Search..." className="w-[200px]" />
|
|
39
|
-
<Button>Search</Button>
|
|
40
|
-
</ButtonGroup>
|
|
41
|
-
),
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const Vertical: Story = {
|
|
45
|
-
render: () => (
|
|
46
|
-
<ButtonGroup orientation="vertical">
|
|
47
|
-
<Button>One</Button>
|
|
48
|
-
<Button>Two</Button>
|
|
49
|
-
<Button>Three</Button>
|
|
50
|
-
</ButtonGroup>
|
|
51
|
-
),
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export const WithText: Story = {
|
|
55
|
-
render: () => (
|
|
56
|
-
<ButtonGroup>
|
|
57
|
-
<ButtonGroupText>Label:</ButtonGroupText>
|
|
58
|
-
<Button>Action</Button>
|
|
59
|
-
</ButtonGroup>
|
|
60
|
-
),
|
|
61
|
-
};
|
|
62
|
-
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
|
|
4
|
-
import { cn } from "@/lib/utils";
|
|
5
|
-
import { Separator } from "@/components/separator";
|
|
6
|
-
|
|
7
|
-
const buttonGroupVariants = cva(
|
|
8
|
-
"flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
|
|
9
|
-
{
|
|
10
|
-
variants: {
|
|
11
|
-
orientation: {
|
|
12
|
-
horizontal:
|
|
13
|
-
"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
|
|
14
|
-
vertical:
|
|
15
|
-
"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
defaultVariants: {
|
|
19
|
-
orientation: "horizontal",
|
|
20
|
-
},
|
|
21
|
-
}
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
function ButtonGroup({
|
|
25
|
-
className,
|
|
26
|
-
orientation,
|
|
27
|
-
...props
|
|
28
|
-
}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
|
|
29
|
-
return (
|
|
30
|
-
<div
|
|
31
|
-
role="group"
|
|
32
|
-
data-slot="button-group"
|
|
33
|
-
data-orientation={orientation}
|
|
34
|
-
className={cn(buttonGroupVariants({ orientation }), className)}
|
|
35
|
-
{...props}
|
|
36
|
-
/>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function ButtonGroupText({
|
|
41
|
-
className,
|
|
42
|
-
asChild = false,
|
|
43
|
-
...props
|
|
44
|
-
}: React.ComponentProps<"div"> & {
|
|
45
|
-
asChild?: boolean;
|
|
46
|
-
}) {
|
|
47
|
-
const Comp = asChild ? Slot : "div";
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<Comp
|
|
51
|
-
className={cn(
|
|
52
|
-
"bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
|
53
|
-
className
|
|
54
|
-
)}
|
|
55
|
-
{...props}
|
|
56
|
-
/>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function ButtonGroupSeparator({
|
|
61
|
-
className,
|
|
62
|
-
orientation = "vertical",
|
|
63
|
-
...props
|
|
64
|
-
}: React.ComponentProps<typeof Separator>) {
|
|
65
|
-
return (
|
|
66
|
-
<Separator
|
|
67
|
-
data-slot="button-group-separator"
|
|
68
|
-
orientation={orientation}
|
|
69
|
-
className={cn(
|
|
70
|
-
"bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto",
|
|
71
|
-
className
|
|
72
|
-
)}
|
|
73
|
-
{...props}
|
|
74
|
-
/>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export {
|
|
79
|
-
ButtonGroup,
|
|
80
|
-
ButtonGroupSeparator,
|
|
81
|
-
ButtonGroupText,
|
|
82
|
-
buttonGroupVariants,
|
|
83
|
-
};
|