create-auto-app 1.34.0 → 1.35.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.
Files changed (157) hide show
  1. package/package.json +2 -2
  2. package/templates/typical/.context/components-db.json +4006 -0
  3. package/templates/typical/.gitignore +1 -1
  4. package/templates/typical/auto.config.ts +85 -80
  5. package/templates/typical/client/.gitignore +0 -4
  6. package/templates/typical/client/.storybook/main.ts +0 -66
  7. package/templates/typical/client/.storybook/manager-head.html +0 -154
  8. package/templates/typical/client/.storybook/manager.ts +0 -164
  9. package/templates/typical/client/.storybook/preview-head.html +0 -31
  10. package/templates/typical/client/.storybook/preview.tsx +0 -120
  11. package/templates/typical/client/codegen.ts +0 -17
  12. package/templates/typical/client/components.json +0 -29
  13. package/templates/typical/client/index.html +0 -12
  14. package/templates/typical/client/package.json +0 -69
  15. package/templates/typical/client/pnpm-lock.yaml +0 -7868
  16. package/templates/typical/client/public/blank.svg +0 -1
  17. package/templates/typical/client/public/mockServiceWorker.js +0 -336
  18. package/templates/typical/client/src/App.tsx +0 -29
  19. package/templates/typical/client/src/components/.gitkeep +0 -0
  20. package/templates/typical/client/src/components/ui/Accordion.stories.tsx +0 -49
  21. package/templates/typical/client/src/components/ui/Accordion.tsx +0 -55
  22. package/templates/typical/client/src/components/ui/Alert.stories.tsx +0 -29
  23. package/templates/typical/client/src/components/ui/Alert.tsx +0 -56
  24. package/templates/typical/client/src/components/ui/AlertDialog.stories.tsx +0 -67
  25. package/templates/typical/client/src/components/ui/AlertDialog.tsx +0 -178
  26. package/templates/typical/client/src/components/ui/AspectRatio.stories.tsx +0 -35
  27. package/templates/typical/client/src/components/ui/AspectRatio.tsx +0 -13
  28. package/templates/typical/client/src/components/ui/Avatar.stories.tsx +0 -45
  29. package/templates/typical/client/src/components/ui/Avatar.tsx +0 -98
  30. package/templates/typical/client/src/components/ui/Badge.stories.tsx +0 -41
  31. package/templates/typical/client/src/components/ui/Badge.tsx +0 -45
  32. package/templates/typical/client/src/components/ui/Breadcrumb.stories.tsx +0 -54
  33. package/templates/typical/client/src/components/ui/Breadcrumb.tsx +0 -104
  34. package/templates/typical/client/src/components/ui/Button.stories.tsx +0 -102
  35. package/templates/typical/client/src/components/ui/Button.tsx +0 -67
  36. package/templates/typical/client/src/components/ui/ButtonGroup.stories.tsx +0 -32
  37. package/templates/typical/client/src/components/ui/ButtonGroup.tsx +0 -81
  38. package/templates/typical/client/src/components/ui/Calendar.stories.tsx +0 -40
  39. package/templates/typical/client/src/components/ui/Calendar.tsx +0 -165
  40. package/templates/typical/client/src/components/ui/Card.stories.tsx +0 -44
  41. package/templates/typical/client/src/components/ui/Card.tsx +0 -66
  42. package/templates/typical/client/src/components/ui/Carousel.stories.tsx +0 -56
  43. package/templates/typical/client/src/components/ui/Carousel.tsx +0 -225
  44. package/templates/typical/client/src/components/ui/Chart.stories.tsx +0 -39
  45. package/templates/typical/client/src/components/ui/Chart.tsx +0 -305
  46. package/templates/typical/client/src/components/ui/Checkbox.stories.tsx +0 -35
  47. package/templates/typical/client/src/components/ui/Checkbox.tsx +0 -30
  48. package/templates/typical/client/src/components/ui/Collapsible.stories.tsx +0 -58
  49. package/templates/typical/client/src/components/ui/Collapsible.tsx +0 -18
  50. package/templates/typical/client/src/components/ui/Combobox.stories.tsx +0 -75
  51. package/templates/typical/client/src/components/ui/Combobox.tsx +0 -296
  52. package/templates/typical/client/src/components/ui/Command.stories.tsx +0 -71
  53. package/templates/typical/client/src/components/ui/Command.tsx +0 -157
  54. package/templates/typical/client/src/components/ui/ContextMenu.stories.tsx +0 -68
  55. package/templates/typical/client/src/components/ui/ContextMenu.tsx +0 -231
  56. package/templates/typical/client/src/components/ui/DesignSystem-Colors.mdx +0 -68
  57. package/templates/typical/client/src/components/ui/DesignSystem-Colors.stories.tsx +0 -117
  58. package/templates/typical/client/src/components/ui/DesignSystem-Layout.mdx +0 -64
  59. package/templates/typical/client/src/components/ui/DesignSystem-Layout.stories.tsx +0 -167
  60. package/templates/typical/client/src/components/ui/DesignSystem-Overview.stories.tsx +0 -748
  61. package/templates/typical/client/src/components/ui/DesignSystem-Typography.mdx +0 -31
  62. package/templates/typical/client/src/components/ui/DesignSystem-Typography.stories.tsx +0 -80
  63. package/templates/typical/client/src/components/ui/Dialog.stories.tsx +0 -74
  64. package/templates/typical/client/src/components/ui/Dialog.tsx +0 -154
  65. package/templates/typical/client/src/components/ui/Direction.stories.tsx +0 -38
  66. package/templates/typical/client/src/components/ui/Direction.tsx +0 -24
  67. package/templates/typical/client/src/components/ui/Drawer.stories.tsx +0 -70
  68. package/templates/typical/client/src/components/ui/Drawer.tsx +0 -124
  69. package/templates/typical/client/src/components/ui/DropdownMenu.stories.tsx +0 -74
  70. package/templates/typical/client/src/components/ui/DropdownMenu.tsx +0 -239
  71. package/templates/typical/client/src/components/ui/Empty.stories.tsx +0 -37
  72. package/templates/typical/client/src/components/ui/Empty.tsx +0 -98
  73. package/templates/typical/client/src/components/ui/Field.stories.tsx +0 -50
  74. package/templates/typical/client/src/components/ui/Field.tsx +0 -251
  75. package/templates/typical/client/src/components/ui/Form.stories.tsx +0 -45
  76. package/templates/typical/client/src/components/ui/Form.tsx +0 -148
  77. package/templates/typical/client/src/components/ui/HoverCard.stories.tsx +0 -49
  78. package/templates/typical/client/src/components/ui/HoverCard.tsx +0 -39
  79. package/templates/typical/client/src/components/ui/Input.stories.tsx +0 -42
  80. package/templates/typical/client/src/components/ui/Input.tsx +0 -22
  81. package/templates/typical/client/src/components/ui/InputGroup.stories.tsx +0 -53
  82. package/templates/typical/client/src/components/ui/InputGroup.tsx +0 -153
  83. package/templates/typical/client/src/components/ui/InputOTP.stories.tsx +0 -42
  84. package/templates/typical/client/src/components/ui/InputOTP.tsx +0 -72
  85. package/templates/typical/client/src/components/ui/Item.stories.tsx +0 -64
  86. package/templates/typical/client/src/components/ui/Item.tsx +0 -168
  87. package/templates/typical/client/src/components/ui/Kbd.stories.tsx +0 -59
  88. package/templates/typical/client/src/components/ui/Kbd.tsx +0 -22
  89. package/templates/typical/client/src/components/ui/Label.stories.tsx +0 -90
  90. package/templates/typical/client/src/components/ui/Label.tsx +0 -44
  91. package/templates/typical/client/src/components/ui/Menubar.stories.tsx +0 -78
  92. package/templates/typical/client/src/components/ui/Menubar.tsx +0 -251
  93. package/templates/typical/client/src/components/ui/NativeSelect.stories.tsx +0 -45
  94. package/templates/typical/client/src/components/ui/NativeSelect.tsx +0 -50
  95. package/templates/typical/client/src/components/ui/NavigationMenu.stories.tsx +0 -80
  96. package/templates/typical/client/src/components/ui/NavigationMenu.tsx +0 -152
  97. package/templates/typical/client/src/components/ui/Pagination.stories.tsx +0 -77
  98. package/templates/typical/client/src/components/ui/Pagination.tsx +0 -108
  99. package/templates/typical/client/src/components/ui/Popover.stories.tsx +0 -53
  100. package/templates/typical/client/src/components/ui/Popover.tsx +0 -57
  101. package/templates/typical/client/src/components/ui/Progress.stories.tsx +0 -32
  102. package/templates/typical/client/src/components/ui/Progress.tsx +0 -25
  103. package/templates/typical/client/src/components/ui/RadioGroup.stories.tsx +0 -50
  104. package/templates/typical/client/src/components/ui/RadioGroup.tsx +0 -36
  105. package/templates/typical/client/src/components/ui/Resizable.stories.tsx +0 -72
  106. package/templates/typical/client/src/components/ui/Resizable.tsx +0 -54
  107. package/templates/typical/client/src/components/ui/ScrollArea.stories.tsx +0 -45
  108. package/templates/typical/client/src/components/ui/ScrollArea.tsx +0 -51
  109. package/templates/typical/client/src/components/ui/Select.stories.tsx +0 -59
  110. package/templates/typical/client/src/components/ui/Select.tsx +0 -171
  111. package/templates/typical/client/src/components/ui/Separator.stories.tsx +0 -42
  112. package/templates/typical/client/src/components/ui/Separator.tsx +0 -27
  113. package/templates/typical/client/src/components/ui/Sheet.stories.tsx +0 -68
  114. package/templates/typical/client/src/components/ui/Sheet.tsx +0 -115
  115. package/templates/typical/client/src/components/ui/Sidebar.stories.tsx +0 -96
  116. package/templates/typical/client/src/components/ui/Sidebar.tsx +0 -695
  117. package/templates/typical/client/src/components/ui/Skeleton.stories.tsx +0 -40
  118. package/templates/typical/client/src/components/ui/Skeleton.tsx +0 -11
  119. package/templates/typical/client/src/components/ui/Slider.stories.tsx +0 -24
  120. package/templates/typical/client/src/components/ui/Slider.tsx +0 -55
  121. package/templates/typical/client/src/components/ui/Sonner.stories.tsx +0 -45
  122. package/templates/typical/client/src/components/ui/Sonner.tsx +0 -38
  123. package/templates/typical/client/src/components/ui/Spinner.stories.tsx +0 -26
  124. package/templates/typical/client/src/components/ui/Spinner.tsx +0 -13
  125. package/templates/typical/client/src/components/ui/Switch.stories.tsx +0 -39
  126. package/templates/typical/client/src/components/ui/Switch.tsx +0 -35
  127. package/templates/typical/client/src/components/ui/Table.stories.tsx +0 -67
  128. package/templates/typical/client/src/components/ui/Table.tsx +0 -86
  129. package/templates/typical/client/src/components/ui/Tabs.stories.tsx +0 -53
  130. package/templates/typical/client/src/components/ui/Tabs.tsx +0 -75
  131. package/templates/typical/client/src/components/ui/Textarea.stories.tsx +0 -27
  132. package/templates/typical/client/src/components/ui/Textarea.tsx +0 -22
  133. package/templates/typical/client/src/components/ui/Toast.stories.tsx +0 -116
  134. package/templates/typical/client/src/components/ui/Toast.tsx +0 -123
  135. package/templates/typical/client/src/components/ui/Toaster.tsx +0 -32
  136. package/templates/typical/client/src/components/ui/Toggle.stories.tsx +0 -44
  137. package/templates/typical/client/src/components/ui/Toggle.tsx +0 -42
  138. package/templates/typical/client/src/components/ui/ToggleGroup.stories.tsx +0 -61
  139. package/templates/typical/client/src/components/ui/ToggleGroup.tsx +0 -83
  140. package/templates/typical/client/src/components/ui/Tooltip.stories.tsx +0 -42
  141. package/templates/typical/client/src/components/ui/Tooltip.tsx +0 -48
  142. package/templates/typical/client/src/gql/execute.ts +0 -11
  143. package/templates/typical/client/src/gql/fragment-masking.ts +0 -83
  144. package/templates/typical/client/src/gql/gql.ts +0 -9
  145. package/templates/typical/client/src/gql/graphql.ts +0 -182
  146. package/templates/typical/client/src/gql/index.ts +0 -2
  147. package/templates/typical/client/src/graphql/mutations.ts +0 -0
  148. package/templates/typical/client/src/graphql/queries.ts +0 -0
  149. package/templates/typical/client/src/hooks/.gitkeep +0 -0
  150. package/templates/typical/client/src/hooks/use-mobile.ts +0 -19
  151. package/templates/typical/client/src/hooks/use-toast.ts +0 -186
  152. package/templates/typical/client/src/index.css +0 -121
  153. package/templates/typical/client/src/lib/utils.ts +0 -6
  154. package/templates/typical/client/src/main.tsx +0 -5
  155. package/templates/typical/client/tsconfig.app.json +0 -26
  156. package/templates/typical/client/tsconfig.json +0 -10
  157. package/templates/typical/client/vite.config.ts +0 -50
@@ -1,40 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Skeleton } from '@/components/ui/Skeleton';
3
-
4
- const meta: Meta<typeof Skeleton> = {
5
- title: 'UI Components/Skeleton',
6
- component: Skeleton,
7
- };
8
- export default meta;
9
- type Story = StoryObj<typeof Skeleton>;
10
-
11
- /** Shows a skeleton mimicking a user profile layout with an avatar circle and two text lines. */
12
- export const Default: Story = {
13
- render: () => (
14
- <div className="flex items-center space-x-4">
15
- <Skeleton className="h-12 w-12 rounded-full" />
16
- <div className="space-y-2">
17
- <Skeleton className="h-4 w-[250px]" />
18
- <Skeleton className="h-4 w-[200px]" />
19
- </div>
20
- </div>
21
- ),
22
- };
23
-
24
- /** Shows a skeleton mimicking a full card layout with image, text, and avatar placeholders. */
25
- export const CardSkeleton: Story = {
26
- render: () => (
27
- <div className="w-[300px] space-y-4 rounded-lg border p-4">
28
- <Skeleton className="h-40 w-full rounded-md" />
29
- <div className="space-y-2">
30
- <Skeleton className="h-5 w-3/4" />
31
- <Skeleton className="h-4 w-full" />
32
- <Skeleton className="h-4 w-5/6" />
33
- </div>
34
- <div className="flex items-center gap-2 pt-2">
35
- <Skeleton className="h-8 w-8 rounded-full" />
36
- <Skeleton className="h-4 w-24" />
37
- </div>
38
- </div>
39
- ),
40
- };
@@ -1,11 +0,0 @@
1
- import { cn } from '@/lib/utils';
2
-
3
- /**
4
- * A placeholder element that animates with a pulse effect to indicate content is loading.
5
- * Use to mirror the shape of upcoming content (e.g., text lines, avatars, cards) and reduce perceived load time.
6
- */
7
- function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
8
- return <div data-slot="skeleton" className={cn('bg-accent animate-pulse rounded-md', className)} {...props} />;
9
- }
10
-
11
- export { Skeleton };
@@ -1,24 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Slider } from '@/components/ui/Slider';
3
-
4
- const meta: Meta<typeof Slider> = {
5
- title: 'UI Components/Slider',
6
- component: Slider,
7
- };
8
- export default meta;
9
- type Story = StoryObj<typeof Slider>;
10
-
11
- /** Shows a single-thumb slider at 50% of a 0-100 range. */
12
- export const Default: Story = {
13
- render: () => <Slider defaultValue={[50]} max={100} step={1} className="w-[60%]" />,
14
- };
15
-
16
- /** Demonstrates a dual-thumb range slider for selecting a value range between 25 and 75. */
17
- export const Range: Story = {
18
- render: () => <Slider defaultValue={[25, 75]} max={100} step={1} className="w-[60%]" />,
19
- };
20
-
21
- /** Shows a slider with discrete step increments of 10. */
22
- export const WithSteps: Story = {
23
- render: () => <Slider defaultValue={[20]} max={100} step={10} className="w-[60%]" />,
24
- };
@@ -1,55 +0,0 @@
1
- import * as React from 'react';
2
- import { Slider as SliderPrimitive } from 'radix-ui';
3
-
4
- import { cn } from '@/lib/utils';
5
-
6
- /** A draggable range input. Supports single or multiple thumbs (range selection), keyboard navigation, and vertical orientation. */
7
- function Slider({
8
- className,
9
- defaultValue,
10
- value,
11
- min = 0,
12
- max = 100,
13
- ...props
14
- }: React.ComponentProps<typeof SliderPrimitive.Root>) {
15
- const _values = React.useMemo(
16
- () => (Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max]),
17
- [value, defaultValue, min, max],
18
- );
19
-
20
- return (
21
- <SliderPrimitive.Root
22
- data-slot="slider"
23
- defaultValue={defaultValue}
24
- value={value}
25
- min={min}
26
- max={max}
27
- className={cn(
28
- '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',
29
- className,
30
- )}
31
- {...props}
32
- >
33
- <SliderPrimitive.Track
34
- data-slot="slider-track"
35
- className={cn(
36
- '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',
37
- )}
38
- >
39
- <SliderPrimitive.Range
40
- data-slot="slider-range"
41
- className={cn('bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full')}
42
- />
43
- </SliderPrimitive.Track>
44
- {Array.from({ length: _values.length }, (_, index) => (
45
- <SliderPrimitive.Thumb
46
- data-slot="slider-thumb"
47
- key={index}
48
- 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"
49
- />
50
- ))}
51
- </SliderPrimitive.Root>
52
- );
53
- }
54
-
55
- export { Slider };
@@ -1,45 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { ThemeProvider } from 'next-themes';
3
- import { toast } from 'sonner';
4
- import { Toaster } from '@/components/ui/Sonner';
5
- import { Button } from '@/components/ui/Button';
6
-
7
- const meta: Meta<typeof Toaster> = {
8
- title: 'UI Components/Sonner',
9
- component: Toaster,
10
- decorators: [
11
- (Story) => (
12
- <ThemeProvider attribute="class" defaultTheme="light">
13
- <Story />
14
- </ThemeProvider>
15
- ),
16
- ],
17
- };
18
- export default meta;
19
- type Story = StoryObj<typeof Toaster>;
20
-
21
- /** Demonstrates all toast variants (default, success, error, warning, info) triggered by buttons. */
22
- export const Default: Story = {
23
- render: () => (
24
- <div>
25
- <Toaster />
26
- <div className="flex flex-wrap gap-2">
27
- <Button variant="outline" onClick={() => toast('Event has been created.')}>
28
- Show Toast
29
- </Button>
30
- <Button variant="outline" onClick={() => toast.success('Successfully saved!')}>
31
- Success
32
- </Button>
33
- <Button variant="outline" onClick={() => toast.error('Something went wrong.')}>
34
- Error
35
- </Button>
36
- <Button variant="outline" onClick={() => toast.warning('Please check your input.')}>
37
- Warning
38
- </Button>
39
- <Button variant="outline" onClick={() => toast.info('Here is some information.')}>
40
- Info
41
- </Button>
42
- </div>
43
- </div>
44
- ),
45
- };
@@ -1,38 +0,0 @@
1
- 'use client';
2
-
3
- import { CircleCheckIcon, InfoIcon, Loader2Icon, OctagonXIcon, TriangleAlertIcon } from 'lucide-react';
4
- import { useTheme } from 'next-themes';
5
- import { Toaster as Sonner, type ToasterProps } from 'sonner';
6
-
7
- /**
8
- * A pre-configured Sonner toast container that integrates with the app's theme system.
9
- * Provides styled icons for success, info, warning, error, and loading states. Place once at the app root and trigger toasts via the `toast()` function 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,26 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Spinner } from '@/components/ui/Spinner';
3
-
4
- const meta: Meta<typeof Spinner> = {
5
- title: 'UI Components/Spinner',
6
- component: Spinner,
7
- };
8
- export default meta;
9
- type Story = StoryObj<typeof Spinner>;
10
-
11
- /** Shows the spinner at its default size (16px). */
12
- export const Default: Story = {};
13
-
14
- /** Shows a smaller 12px spinner for inline or compact contexts. */
15
- export const Small: Story = {
16
- args: {
17
- className: 'size-3',
18
- },
19
- };
20
-
21
- /** Shows a larger 32px spinner for full-page or section-level loading states. */
22
- export const Large: Story = {
23
- args: {
24
- className: 'size-8',
25
- },
26
- };
@@ -1,13 +0,0 @@
1
- import { Loader2Icon } from 'lucide-react';
2
-
3
- import { cn } from '@/lib/utils';
4
-
5
- /**
6
- * An animated spinning loader icon that indicates an in-progress operation.
7
- * Includes role="status" and an aria-label for accessibility. Resize via className (e.g., "size-8").
8
- */
9
- function Spinner({ className, ...props }: React.ComponentProps<'svg'>) {
10
- return <Loader2Icon role="status" aria-label="Loading" className={cn('size-4 animate-spin', className)} {...props} />;
11
- }
12
-
13
- export { Spinner };
@@ -1,39 +0,0 @@
1
- import * as React from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { Switch } from '@/components/ui/Switch';
4
-
5
- const meta: Meta<typeof Switch> = {
6
- title: 'UI Components/Switch',
7
- component: Switch,
8
- };
9
- export default meta;
10
- type Story = StoryObj<typeof Switch>;
11
-
12
- /** Shows the switch in its default unchecked state. */
13
- export const Default: Story = {};
14
-
15
- /** Shows the switch in its checked (on) state. */
16
- export const Checked: Story = {
17
- args: {
18
- defaultChecked: true,
19
- },
20
- };
21
-
22
- /** Shows a disabled switch that cannot be interacted with. */
23
- export const Disabled: Story = {
24
- args: {
25
- disabled: true,
26
- },
27
- };
28
-
29
- /** Shows the switch paired with an associated label element for accessible labeling. */
30
- export const WithLabel: Story = {
31
- render: () => (
32
- <div className="flex items-center gap-2">
33
- <Switch id="airplane-mode" />
34
- <label htmlFor="airplane-mode" className="text-sm">
35
- Airplane Mode
36
- </label>
37
- </div>
38
- ),
39
- };
@@ -1,35 +0,0 @@
1
- import * as React from 'react';
2
- import { Switch as SwitchPrimitive } from 'radix-ui';
3
-
4
- import { cn } from '@/lib/utils';
5
-
6
- /** A sliding on/off toggle control with WAI-ARIA switch role and keyboard support. */
7
- function Switch({
8
- className,
9
- /** Controls the physical dimensions of the switch track and thumb. */
10
- size = 'default',
11
- ...props
12
- }: React.ComponentProps<typeof SwitchPrimitive.Root> & {
13
- size?: 'sm' | 'default';
14
- }) {
15
- return (
16
- <SwitchPrimitive.Root
17
- data-slot="switch"
18
- data-size={size}
19
- className={cn(
20
- 'peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6',
21
- className,
22
- )}
23
- {...props}
24
- >
25
- <SwitchPrimitive.Thumb
26
- data-slot="switch-thumb"
27
- className={cn(
28
- 'bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0',
29
- )}
30
- />
31
- </SwitchPrimitive.Root>
32
- );
33
- }
34
-
35
- export { Switch };
@@ -1,67 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, TableCaption } from '@/components/ui/Table';
3
-
4
- const meta: Meta<typeof Table> = {
5
- title: 'UI Components/Table',
6
- component: Table,
7
- };
8
- export default meta;
9
- type Story = StoryObj<typeof Table>;
10
-
11
- const invoices = [
12
- { invoice: 'INV001', status: 'Paid', method: 'Credit Card', amount: '$250.00' },
13
- { invoice: 'INV002', status: 'Pending', method: 'PayPal', amount: '$150.00' },
14
- { invoice: 'INV003', status: 'Unpaid', method: 'Bank Transfer', amount: '$350.00' },
15
- { invoice: 'INV004', status: 'Paid', method: 'Credit Card', amount: '$450.00' },
16
- ];
17
-
18
- /** Shows a full table with header, body, and caption using invoice data. */
19
- export const Default: Story = {
20
- render: () => (
21
- <Table>
22
- <TableCaption>A list of recent invoices.</TableCaption>
23
- <TableHeader>
24
- <TableRow>
25
- <TableHead>Invoice</TableHead>
26
- <TableHead>Status</TableHead>
27
- <TableHead>Method</TableHead>
28
- <TableHead className="text-right">Amount</TableHead>
29
- </TableRow>
30
- </TableHeader>
31
- <TableBody>
32
- {invoices.map((invoice) => (
33
- <TableRow key={invoice.invoice}>
34
- <TableCell className="font-medium">{invoice.invoice}</TableCell>
35
- <TableCell>{invoice.status}</TableCell>
36
- <TableCell>{invoice.method}</TableCell>
37
- <TableCell className="text-right">{invoice.amount}</TableCell>
38
- </TableRow>
39
- ))}
40
- </TableBody>
41
- </Table>
42
- ),
43
- };
44
-
45
- /** Shows a minimal two-column table without caption or footer. */
46
- export const Minimal: Story = {
47
- render: () => (
48
- <Table>
49
- <TableHeader>
50
- <TableRow>
51
- <TableHead>Name</TableHead>
52
- <TableHead>Role</TableHead>
53
- </TableRow>
54
- </TableHeader>
55
- <TableBody>
56
- <TableRow>
57
- <TableCell>Alice</TableCell>
58
- <TableCell>Engineer</TableCell>
59
- </TableRow>
60
- <TableRow>
61
- <TableCell>Bob</TableCell>
62
- <TableCell>Designer</TableCell>
63
- </TableRow>
64
- </TableBody>
65
- </Table>
66
- ),
67
- };
@@ -1,86 +0,0 @@
1
- 'use client';
2
-
3
- import * as React from 'react';
4
-
5
- import { cn } from '@/lib/utils';
6
-
7
- /**
8
- * A responsive data table with horizontal scroll overflow.
9
- * Compose with TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, and TableCaption subcomponents.
10
- */
11
- function Table({ className, ...props }: React.ComponentProps<'table'>) {
12
- return (
13
- <div data-slot="table-container" className="relative w-full overflow-x-auto">
14
- <table data-slot="table" className={cn('w-full caption-bottom text-sm', className)} {...props} />
15
- </div>
16
- );
17
- }
18
-
19
- /** The header section of a Table, rendering a thead with bottom-bordered rows. */
20
- function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
21
- return <thead data-slot="table-header" className={cn('[&_tr]:border-b', className)} {...props} />;
22
- }
23
-
24
- /** The body section of a Table, rendering a tbody with no border on the last row. */
25
- function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {
26
- return <tbody data-slot="table-body" className={cn('[&_tr:last-child]:border-0', className)} {...props} />;
27
- }
28
-
29
- /** The footer section of a Table, rendering a tfoot with a muted background and top border. */
30
- function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {
31
- return (
32
- <tfoot
33
- data-slot="table-footer"
34
- className={cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', className)}
35
- {...props}
36
- />
37
- );
38
- }
39
-
40
- /** A table row with hover highlight and selected state styling via data-state="selected". */
41
- function TableRow({ className, ...props }: React.ComponentProps<'tr'>) {
42
- return (
43
- <tr
44
- data-slot="table-row"
45
- className={cn('hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors', className)}
46
- {...props}
47
- />
48
- );
49
- }
50
-
51
- /** A table header cell with bold text and left alignment. Automatically adjusts padding when containing a checkbox. */
52
- function TableHead({ className, ...props }: React.ComponentProps<'th'>) {
53
- return (
54
- <th
55
- data-slot="table-head"
56
- className={cn(
57
- 'text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
58
- className,
59
- )}
60
- {...props}
61
- />
62
- );
63
- }
64
-
65
- /** A table data cell with standard padding and vertical alignment. */
66
- function TableCell({ className, ...props }: React.ComponentProps<'td'>) {
67
- return (
68
- <td
69
- data-slot="table-cell"
70
- className={cn(
71
- 'p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
72
- className,
73
- )}
74
- {...props}
75
- />
76
- );
77
- }
78
-
79
- /** A table caption rendered below the table body in muted text. */
80
- function TableCaption({ className, ...props }: React.ComponentProps<'caption'>) {
81
- return (
82
- <caption data-slot="table-caption" className={cn('text-muted-foreground mt-4 text-sm', className)} {...props} />
83
- );
84
- }
85
-
86
- export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };
@@ -1,53 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/Tabs';
3
-
4
- const meta: Meta<typeof Tabs> = {
5
- title: 'UI Components/Tabs',
6
- component: Tabs,
7
- };
8
- export default meta;
9
- type Story = StoryObj<typeof Tabs>;
10
-
11
- /** Shows the default pill-style tabs with three panels. */
12
- export const Default: Story = {
13
- render: () => (
14
- <Tabs defaultValue="account" className="w-[400px]">
15
- <TabsList>
16
- <TabsTrigger value="account">Account</TabsTrigger>
17
- <TabsTrigger value="password">Password</TabsTrigger>
18
- <TabsTrigger value="settings">Settings</TabsTrigger>
19
- </TabsList>
20
- <TabsContent value="account">
21
- <p className="text-sm text-muted-foreground p-4">Make changes to your account here.</p>
22
- </TabsContent>
23
- <TabsContent value="password">
24
- <p className="text-sm text-muted-foreground p-4">Change your password here.</p>
25
- </TabsContent>
26
- <TabsContent value="settings">
27
- <p className="text-sm text-muted-foreground p-4">Adjust your settings here.</p>
28
- </TabsContent>
29
- </Tabs>
30
- ),
31
- };
32
-
33
- /** Shows the line variant where the active tab is indicated by an underline rather than a background. */
34
- export const LineVariant: Story = {
35
- render: () => (
36
- <Tabs defaultValue="overview" className="w-[400px]">
37
- <TabsList variant="line">
38
- <TabsTrigger value="overview">Overview</TabsTrigger>
39
- <TabsTrigger value="analytics">Analytics</TabsTrigger>
40
- <TabsTrigger value="reports">Reports</TabsTrigger>
41
- </TabsList>
42
- <TabsContent value="overview">
43
- <p className="text-sm text-muted-foreground p-4">Overview content goes here.</p>
44
- </TabsContent>
45
- <TabsContent value="analytics">
46
- <p className="text-sm text-muted-foreground p-4">Analytics content goes here.</p>
47
- </TabsContent>
48
- <TabsContent value="reports">
49
- <p className="text-sm text-muted-foreground p-4">Reports content goes here.</p>
50
- </TabsContent>
51
- </Tabs>
52
- ),
53
- };
@@ -1,75 +0,0 @@
1
- import * as React from 'react';
2
- import { cva, type VariantProps } from 'class-variance-authority';
3
- import { Tabs as TabsPrimitive } from 'radix-ui';
4
-
5
- import { cn } from '@/lib/utils';
6
-
7
- /** Layered content panels activated by tab triggers. Supports horizontal and vertical orientations with keyboard navigation. */
8
- function Tabs({ className, orientation = 'horizontal', ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {
9
- return (
10
- <TabsPrimitive.Root
11
- data-slot="tabs"
12
- data-orientation={orientation}
13
- orientation={orientation}
14
- className={cn('group/tabs flex gap-2 data-[orientation=horizontal]:flex-col', className)}
15
- {...props}
16
- />
17
- );
18
- }
19
-
20
- const tabsListVariants = cva(
21
- 'rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col',
22
- {
23
- variants: {
24
- variant: {
25
- default: 'bg-muted',
26
- line: 'gap-1 bg-transparent',
27
- },
28
- },
29
- defaultVariants: {
30
- variant: 'default',
31
- },
32
- },
33
- );
34
-
35
- /**
36
- * The container for tab triggers. Supports "default" (pill background) and "line" (underline indicator) variants.
37
- */
38
- function TabsList({
39
- className,
40
- variant = 'default',
41
- ...props
42
- }: React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>) {
43
- return (
44
- <TabsPrimitive.List
45
- data-slot="tabs-list"
46
- data-variant={variant}
47
- className={cn(tabsListVariants({ variant }), className)}
48
- {...props}
49
- />
50
- );
51
- }
52
-
53
- /** A clickable tab button that activates its associated TabsContent panel. */
54
- function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
55
- return (
56
- <TabsPrimitive.Trigger
57
- data-slot="tabs-trigger"
58
- className={cn(
59
- "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
60
- 'group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent',
61
- 'data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground',
62
- 'after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100',
63
- className,
64
- )}
65
- {...props}
66
- />
67
- );
68
- }
69
-
70
- /** The content panel associated with a tab trigger, shown when its corresponding trigger is active. */
71
- function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {
72
- return <TabsPrimitive.Content data-slot="tabs-content" className={cn('flex-1 outline-none', className)} {...props} />;
73
- }
74
-
75
- export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
@@ -1,27 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Textarea } from '@/components/ui/Textarea';
3
-
4
- const meta: Meta<typeof Textarea> = {
5
- title: 'UI Components/Textarea',
6
- component: Textarea,
7
- };
8
- export default meta;
9
- type Story = StoryObj<typeof Textarea>;
10
-
11
- /** Shows the textarea in its default empty state. */
12
- export const Default: Story = {};
13
-
14
- /** Shows the textarea with placeholder text. */
15
- export const WithPlaceholder: Story = {
16
- args: {
17
- placeholder: 'Type your message here...',
18
- },
19
- };
20
-
21
- /** Shows a disabled textarea that cannot receive input. */
22
- export const Disabled: Story = {
23
- args: {
24
- placeholder: 'This textarea is disabled',
25
- disabled: true,
26
- },
27
- };
@@ -1,22 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { cn } from '@/lib/utils';
4
-
5
- /**
6
- * A multi-line text input that auto-sizes to its content via field-sizing-content.
7
- * Supports aria-invalid styling for form validation errors.
8
- */
9
- function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {
10
- return (
11
- <textarea
12
- data-slot="textarea"
13
- className={cn(
14
- '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',
15
- className,
16
- )}
17
- {...props}
18
- />
19
- );
20
- }
21
-
22
- export { Textarea };