@auto-engineer/generate-react-client 1.64.0 → 1.65.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 (144) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/starter/.storybook/main.ts +17 -22
  3. package/dist/starter/.storybook/manager-head.html +31 -31
  4. package/dist/starter/.storybook/manager.ts +133 -133
  5. package/dist/starter/.storybook/preview-head.html +12 -12
  6. package/dist/starter/.storybook/preview.tsx +79 -79
  7. package/dist/starter/biome.json +126 -0
  8. package/dist/starter/codegen.ts +11 -11
  9. package/dist/starter/components.json +27 -27
  10. package/dist/starter/package.json +86 -80
  11. package/dist/starter/public/mockServiceWorker.js +261 -261
  12. package/dist/starter/scripts/build-component-db.ts +17 -20
  13. package/dist/starter/src/App.tsx +15 -17
  14. package/dist/starter/src/components/ui/Accordion.stories.tsx +35 -35
  15. package/dist/starter/src/components/ui/Accordion.tsx +33 -33
  16. package/dist/starter/src/components/ui/Alert.stories.tsx +15 -15
  17. package/dist/starter/src/components/ui/Alert.tsx +32 -32
  18. package/dist/starter/src/components/ui/AlertDialog.stories.tsx +50 -50
  19. package/dist/starter/src/components/ui/AlertDialog.tsx +114 -115
  20. package/dist/starter/src/components/ui/AspectRatio.stories.tsx +20 -20
  21. package/dist/starter/src/components/ui/AspectRatio.tsx +1 -1
  22. package/dist/starter/src/components/ui/Avatar.stories.tsx +27 -27
  23. package/dist/starter/src/components/ui/Avatar.tsx +63 -63
  24. package/dist/starter/src/components/ui/Badge.stories.tsx +14 -14
  25. package/dist/starter/src/components/ui/Badge.tsx +27 -27
  26. package/dist/starter/src/components/ui/Breadcrumb.stories.tsx +38 -38
  27. package/dist/starter/src/components/ui/Breadcrumb.tsx +63 -62
  28. package/dist/starter/src/components/ui/Button.stories.tsx +55 -55
  29. package/dist/starter/src/components/ui/Button.tsx +49 -49
  30. package/dist/starter/src/components/ui/ButtonGroup.stories.tsx +17 -17
  31. package/dist/starter/src/components/ui/ButtonGroup.tsx +52 -53
  32. package/dist/starter/src/components/ui/Calendar.stories.tsx +20 -19
  33. package/dist/starter/src/components/ui/Calendar.tsx +142 -143
  34. package/dist/starter/src/components/ui/Card.stories.tsx +29 -29
  35. package/dist/starter/src/components/ui/Card.tsx +31 -31
  36. package/dist/starter/src/components/ui/Carousel.stories.tsx +41 -41
  37. package/dist/starter/src/components/ui/Carousel.tsx +171 -172
  38. package/dist/starter/src/components/ui/Chart.stories.tsx +21 -21
  39. package/dist/starter/src/components/ui/Chart.tsx +244 -247
  40. package/dist/starter/src/components/ui/Checkbox.stories.tsx +11 -11
  41. package/dist/starter/src/components/ui/Checkbox.tsx +18 -18
  42. package/dist/starter/src/components/ui/Collapsible.stories.tsx +40 -40
  43. package/dist/starter/src/components/ui/Collapsible.tsx +3 -3
  44. package/dist/starter/src/components/ui/Combobox.stories.tsx +48 -48
  45. package/dist/starter/src/components/ui/Combobox.tsx +204 -205
  46. package/dist/starter/src/components/ui/Command.stories.tsx +55 -55
  47. package/dist/starter/src/components/ui/Command.tsx +102 -103
  48. package/dist/starter/src/components/ui/ContextMenu.stories.tsx +52 -52
  49. package/dist/starter/src/components/ui/ContextMenu.tsx +151 -151
  50. package/dist/starter/src/components/ui/DesignSystem-Colors.stories.tsx +92 -92
  51. package/dist/starter/src/components/ui/DesignSystem-Layout.stories.tsx +139 -139
  52. package/dist/starter/src/components/ui/DesignSystem-Overview.stories.tsx +676 -657
  53. package/dist/starter/src/components/ui/DesignSystem-Typography.stories.tsx +59 -59
  54. package/dist/starter/src/components/ui/Dialog.stories.tsx +56 -56
  55. package/dist/starter/src/components/ui/Dialog.tsx +97 -98
  56. package/dist/starter/src/components/ui/Direction.stories.tsx +20 -20
  57. package/dist/starter/src/components/ui/Direction.tsx +7 -7
  58. package/dist/starter/src/components/ui/Drawer.stories.tsx +54 -54
  59. package/dist/starter/src/components/ui/Drawer.tsx +70 -70
  60. package/dist/starter/src/components/ui/DropdownMenu.stories.tsx +58 -58
  61. package/dist/starter/src/components/ui/DropdownMenu.tsx +157 -157
  62. package/dist/starter/src/components/ui/Empty.stories.tsx +22 -22
  63. package/dist/starter/src/components/ui/Empty.tsx +58 -58
  64. package/dist/starter/src/components/ui/Field.stories.tsx +31 -31
  65. package/dist/starter/src/components/ui/Field.tsx +180 -181
  66. package/dist/starter/src/components/ui/Form.stories.tsx +29 -29
  67. package/dist/starter/src/components/ui/Form.tsx +93 -96
  68. package/dist/starter/src/components/ui/HoverCard.stories.tsx +34 -34
  69. package/dist/starter/src/components/ui/HoverCard.tsx +21 -21
  70. package/dist/starter/src/components/ui/Input.stories.tsx +18 -18
  71. package/dist/starter/src/components/ui/Input.tsx +14 -14
  72. package/dist/starter/src/components/ui/InputGroup.stories.tsx +34 -34
  73. package/dist/starter/src/components/ui/InputGroup.tsx +110 -111
  74. package/dist/starter/src/components/ui/InputOTP.stories.tsx +28 -28
  75. package/dist/starter/src/components/ui/InputOTP.tsx +43 -43
  76. package/dist/starter/src/components/ui/Item.stories.tsx +45 -45
  77. package/dist/starter/src/components/ui/Item.tsx +113 -114
  78. package/dist/starter/src/components/ui/Kbd.stories.tsx +31 -31
  79. package/dist/starter/src/components/ui/Kbd.tsx +11 -11
  80. package/dist/starter/src/components/ui/Label.stories.tsx +62 -62
  81. package/dist/starter/src/components/ui/Label.tsx +26 -25
  82. package/dist/starter/src/components/ui/Menubar.stories.tsx +62 -62
  83. package/dist/starter/src/components/ui/Menubar.tsx +173 -173
  84. package/dist/starter/src/components/ui/NativeSelect.stories.tsx +26 -26
  85. package/dist/starter/src/components/ui/NativeSelect.tsx +29 -29
  86. package/dist/starter/src/components/ui/NavigationMenu.stories.tsx +64 -64
  87. package/dist/starter/src/components/ui/NavigationMenu.tsx +103 -103
  88. package/dist/starter/src/components/ui/Pagination.stories.tsx +61 -61
  89. package/dist/starter/src/components/ui/Pagination.tsx +69 -71
  90. package/dist/starter/src/components/ui/Popover.stories.tsx +38 -38
  91. package/dist/starter/src/components/ui/Popover.tsx +25 -25
  92. package/dist/starter/src/components/ui/Progress.stories.tsx +9 -9
  93. package/dist/starter/src/components/ui/Progress.tsx +14 -14
  94. package/dist/starter/src/components/ui/RadioGroup.stories.tsx +35 -35
  95. package/dist/starter/src/components/ui/RadioGroup.tsx +19 -19
  96. package/dist/starter/src/components/ui/Resizable.stories.tsx +54 -54
  97. package/dist/starter/src/components/ui/Resizable.tsx +29 -29
  98. package/dist/starter/src/components/ui/ScrollArea.stories.tsx +27 -27
  99. package/dist/starter/src/components/ui/ScrollArea.tsx +34 -34
  100. package/dist/starter/src/components/ui/Select.stories.tsx +43 -43
  101. package/dist/starter/src/components/ui/Select.tsx +120 -120
  102. package/dist/starter/src/components/ui/Separator.stories.tsx +27 -27
  103. package/dist/starter/src/components/ui/Separator.tsx +17 -17
  104. package/dist/starter/src/components/ui/Sheet.stories.tsx +53 -53
  105. package/dist/starter/src/components/ui/Sheet.tsx +69 -69
  106. package/dist/starter/src/components/ui/Sidebar.stories.tsx +77 -77
  107. package/dist/starter/src/components/ui/Sidebar.tsx +563 -564
  108. package/dist/starter/src/components/ui/Skeleton.stories.tsx +25 -25
  109. package/dist/starter/src/components/ui/Skeleton.tsx +1 -1
  110. package/dist/starter/src/components/ui/Slider.stories.tsx +5 -5
  111. package/dist/starter/src/components/ui/Slider.tsx +45 -44
  112. package/dist/starter/src/components/ui/Sonner.stories.tsx +32 -32
  113. package/dist/starter/src/components/ui/Sonner.tsx +23 -23
  114. package/dist/starter/src/components/ui/Spinner.stories.tsx +8 -8
  115. package/dist/starter/src/components/ui/Spinner.tsx +1 -1
  116. package/dist/starter/src/components/ui/Switch.stories.tsx +16 -17
  117. package/dist/starter/src/components/ui/Switch.tsx +24 -24
  118. package/dist/starter/src/components/ui/Table.stories.tsx +50 -50
  119. package/dist/starter/src/components/ui/Table.tsx +45 -45
  120. package/dist/starter/src/components/ui/Tabs.stories.tsx +39 -39
  121. package/dist/starter/src/components/ui/Tabs.tsx +47 -47
  122. package/dist/starter/src/components/ui/Textarea.stories.tsx +9 -9
  123. package/dist/starter/src/components/ui/Textarea.tsx +11 -11
  124. package/dist/starter/src/components/ui/Toast.stories.tsx +77 -77
  125. package/dist/starter/src/components/ui/Toast.tsx +75 -75
  126. package/dist/starter/src/components/ui/Toaster.tsx +17 -19
  127. package/dist/starter/src/components/ui/Toggle.stories.tsx +20 -20
  128. package/dist/starter/src/components/ui/Toggle.tsx +26 -26
  129. package/dist/starter/src/components/ui/ToggleGroup.stories.tsx +41 -41
  130. package/dist/starter/src/components/ui/ToggleGroup.tsx +61 -62
  131. package/dist/starter/src/components/ui/Tooltip.stories.tsx +26 -26
  132. package/dist/starter/src/components/ui/Tooltip.tsx +24 -24
  133. package/dist/starter/src/gql/execute.ts +1 -1
  134. package/dist/starter/src/gql/fragment-masking.ts +1 -1
  135. package/dist/starter/src/gql/graphql.ts +3 -0
  136. package/dist/starter/src/hooks/use-mobile.ts +11 -11
  137. package/dist/starter/src/hooks/use-toast.ts +135 -135
  138. package/dist/starter/src/index.css +105 -105
  139. package/dist/starter/src/lib/utils.ts +1 -1
  140. package/dist/starter/src/main.tsx +4 -1
  141. package/dist/starter/tsconfig.app.json +24 -24
  142. package/dist/starter/tsconfig.json +8 -8
  143. package/dist/starter/vite.config.ts +38 -37
  144. package/package.json +3 -3
@@ -1,168 +1,167 @@
1
- import * as React from 'react';
2
1
  import { cva, type VariantProps } from 'class-variance-authority';
3
2
  import { Slot } from 'radix-ui';
4
-
5
- import { cn } from '@/lib/utils';
3
+ import type * as React from 'react';
6
4
  import { Separator } from '@/components/ui/Separator';
5
+ import { cn } from '@/lib/utils';
7
6
 
8
7
  /** Container for a list of Item components. Provides list semantics for accessibility. */
9
8
  function ItemGroup({ className, ...props }: React.ComponentProps<'div'>) {
10
- return (
11
- <div role="list" data-slot="item-group" className={cn('group/item-group flex flex-col', className)} {...props} />
12
- );
9
+ return (
10
+ <div role="list" data-slot="item-group" className={cn('group/item-group flex flex-col', className)} {...props} />
11
+ );
13
12
  }
14
13
 
15
14
  /** Horizontal divider between items in an ItemGroup. */
16
15
  function ItemSeparator({ className, ...props }: React.ComponentProps<typeof Separator>) {
17
- return <Separator data-slot="item-separator" orientation="horizontal" className={cn('my-0', className)} {...props} />;
16
+ return <Separator data-slot="item-separator" orientation="horizontal" className={cn('my-0', className)} {...props} />;
18
17
  }
19
18
 
20
19
  const itemVariants = cva(
21
- 'group/item flex items-center border border-transparent text-sm rounded-md transition-colors [a]:hover:bg-accent/50 [a]:transition-colors duration-100 flex-wrap outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
22
- {
23
- variants: {
24
- variant: {
25
- default: 'bg-transparent',
26
- outline: 'border-border',
27
- muted: 'bg-muted/50',
28
- },
29
- size: {
30
- default: 'p-4 gap-4 ',
31
- sm: 'py-3 px-4 gap-2.5',
32
- },
33
- },
34
- defaultVariants: {
35
- variant: 'default',
36
- size: 'default',
37
- },
38
- },
20
+ 'group/item flex items-center border border-transparent text-sm rounded-md transition-colors [a]:hover:bg-accent/50 [a]:transition-colors duration-100 flex-wrap outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
21
+ {
22
+ variants: {
23
+ variant: {
24
+ default: 'bg-transparent',
25
+ outline: 'border-border',
26
+ muted: 'bg-muted/50',
27
+ },
28
+ size: {
29
+ default: 'p-4 gap-4 ',
30
+ sm: 'py-3 px-4 gap-2.5',
31
+ },
32
+ },
33
+ defaultVariants: {
34
+ variant: 'default',
35
+ size: 'default',
36
+ },
37
+ },
39
38
  );
40
39
 
41
40
  /** A flexible list item for displaying structured content like notifications, settings rows, or search results. Compose with ItemMedia, ItemContent, ItemTitle, ItemDescription, and ItemActions. */
42
41
  function Item({
43
- className,
44
- variant = 'default',
45
- size = 'default',
46
- asChild = false,
47
- ...props
42
+ className,
43
+ variant = 'default',
44
+ size = 'default',
45
+ asChild = false,
46
+ ...props
48
47
  }: React.ComponentProps<'div'> & VariantProps<typeof itemVariants> & { asChild?: boolean }) {
49
- const Comp = asChild ? Slot.Root : 'div';
50
- return (
51
- <Comp
52
- data-slot="item"
53
- data-variant={variant}
54
- data-size={size}
55
- className={cn(itemVariants({ variant, size, className }))}
56
- {...props}
57
- />
58
- );
48
+ const Comp = asChild ? Slot.Root : 'div';
49
+ return (
50
+ <Comp
51
+ data-slot="item"
52
+ data-variant={variant}
53
+ data-size={size}
54
+ className={cn(itemVariants({ variant, size, className }))}
55
+ {...props}
56
+ />
57
+ );
59
58
  }
60
59
 
61
60
  const itemMediaVariants = cva(
62
- 'flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5',
63
- {
64
- variants: {
65
- variant: {
66
- default: 'bg-transparent',
67
- icon: "size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4",
68
- image: 'size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover',
69
- },
70
- },
71
- defaultVariants: {
72
- variant: 'default',
73
- },
74
- },
61
+ 'flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5',
62
+ {
63
+ variants: {
64
+ variant: {
65
+ default: 'bg-transparent',
66
+ icon: "size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4",
67
+ image: 'size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover',
68
+ },
69
+ },
70
+ defaultVariants: {
71
+ variant: 'default',
72
+ },
73
+ },
75
74
  );
76
75
 
77
76
  /** Container for an icon, avatar, or image at the start of an Item. Use variant="icon" for styled icon backgrounds or variant="image" for thumbnails. */
78
77
  function ItemMedia({
79
- className,
80
- variant = 'default',
81
- ...props
78
+ className,
79
+ variant = 'default',
80
+ ...props
82
81
  }: React.ComponentProps<'div'> & VariantProps<typeof itemMediaVariants>) {
83
- return (
84
- <div
85
- data-slot="item-media"
86
- data-variant={variant}
87
- className={cn(itemMediaVariants({ variant, className }))}
88
- {...props}
89
- />
90
- );
82
+ return (
83
+ <div
84
+ data-slot="item-media"
85
+ data-variant={variant}
86
+ className={cn(itemMediaVariants({ variant, className }))}
87
+ {...props}
88
+ />
89
+ );
91
90
  }
92
91
 
93
92
  /** Main content area of an Item, containing title and description. */
94
93
  function ItemContent({ className, ...props }: React.ComponentProps<'div'>) {
95
- return (
96
- <div
97
- data-slot="item-content"
98
- className={cn('flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none', className)}
99
- {...props}
100
- />
101
- );
94
+ return (
95
+ <div
96
+ data-slot="item-content"
97
+ className={cn('flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none', className)}
98
+ {...props}
99
+ />
100
+ );
102
101
  }
103
102
 
104
103
  /** Primary text label for an Item. */
105
104
  function ItemTitle({ className, ...props }: React.ComponentProps<'div'>) {
106
- return (
107
- <div
108
- data-slot="item-title"
109
- className={cn('flex w-fit items-center gap-2 text-sm leading-snug font-medium', className)}
110
- {...props}
111
- />
112
- );
105
+ return (
106
+ <div
107
+ data-slot="item-title"
108
+ className={cn('flex w-fit items-center gap-2 text-sm leading-snug font-medium', className)}
109
+ {...props}
110
+ />
111
+ );
113
112
  }
114
113
 
115
114
  /** Secondary text below the title, limited to 2 lines. */
116
115
  function ItemDescription({ className, ...props }: React.ComponentProps<'p'>) {
117
- return (
118
- <p
119
- data-slot="item-description"
120
- className={cn(
121
- 'text-muted-foreground line-clamp-2 text-sm leading-normal font-normal text-balance',
122
- '[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
123
- className,
124
- )}
125
- {...props}
126
- />
127
- );
116
+ return (
117
+ <p
118
+ data-slot="item-description"
119
+ className={cn(
120
+ 'text-muted-foreground line-clamp-2 text-sm leading-normal font-normal text-balance',
121
+ '[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
122
+ className,
123
+ )}
124
+ {...props}
125
+ />
126
+ );
128
127
  }
129
128
 
130
129
  /** Container for action buttons at the end of an Item. */
131
130
  function ItemActions({ className, ...props }: React.ComponentProps<'div'>) {
132
- return <div data-slot="item-actions" className={cn('flex items-center gap-2', className)} {...props} />;
131
+ return <div data-slot="item-actions" className={cn('flex items-center gap-2', className)} {...props} />;
133
132
  }
134
133
 
135
134
  /** Full-width header row spanning the top of an Item, with space-between layout. */
136
135
  function ItemHeader({ className, ...props }: React.ComponentProps<'div'>) {
137
- return (
138
- <div
139
- data-slot="item-header"
140
- className={cn('flex basis-full items-center justify-between gap-2', className)}
141
- {...props}
142
- />
143
- );
136
+ return (
137
+ <div
138
+ data-slot="item-header"
139
+ className={cn('flex basis-full items-center justify-between gap-2', className)}
140
+ {...props}
141
+ />
142
+ );
144
143
  }
145
144
 
146
145
  /** Full-width footer row spanning the bottom of an Item, with space-between layout. */
147
146
  function ItemFooter({ className, ...props }: React.ComponentProps<'div'>) {
148
- return (
149
- <div
150
- data-slot="item-footer"
151
- className={cn('flex basis-full items-center justify-between gap-2', className)}
152
- {...props}
153
- />
154
- );
147
+ return (
148
+ <div
149
+ data-slot="item-footer"
150
+ className={cn('flex basis-full items-center justify-between gap-2', className)}
151
+ {...props}
152
+ />
153
+ );
155
154
  }
156
155
 
157
156
  export {
158
- Item,
159
- ItemMedia,
160
- ItemContent,
161
- ItemActions,
162
- ItemGroup,
163
- ItemSeparator,
164
- ItemTitle,
165
- ItemDescription,
166
- ItemHeader,
167
- ItemFooter,
157
+ Item,
158
+ ItemMedia,
159
+ ItemContent,
160
+ ItemActions,
161
+ ItemGroup,
162
+ ItemSeparator,
163
+ ItemTitle,
164
+ ItemDescription,
165
+ ItemHeader,
166
+ ItemFooter,
168
167
  };
@@ -2,12 +2,12 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import { Kbd } from './Kbd';
3
3
 
4
4
  const meta: Meta<typeof Kbd> = {
5
- title: 'UI Components/Kbd',
6
- component: Kbd,
7
- parameters: {
8
- layout: 'centered',
9
- },
10
- tags: ['autodocs'],
5
+ title: 'UI Components/Kbd',
6
+ component: Kbd,
7
+ parameters: {
8
+ layout: 'centered',
9
+ },
10
+ tags: ['autodocs'],
11
11
  };
12
12
 
13
13
  export default meta;
@@ -15,45 +15,45 @@ type Story = StoryObj<typeof meta>;
15
15
 
16
16
  /** Shows a single keyboard key shortcut. */
17
17
  export const Default: Story = {
18
- args: {
19
- children: '⌘K',
20
- },
18
+ args: {
19
+ children: '⌘K',
20
+ },
21
21
  };
22
22
 
23
23
  /** Shows a key with a text label like "Ctrl". */
24
24
  export const WithText: Story = {
25
- args: {
26
- children: 'Ctrl',
27
- },
25
+ args: {
26
+ children: 'Ctrl',
27
+ },
28
28
  };
29
29
 
30
30
  /** Shows a key with an arrow symbol. */
31
31
  export const ArrowKeys: Story = {
32
- args: {
33
- children: '→',
34
- },
32
+ args: {
33
+ children: '→',
34
+ },
35
35
  };
36
36
 
37
37
  /** Shows two keys composed together to represent a shortcut combination. */
38
38
  export const Multiple: Story = {
39
- render: () => (
40
- <div className="flex gap-2 items-center">
41
- <Kbd>⌘</Kbd>
42
- <span>+</span>
43
- <Kbd>K</Kbd>
44
- </div>
45
- ),
39
+ render: () => (
40
+ <div className="flex gap-2 items-center">
41
+ <Kbd>⌘</Kbd>
42
+ <span>+</span>
43
+ <Kbd>K</Kbd>
44
+ </div>
45
+ ),
46
46
  };
47
47
 
48
48
  /** Shows a three-key combination shortcut. */
49
49
  export const Combination: Story = {
50
- render: () => (
51
- <div className="flex gap-2 items-center">
52
- <Kbd>Ctrl</Kbd>
53
- <span>+</span>
54
- <Kbd>Shift</Kbd>
55
- <span>+</span>
56
- <Kbd>P</Kbd>
57
- </div>
58
- ),
50
+ render: () => (
51
+ <div className="flex gap-2 items-center">
52
+ <Kbd>Ctrl</Kbd>
53
+ <span>+</span>
54
+ <Kbd>Shift</Kbd>
55
+ <span>+</span>
56
+ <Kbd>P</Kbd>
57
+ </div>
58
+ ),
59
59
  };
@@ -1,9 +1,9 @@
1
- import React from 'react';
1
+ import type React from 'react';
2
2
  import { cn } from '@/lib/utils';
3
3
 
4
4
  interface KbdProps {
5
- children: React.ReactNode;
6
- className?: string;
5
+ children: React.ReactNode;
6
+ className?: string;
7
7
  }
8
8
 
9
9
  /**
@@ -11,12 +11,12 @@ interface KbdProps {
11
11
  * Use to display keyboard shortcuts or key combinations in documentation and UI hints.
12
12
  */
13
13
  export function Kbd({ children, className }: KbdProps) {
14
- return (
15
- <kbd
16
- data-slot="kbd"
17
- className={cn('border border-border rounded bg-muted px-1.5 py-0.5 text-xs font-medium', className)}
18
- >
19
- {children}
20
- </kbd>
21
- );
14
+ return (
15
+ <kbd
16
+ data-slot="kbd"
17
+ className={cn('border border-border rounded bg-muted px-1.5 py-0.5 text-xs font-medium', className)}
18
+ >
19
+ {children}
20
+ </kbd>
21
+ );
22
22
  }
@@ -2,27 +2,27 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import { Label } from './Label';
3
3
 
4
4
  const meta: Meta<typeof Label> = {
5
- title: 'UI Components/Label',
6
- component: Label,
7
- parameters: {
8
- layout: 'centered',
9
- },
10
- tags: ['autodocs'],
11
- argTypes: {
12
- variant: {
13
- control: { type: 'radio' },
14
- options: ['default', 'required'],
15
- },
16
- required: {
17
- control: { type: 'boolean' },
18
- },
19
- htmlFor: {
20
- control: { type: 'text' },
21
- },
22
- children: {
23
- control: { type: 'text' },
24
- },
25
- },
5
+ title: 'UI Components/Label',
6
+ component: Label,
7
+ parameters: {
8
+ layout: 'centered',
9
+ },
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ variant: {
13
+ control: { type: 'radio' },
14
+ options: ['default', 'required'],
15
+ },
16
+ required: {
17
+ control: { type: 'boolean' },
18
+ },
19
+ htmlFor: {
20
+ control: { type: 'text' },
21
+ },
22
+ children: {
23
+ control: { type: 'text' },
24
+ },
25
+ },
26
26
  };
27
27
 
28
28
  export default meta;
@@ -30,61 +30,61 @@ type Story = StoryObj<typeof meta>;
30
30
 
31
31
  /** Shows a basic label associated with a form field. */
32
32
  export const Default: Story = {
33
- args: {
34
- children: 'Email address',
35
- htmlFor: 'email',
36
- },
33
+ args: {
34
+ children: 'Email address',
35
+ htmlFor: 'email',
36
+ },
37
37
  };
38
38
 
39
39
  /** Shows the label with the required prop, which appends a red asterisk. */
40
40
  export const Required: Story = {
41
- args: {
42
- children: 'Email address',
43
- htmlFor: 'email',
44
- required: true,
45
- },
41
+ args: {
42
+ children: 'Email address',
43
+ htmlFor: 'email',
44
+ required: true,
45
+ },
46
46
  };
47
47
 
48
48
  /** Shows the label using the "required" variant prop directly. */
49
49
  export const RequiredVariant: Story = {
50
- args: {
51
- children: 'Email address',
52
- htmlFor: 'email',
53
- variant: 'required',
54
- },
50
+ args: {
51
+ children: 'Email address',
52
+ htmlFor: 'email',
53
+ variant: 'required',
54
+ },
55
55
  };
56
56
 
57
57
  /** Shows the label paired with a text input in a form layout. */
58
58
  export const WithForm: Story = {
59
- render: (args) => (
60
- <div className="space-y-2">
61
- <Label htmlFor="example-input" required>
62
- Example Field
63
- </Label>
64
- <input
65
- id="example-input"
66
- type="text"
67
- className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
68
- placeholder="Enter value..."
69
- />
70
- </div>
71
- ),
59
+ render: (_args) => (
60
+ <div className="space-y-2">
61
+ <Label htmlFor="example-input" required>
62
+ Example Field
63
+ </Label>
64
+ <input
65
+ id="example-input"
66
+ type="text"
67
+ className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
68
+ placeholder="Enter value..."
69
+ />
70
+ </div>
71
+ ),
72
72
  };
73
73
 
74
74
  /** Demonstrates the dimmed appearance when the associated input is disabled. */
75
75
  export const DisabledField: Story = {
76
- render: (args) => (
77
- <div className="space-y-2">
78
- <Label htmlFor="disabled-input" required>
79
- Disabled Field
80
- </Label>
81
- <input
82
- id="disabled-input"
83
- type="text"
84
- disabled
85
- className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
86
- placeholder="Disabled input..."
87
- />
88
- </div>
89
- ),
76
+ render: (_args) => (
77
+ <div className="space-y-2">
78
+ <Label htmlFor="disabled-input" required>
79
+ Disabled Field
80
+ </Label>
81
+ <input
82
+ id="disabled-input"
83
+ type="text"
84
+ disabled
85
+ className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
86
+ placeholder="Disabled input..."
87
+ />
88
+ </div>
89
+ ),
90
90
  };
@@ -1,26 +1,26 @@
1
- import * as React from 'react';
2
1
  import { cva, type VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
3
  import { cn } from '@/lib/utils';
4
4
 
5
5
  const labelVariants = cva(
6
- 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
7
- {
8
- variants: {
9
- variant: {
10
- default: 'text-foreground',
11
- required: "text-foreground after:content-['*'] after:ml-1 after:text-destructive",
12
- },
13
- },
14
- defaultVariants: {
15
- variant: 'default',
16
- },
17
- },
6
+ 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: 'text-foreground',
11
+ required: "text-foreground after:content-['*'] after:ml-1 after:text-destructive",
12
+ },
13
+ },
14
+ defaultVariants: {
15
+ variant: 'default',
16
+ },
17
+ },
18
18
  );
19
19
 
20
20
  export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement>, VariantProps<typeof labelVariants> {
21
- htmlFor?: string;
22
- required?: boolean;
23
- children?: React.ReactNode;
21
+ htmlFor?: string;
22
+ required?: boolean;
23
+ children?: React.ReactNode;
24
24
  }
25
25
 
26
26
  /**
@@ -28,16 +28,17 @@ export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement>,
28
28
  * Supports a "required" variant that appends a red asterisk, and automatically dims when its peer input is disabled.
29
29
  */
30
30
  const Label = React.forwardRef<HTMLLabelElement, LabelProps>(({ className, variant, required, ...props }, ref) => {
31
- const effectiveVariant = required ? 'required' : variant || 'default';
31
+ const effectiveVariant = required ? 'required' : variant || 'default';
32
32
 
33
- return (
34
- <label
35
- ref={ref}
36
- data-slot="label"
37
- className={cn(labelVariants({ variant: effectiveVariant }), className)}
38
- {...props}
39
- />
40
- );
33
+ return (
34
+ // biome-ignore lint/a11y/noLabelWithoutControl: Label is a generic component - htmlFor is provided by consumers
35
+ <label
36
+ ref={ref}
37
+ data-slot="label"
38
+ className={cn(labelVariants({ variant: effectiveVariant }), className)}
39
+ {...props}
40
+ />
41
+ );
41
42
  });
42
43
  Label.displayName = 'Label';
43
44