@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.
Files changed (219) hide show
  1. package/dist/components/accordion.d.ts +7 -0
  2. package/dist/components/alert-dialog.d.ts +14 -0
  3. package/dist/components/alert.d.ts +9 -0
  4. package/dist/components/aspect-ratio.d.ts +3 -0
  5. package/dist/components/avatar.d.ts +6 -0
  6. package/dist/components/badge.d.ts +9 -0
  7. package/dist/components/breadcrumb.d.ts +11 -0
  8. package/dist/components/button-group.d.ts +11 -0
  9. package/dist/components/button.d.ts +10 -0
  10. package/dist/components/calendar.d.ts +8 -0
  11. package/dist/components/card.d.ts +9 -0
  12. package/dist/components/carousel.d.ts +19 -0
  13. package/dist/components/chart.d.ts +40 -0
  14. package/dist/components/checkbox.d.ts +4 -0
  15. package/dist/components/collapsible.d.ts +5 -0
  16. package/dist/components/command.d.ts +18 -0
  17. package/dist/components/context-menu.d.ts +25 -0
  18. package/dist/components/dialog.d.ts +15 -0
  19. package/dist/components/drawer.d.ts +13 -0
  20. package/dist/components/dropdown-menu.d.ts +25 -0
  21. package/dist/components/empty.d.ts +11 -0
  22. package/dist/components/field.d.ts +24 -0
  23. package/dist/components/form.d.ts +24 -0
  24. package/dist/components/hover-card.d.ts +6 -0
  25. package/dist/components/input-group.d.ts +16 -0
  26. package/dist/components/input-otp.d.ts +11 -0
  27. package/dist/components/input.d.ts +3 -0
  28. package/dist/components/item.d.ts +23 -0
  29. package/dist/components/kbd.d.ts +3 -0
  30. package/dist/components/label.d.ts +4 -0
  31. package/dist/components/menubar.d.ts +26 -0
  32. package/dist/components/navigation-menu.d.ts +14 -0
  33. package/dist/components/pagination.d.ts +13 -0
  34. package/dist/components/popover.d.ts +7 -0
  35. package/dist/components/progress.d.ts +4 -0
  36. package/dist/components/radio-group.d.ts +5 -0
  37. package/dist/components/resizable.d.ts +8 -0
  38. package/dist/components/scroll-area.d.ts +5 -0
  39. package/dist/components/select.d.ts +15 -0
  40. package/dist/components/separator.d.ts +4 -0
  41. package/dist/components/sheet.d.ts +13 -0
  42. package/dist/components/sidebar.d.ts +69 -0
  43. package/dist/components/skeleton.d.ts +2 -0
  44. package/dist/components/slider.d.ts +4 -0
  45. package/dist/components/sonner.d.ts +3 -0
  46. package/dist/components/spinner.d.ts +2 -0
  47. package/dist/components/switch.d.ts +4 -0
  48. package/dist/components/table.d.ts +10 -0
  49. package/dist/components/tabs.d.ts +7 -0
  50. package/dist/components/textarea.d.ts +3 -0
  51. package/dist/components/toggle-group.d.ts +9 -0
  52. package/dist/components/toggle.d.ts +9 -0
  53. package/dist/components/tooltip.d.ts +7 -0
  54. package/dist/design-system.css +1 -0
  55. package/dist/design-system.es.js +30200 -0
  56. package/dist/design-system.umd.js +260 -0
  57. package/dist/foundations/ThemeProvider.d.ts +13 -0
  58. package/dist/hooks/use-mobile.d.ts +1 -0
  59. package/dist/index.d.ts +54 -0
  60. package/dist/lib/utils.d.ts +2 -0
  61. package/package.json +14 -1
  62. package/.husky/pre-push +0 -21
  63. package/.storybook/main.ts +0 -11
  64. package/.storybook/preview.tsx +0 -30
  65. package/.vscode/settings.json +0 -12
  66. package/.vscode/tailwind.json +0 -105
  67. package/bitbucket-pipelines.yml +0 -50
  68. package/components.json +0 -21
  69. package/eslint.config.js +0 -38
  70. package/src/components/accordion.stories.tsx +0 -258
  71. package/src/components/accordion.test.tsx +0 -390
  72. package/src/components/accordion.tsx +0 -64
  73. package/src/components/alert-dialog.stories.tsx +0 -213
  74. package/src/components/alert-dialog.test.tsx +0 -80
  75. package/src/components/alert-dialog.tsx +0 -155
  76. package/src/components/alert.stories.tsx +0 -84
  77. package/src/components/alert.test.tsx +0 -35
  78. package/src/components/alert.tsx +0 -66
  79. package/src/components/aspect-ratio.stories.tsx +0 -97
  80. package/src/components/aspect-ratio.test.tsx +0 -47
  81. package/src/components/aspect-ratio.tsx +0 -11
  82. package/src/components/avatar.stories.tsx +0 -76
  83. package/src/components/avatar.test.tsx +0 -50
  84. package/src/components/avatar.tsx +0 -51
  85. package/src/components/badge.stories.tsx +0 -64
  86. package/src/components/badge.test.tsx +0 -34
  87. package/src/components/badge.tsx +0 -46
  88. package/src/components/breadcrumb.stories.tsx +0 -86
  89. package/src/components/breadcrumb.test.tsx +0 -74
  90. package/src/components/breadcrumb.tsx +0 -109
  91. package/src/components/button-group.stories.tsx +0 -62
  92. package/src/components/button-group.tsx +0 -83
  93. package/src/components/button.stories.tsx +0 -118
  94. package/src/components/button.test.tsx +0 -64
  95. package/src/components/button.tsx +0 -62
  96. package/src/components/calendar.stories.tsx +0 -81
  97. package/src/components/calendar.tsx +0 -220
  98. package/src/components/card.stories.tsx +0 -110
  99. package/src/components/card.test.tsx +0 -56
  100. package/src/components/card.tsx +0 -92
  101. package/src/components/carousel.stories.tsx +0 -90
  102. package/src/components/carousel.tsx +0 -239
  103. package/src/components/chart.tsx +0 -357
  104. package/src/components/checkbox.stories.tsx +0 -108
  105. package/src/components/checkbox.test.tsx +0 -67
  106. package/src/components/checkbox.tsx +0 -32
  107. package/src/components/collapsible.stories.tsx +0 -106
  108. package/src/components/collapsible.test.tsx +0 -92
  109. package/src/components/collapsible.tsx +0 -31
  110. package/src/components/command.stories.tsx +0 -90
  111. package/src/components/command.tsx +0 -182
  112. package/src/components/context-menu.stories.tsx +0 -63
  113. package/src/components/context-menu.tsx +0 -252
  114. package/src/components/dialog.stories.tsx +0 -128
  115. package/src/components/dialog.tsx +0 -141
  116. package/src/components/drawer.stories.tsx +0 -104
  117. package/src/components/drawer.tsx +0 -135
  118. package/src/components/dropdown-menu.stories.tsx +0 -97
  119. package/src/components/dropdown-menu.tsx +0 -255
  120. package/src/components/empty.stories.tsx +0 -90
  121. package/src/components/empty.test.tsx +0 -55
  122. package/src/components/empty.tsx +0 -104
  123. package/src/components/field.tsx +0 -246
  124. package/src/components/form.tsx +0 -168
  125. package/src/components/hover-card.stories.tsx +0 -66
  126. package/src/components/hover-card.tsx +0 -44
  127. package/src/components/input-group.stories.tsx +0 -57
  128. package/src/components/input-group.test.tsx +0 -40
  129. package/src/components/input-group.tsx +0 -170
  130. package/src/components/input-otp.stories.tsx +0 -94
  131. package/src/components/input-otp.test.tsx +0 -60
  132. package/src/components/input-otp.tsx +0 -75
  133. package/src/components/input.stories.tsx +0 -94
  134. package/src/components/input.test.tsx +0 -53
  135. package/src/components/input.tsx +0 -21
  136. package/src/components/item.tsx +0 -193
  137. package/src/components/kbd.stories.tsx +0 -100
  138. package/src/components/kbd.test.tsx +0 -28
  139. package/src/components/kbd.tsx +0 -28
  140. package/src/components/label.stories.tsx +0 -48
  141. package/src/components/label.test.tsx +0 -28
  142. package/src/components/label.tsx +0 -24
  143. package/src/components/menubar.tsx +0 -274
  144. package/src/components/navigation-menu.tsx +0 -168
  145. package/src/components/pagination.stories.tsx +0 -107
  146. package/src/components/pagination.tsx +0 -127
  147. package/src/components/popover.stories.tsx +0 -102
  148. package/src/components/popover.tsx +0 -48
  149. package/src/components/progress.stories.tsx +0 -76
  150. package/src/components/progress.test.tsx +0 -36
  151. package/src/components/progress.tsx +0 -29
  152. package/src/components/radio-group.stories.tsx +0 -73
  153. package/src/components/radio-group.test.tsx +0 -74
  154. package/src/components/radio-group.tsx +0 -45
  155. package/src/components/resizable.stories.tsx +0 -120
  156. package/src/components/resizable.tsx +0 -54
  157. package/src/components/scroll-area.stories.tsx +0 -64
  158. package/src/components/scroll-area.test.tsx +0 -46
  159. package/src/components/scroll-area.tsx +0 -58
  160. package/src/components/select.stories.tsx +0 -111
  161. package/src/components/select.test.tsx +0 -90
  162. package/src/components/select.tsx +0 -188
  163. package/src/components/separator.stories.tsx +0 -76
  164. package/src/components/separator.test.tsx +0 -24
  165. package/src/components/separator.tsx +0 -28
  166. package/src/components/sheet.stories.tsx +0 -122
  167. package/src/components/sheet.tsx +0 -137
  168. package/src/components/sidebar.tsx +0 -726
  169. package/src/components/skeleton.stories.tsx +0 -53
  170. package/src/components/skeleton.test.tsx +0 -24
  171. package/src/components/skeleton.tsx +0 -13
  172. package/src/components/slider.stories.tsx +0 -97
  173. package/src/components/slider.test.tsx +0 -49
  174. package/src/components/slider.tsx +0 -63
  175. package/src/components/sonner.stories.tsx +0 -96
  176. package/src/components/sonner.tsx +0 -38
  177. package/src/components/spinner.stories.tsx +0 -54
  178. package/src/components/spinner.test.tsx +0 -30
  179. package/src/components/spinner.tsx +0 -16
  180. package/src/components/switch.stories.tsx +0 -108
  181. package/src/components/switch.test.tsx +0 -62
  182. package/src/components/switch.tsx +0 -31
  183. package/src/components/table.stories.tsx +0 -139
  184. package/src/components/table.test.tsx +0 -85
  185. package/src/components/table.tsx +0 -114
  186. package/src/components/tabs.stories.tsx +0 -99
  187. package/src/components/tabs.test.tsx +0 -64
  188. package/src/components/tabs.tsx +0 -66
  189. package/src/components/textarea.stories.tsx +0 -89
  190. package/src/components/textarea.test.tsx +0 -53
  191. package/src/components/textarea.tsx +0 -18
  192. package/src/components/toggle-group.stories.tsx +0 -108
  193. package/src/components/toggle-group.test.tsx +0 -66
  194. package/src/components/toggle-group.tsx +0 -81
  195. package/src/components/toggle.stories.tsx +0 -98
  196. package/src/components/toggle.test.tsx +0 -42
  197. package/src/components/toggle.tsx +0 -45
  198. package/src/components/tooltip.stories.tsx +0 -111
  199. package/src/components/tooltip.tsx +0 -61
  200. package/src/foundations/README.md +0 -141
  201. package/src/foundations/ThemeProvider.tsx +0 -77
  202. package/src/foundations/color.css +0 -232
  203. package/src/foundations/color.stories.tsx +0 -719
  204. package/src/foundations/palette.css +0 -249
  205. package/src/foundations/spacing.css +0 -8
  206. package/src/foundations/typography.css +0 -143
  207. package/src/foundations/typography.stories.tsx +0 -17
  208. package/src/hooks/use-mobile.ts +0 -19
  209. package/src/index.css +0 -176
  210. package/src/index.ts +0 -336
  211. package/src/lib/utils.ts +0 -6
  212. package/src/test/setup.ts +0 -8
  213. package/src/vite-env.d.ts +0 -1
  214. package/tsconfig.app.json +0 -33
  215. package/tsconfig.json +0 -13
  216. package/tsconfig.node.json +0 -25
  217. package/vite.config.ts +0 -30
  218. package/vitest.config.ts +0 -25
  219. /package/{public → dist}/vite.svg +0 -0
@@ -1,53 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { Skeleton } from "./skeleton";
3
-
4
- const meta = {
5
- title: "Components/Skeleton",
6
- component: Skeleton,
7
- parameters: {
8
- layout: "padded",
9
- },
10
- tags: ["autodocs"],
11
- } satisfies Meta<typeof Skeleton>;
12
-
13
- export default meta;
14
- type Story = StoryObj<typeof meta>;
15
-
16
- export const Default: Story = {
17
- render: () => <Skeleton className="h-4 w-[250px]" />,
18
- };
19
-
20
- export const Shapes: Story = {
21
- render: () => (
22
- <div className="space-y-4">
23
- <Skeleton className="h-4 w-[250px]" />
24
- <Skeleton className="h-4 w-[200px]" />
25
- <Skeleton className="h-4 w-[150px]" />
26
- </div>
27
- ),
28
- };
29
-
30
- export const CardSkeleton: Story = {
31
- render: () => (
32
- <div className="flex items-center space-x-4 w-[350px]">
33
- <Skeleton className="h-12 w-12 rounded-full" />
34
- <div className="space-y-2 flex-1">
35
- <Skeleton className="h-4 w-full" />
36
- <Skeleton className="h-4 w-3/4" />
37
- </div>
38
- </div>
39
- ),
40
- };
41
-
42
- export const ArticleSkeleton: Story = {
43
- render: () => (
44
- <div className="space-y-4 w-[400px]">
45
- <Skeleton className="h-8 w-3/4" />
46
- <Skeleton className="h-4 w-full" />
47
- <Skeleton className="h-4 w-full" />
48
- <Skeleton className="h-4 w-5/6" />
49
- <Skeleton className="h-[200px] w-full rounded-md" />
50
- </div>
51
- ),
52
- };
53
-
@@ -1,24 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { render } from "@testing-library/react";
3
- import { Skeleton } from "./skeleton";
4
-
5
- describe("Skeleton", () => {
6
- it("should render skeleton", () => {
7
- const { container } = render(<Skeleton />);
8
- const skeleton = container.querySelector('[data-slot="skeleton"]');
9
- expect(skeleton).toBeInTheDocument();
10
- });
11
-
12
- it("should apply custom className", () => {
13
- const { container } = render(<Skeleton className="w-20 h-20" />);
14
- const skeleton = container.querySelector('[data-slot="skeleton"]');
15
- expect(skeleton).toHaveClass("w-20", "h-20");
16
- });
17
-
18
- it("should have animate-pulse class", () => {
19
- const { container } = render(<Skeleton />);
20
- const skeleton = container.querySelector('[data-slot="skeleton"]');
21
- expect(skeleton).toHaveClass("animate-pulse");
22
- });
23
- });
24
-
@@ -1,13 +0,0 @@
1
- import { cn } from "@/lib/utils"
2
-
3
- function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
- return (
5
- <div
6
- data-slot="skeleton"
7
- className={cn("bg-accent animate-pulse rounded-md", className)}
8
- {...props}
9
- />
10
- )
11
- }
12
-
13
- export { Skeleton }
@@ -1,97 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { useState } from "react";
3
- import { Slider } from "./slider";
4
-
5
- const meta = {
6
- title: "Components/Slider",
7
- component: Slider,
8
- parameters: {
9
- layout: "padded",
10
- },
11
- tags: ["autodocs"],
12
- argTypes: {
13
- defaultValue: {
14
- control: "object",
15
- description: "The default value of the slider.",
16
- },
17
- min: {
18
- control: "number",
19
- description: "The minimum value.",
20
- },
21
- max: {
22
- control: "number",
23
- description: "The maximum value.",
24
- },
25
- step: {
26
- control: "number",
27
- description: "The step value.",
28
- },
29
- },
30
- } satisfies Meta<typeof Slider>;
31
-
32
- export default meta;
33
- type Story = StoryObj<typeof meta>;
34
-
35
- export const Default: Story = {
36
- args: {
37
- defaultValue: [50],
38
- max: 100,
39
- },
40
- };
41
-
42
- export const WithValue: Story = {
43
- render: () => {
44
- const [value, setValue] = useState([50]);
45
- return (
46
- <div className="space-y-4 w-[350px]">
47
- <Slider value={value} onValueChange={setValue} max={100} />
48
- <div className="text-sm text-muted-foreground">
49
- Value: {value[0]}
50
- </div>
51
- </div>
52
- );
53
- },
54
- };
55
-
56
- export const Range: Story = {
57
- render: () => {
58
- const [value, setValue] = useState([20, 80]);
59
- return (
60
- <div className="space-y-4 w-[350px]">
61
- <Slider value={value} onValueChange={setValue} max={100} />
62
- <div className="text-sm text-muted-foreground">
63
- Range: {value[0]} - {value[1]}
64
- </div>
65
- </div>
66
- );
67
- },
68
- };
69
-
70
- export const CustomRange: Story = {
71
- render: () => {
72
- const [value, setValue] = useState([25]);
73
- return (
74
- <div className="space-y-4 w-[350px]">
75
- <Slider
76
- value={value}
77
- onValueChange={setValue}
78
- min={0}
79
- max={1000}
80
- step={10}
81
- />
82
- <div className="text-sm text-muted-foreground">
83
- Value: {value[0]} (0-1000, step 10)
84
- </div>
85
- </div>
86
- );
87
- },
88
- };
89
-
90
- export const Disabled: Story = {
91
- render: () => (
92
- <div className="w-[350px]">
93
- <Slider defaultValue={[50]} max={100} disabled />
94
- </div>
95
- ),
96
- };
97
-
@@ -1,49 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
- import { render } from "@testing-library/react";
3
- import { Slider } from "./slider";
4
-
5
- describe("Slider", () => {
6
- it("should render slider", () => {
7
- const { container } = render(<Slider defaultValue={[50]} />);
8
- const slider = container.querySelector('[data-slot="slider"]');
9
- expect(slider).toBeInTheDocument();
10
- });
11
-
12
- it("should render slider track", () => {
13
- const { container } = render(<Slider defaultValue={[50]} />);
14
- const track = container.querySelector('[data-slot="slider-track"]');
15
- expect(track).toBeInTheDocument();
16
- });
17
-
18
- it("should render slider thumb", () => {
19
- const { container } = render(<Slider defaultValue={[50]} />);
20
- const thumb = container.querySelector('[data-slot="slider-thumb"]');
21
- expect(thumb).toBeInTheDocument();
22
- });
23
-
24
- it("should call onValueChange when value changes", async () => {
25
- const handleChange = vi.fn();
26
- const { container } = render(
27
- <Slider value={[50]} onValueChange={handleChange} />
28
- );
29
- const thumb = container.querySelector(
30
- '[data-slot="slider-thumb"]'
31
- ) as HTMLElement;
32
- // Note: 실제 슬라이더 드래그는 더 복잡한 상호작용이 필요합니다
33
- expect(thumb).toBeInTheDocument();
34
- });
35
-
36
- it("should support range values", () => {
37
- const { container } = render(<Slider value={[20, 80]} />);
38
- const thumbs = container.querySelectorAll('[data-slot="slider-thumb"]');
39
- expect(thumbs.length).toBe(2);
40
- });
41
-
42
- it("should respect min and max values", () => {
43
- const { container } = render(
44
- <Slider defaultValue={[25]} min={0} max={100} />
45
- );
46
- const slider = container.querySelector('[data-slot="slider"]');
47
- expect(slider).toBeInTheDocument();
48
- });
49
- });
@@ -1,63 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as SliderPrimitive from "@radix-ui/react-slider"
5
-
6
- import { cn } from "@/lib/utils"
7
-
8
- function Slider({
9
- className,
10
- defaultValue,
11
- value,
12
- min = 0,
13
- max = 100,
14
- ...props
15
- }: React.ComponentProps<typeof SliderPrimitive.Root>) {
16
- const _values = React.useMemo(
17
- () =>
18
- Array.isArray(value)
19
- ? value
20
- : Array.isArray(defaultValue)
21
- ? defaultValue
22
- : [min, max],
23
- [value, defaultValue, min, max]
24
- )
25
-
26
- return (
27
- <SliderPrimitive.Root
28
- data-slot="slider"
29
- defaultValue={defaultValue}
30
- value={value}
31
- min={min}
32
- max={max}
33
- className={cn(
34
- "relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
35
- className
36
- )}
37
- {...props}
38
- >
39
- <SliderPrimitive.Track
40
- data-slot="slider-track"
41
- className={cn(
42
- "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
43
- )}
44
- >
45
- <SliderPrimitive.Range
46
- data-slot="slider-range"
47
- className={cn(
48
- "bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
49
- )}
50
- />
51
- </SliderPrimitive.Track>
52
- {Array.from({ length: _values.length }, (_, index) => (
53
- <SliderPrimitive.Thumb
54
- data-slot="slider-thumb"
55
- key={index}
56
- className="border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
57
- />
58
- ))}
59
- </SliderPrimitive.Root>
60
- )
61
- }
62
-
63
- export { Slider }
@@ -1,96 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { Toaster } from "./sonner";
3
- import { Button } from "./button";
4
- import { toast } from "sonner";
5
-
6
- const meta = {
7
- title: "Components/Sonner",
8
- component: Toaster,
9
- parameters: {
10
- layout: "padded",
11
- },
12
- tags: ["autodocs"],
13
- } satisfies Meta<typeof Toaster>;
14
-
15
- export default meta;
16
- type Story = StoryObj<typeof meta>;
17
-
18
- export const Default: Story = {
19
- render: () => (
20
- <>
21
- <Toaster />
22
- <div className="flex flex-wrap gap-4">
23
- <Button
24
- onClick={() => toast("Event has been created", { description: "Monday, January 3rd at 6:00pm" })}
25
- >
26
- Show Toast
27
- </Button>
28
- <Button
29
- variant="outline"
30
- onClick={() => toast.success("Success!", { description: "Your changes have been saved." })}
31
- >
32
- Success
33
- </Button>
34
- <Button
35
- variant="destructive"
36
- onClick={() => toast.error("Error!", { description: "Something went wrong." })}
37
- >
38
- Error
39
- </Button>
40
- <Button
41
- variant="secondary"
42
- onClick={() => toast.info("Info", { description: "Here's some information." })}
43
- >
44
- Info
45
- </Button>
46
- <Button
47
- variant="outline"
48
- onClick={() => toast.warning("Warning", { description: "Please be careful." })}
49
- >
50
- Warning
51
- </Button>
52
- </div>
53
- </>
54
- ),
55
- };
56
-
57
- export const WithActions: Story = {
58
- render: () => (
59
- <>
60
- <Toaster />
61
- <div className="flex gap-4">
62
- <Button
63
- onClick={() =>
64
- toast("Event has been created", {
65
- description: "Monday, January 3rd at 6:00pm",
66
- action: {
67
- label: "Undo",
68
- onClick: () => console.log("Undo"),
69
- },
70
- })
71
- }
72
- >
73
- Toast with Action
74
- </Button>
75
- </div>
76
- </>
77
- ),
78
- };
79
-
80
- export const LongDuration: Story = {
81
- render: () => (
82
- <>
83
- <Toaster />
84
- <Button
85
- onClick={() =>
86
- toast("This toast will stay for 10 seconds", {
87
- duration: 10000,
88
- })
89
- }
90
- >
91
- Long Duration Toast
92
- </Button>
93
- </>
94
- ),
95
- };
96
-
@@ -1,38 +0,0 @@
1
- import {
2
- CircleCheckIcon,
3
- InfoIcon,
4
- Loader2Icon,
5
- OctagonXIcon,
6
- TriangleAlertIcon,
7
- } from "lucide-react";
8
- import { useTheme } from "next-themes";
9
- import { Toaster as Sonner, type ToasterProps } from "sonner";
10
-
11
- const Toaster = ({ ...props }: ToasterProps) => {
12
- const { theme = "system" } = useTheme();
13
-
14
- return (
15
- <Sonner
16
- theme={theme as ToasterProps["theme"]}
17
- className="toaster group"
18
- icons={{
19
- success: <CircleCheckIcon className="size-4" />,
20
- info: <InfoIcon className="size-4" />,
21
- warning: <TriangleAlertIcon className="size-4" />,
22
- error: <OctagonXIcon className="size-4" />,
23
- loading: <Loader2Icon className="size-4 animate-spin" />,
24
- }}
25
- style={
26
- {
27
- "--normal-bg": "var(--popover)",
28
- "--normal-text": "var(--popover-foreground)",
29
- "--normal-border": "var(--border)",
30
- "--border-radius": "var(--radius)",
31
- } as React.CSSProperties
32
- }
33
- {...props}
34
- />
35
- );
36
- };
37
-
38
- export { Toaster };
@@ -1,54 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { Spinner } from "./spinner";
3
-
4
- const meta = {
5
- title: "Components/Spinner",
6
- component: Spinner,
7
- parameters: {
8
- layout: "padded",
9
- },
10
- tags: ["autodocs"],
11
- } satisfies Meta<typeof Spinner>;
12
-
13
- export default meta;
14
- type Story = StoryObj<typeof meta>;
15
-
16
- export const Default: Story = {
17
- render: () => <Spinner />,
18
- };
19
-
20
- export const Sizes: Story = {
21
- render: () => (
22
- <div className="flex items-center gap-4">
23
- <Spinner className="size-4" />
24
- <Spinner className="size-6" />
25
- <Spinner className="size-8" />
26
- <Spinner className="size-12" />
27
- </div>
28
- ),
29
- };
30
-
31
- export const InButton: Story = {
32
- render: () => (
33
- <div className="flex gap-4">
34
- <button className="inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-primary-foreground">
35
- <Spinner className="size-4" />
36
- Loading...
37
- </button>
38
- <button className="inline-flex items-center gap-2 rounded-md border px-4 py-2">
39
- <Spinner className="size-4" />
40
- Processing
41
- </button>
42
- </div>
43
- ),
44
- };
45
-
46
- export const WithText: Story = {
47
- render: () => (
48
- <div className="flex items-center gap-2">
49
- <Spinner />
50
- <span className="text-sm text-muted-foreground">Loading data...</span>
51
- </div>
52
- ),
53
- };
54
-
@@ -1,30 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { render } from "@testing-library/react";
3
- import { Spinner } from "./spinner";
4
-
5
- describe("Spinner", () => {
6
- it("should render spinner", () => {
7
- const { container } = render(<Spinner />);
8
- const spinner = container.querySelector('[role="status"]');
9
- expect(spinner).toBeInTheDocument();
10
- });
11
-
12
- it("should have aria-label", () => {
13
- const { container } = render(<Spinner />);
14
- const spinner = container.querySelector('[role="status"]');
15
- expect(spinner).toHaveAttribute("aria-label", "Loading");
16
- });
17
-
18
- it("should apply custom className", () => {
19
- const { container } = render(<Spinner className="size-8" />);
20
- const spinner = container.querySelector('[role="status"]');
21
- expect(spinner).toHaveClass("size-8");
22
- });
23
-
24
- it("should have animate-spin class", () => {
25
- const { container } = render(<Spinner />);
26
- const spinner = container.querySelector('[role="status"]');
27
- expect(spinner).toHaveClass("animate-spin");
28
- });
29
- });
30
-
@@ -1,16 +0,0 @@
1
- import { Loader2Icon } from "lucide-react"
2
-
3
- import { cn } from "@/lib/utils"
4
-
5
- function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
6
- return (
7
- <Loader2Icon
8
- role="status"
9
- aria-label="Loading"
10
- className={cn("size-4 animate-spin", className)}
11
- {...props}
12
- />
13
- )
14
- }
15
-
16
- export { Spinner }
@@ -1,108 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react-vite";
2
- import { useState } from "react";
3
- import { Switch } from "./switch";
4
- import { Label } from "./label";
5
-
6
- const meta = {
7
- title: "Components/Switch",
8
- component: Switch,
9
- parameters: {
10
- layout: "padded",
11
- },
12
- tags: ["autodocs"],
13
- argTypes: {
14
- checked: {
15
- control: "boolean",
16
- description: "Whether the switch is checked.",
17
- },
18
- disabled: {
19
- control: "boolean",
20
- description: "Whether the switch is disabled.",
21
- },
22
- },
23
- } satisfies Meta<typeof Switch>;
24
-
25
- export default meta;
26
- type Story = StoryObj<typeof meta>;
27
-
28
- export const Default: Story = {
29
- render: () => {
30
- const [checked, setChecked] = useState(false);
31
- return (
32
- <div className="flex items-center space-x-2">
33
- <Switch id="airplane-mode" checked={checked} onCheckedChange={setChecked} />
34
- <Label htmlFor="airplane-mode">Airplane Mode</Label>
35
- </div>
36
- );
37
- },
38
- };
39
-
40
- export const Checked: Story = {
41
- render: () => (
42
- <div className="flex items-center space-x-2">
43
- <Switch id="checked" defaultChecked />
44
- <Label htmlFor="checked">Enabled by default</Label>
45
- </div>
46
- ),
47
- };
48
-
49
- export const Disabled: Story = {
50
- render: () => (
51
- <div className="space-y-4">
52
- <div className="flex items-center space-x-2">
53
- <Switch id="disabled" disabled />
54
- <Label htmlFor="disabled">Disabled off</Label>
55
- </div>
56
- <div className="flex items-center space-x-2">
57
- <Switch id="disabled-on" disabled defaultChecked />
58
- <Label htmlFor="disabled-on">Disabled on</Label>
59
- </div>
60
- </div>
61
- ),
62
- };
63
-
64
- export const Multiple: Story = {
65
- render: () => {
66
- const [settings, setSettings] = useState({
67
- notifications: true,
68
- email: false,
69
- sms: true,
70
- });
71
-
72
- return (
73
- <div className="space-y-3">
74
- <div className="flex items-center space-x-2">
75
- <Switch
76
- id="notifications"
77
- checked={settings.notifications}
78
- onCheckedChange={(checked) =>
79
- setSettings({ ...settings, notifications: checked as boolean })
80
- }
81
- />
82
- <Label htmlFor="notifications">Notifications</Label>
83
- </div>
84
- <div className="flex items-center space-x-2">
85
- <Switch
86
- id="email"
87
- checked={settings.email}
88
- onCheckedChange={(checked) =>
89
- setSettings({ ...settings, email: checked as boolean })
90
- }
91
- />
92
- <Label htmlFor="email">Email</Label>
93
- </div>
94
- <div className="flex items-center space-x-2">
95
- <Switch
96
- id="sms"
97
- checked={settings.sms}
98
- onCheckedChange={(checked) =>
99
- setSettings({ ...settings, sms: checked as boolean })
100
- }
101
- />
102
- <Label htmlFor="sms">SMS</Label>
103
- </div>
104
- </div>
105
- );
106
- },
107
- };
108
-