@auto-engineer/generate-react-client 1.34.0 → 1.36.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 (119) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/starter/package.json +2 -1
  3. package/dist/starter/scripts/build-component-db.ts +157 -0
  4. package/dist/starter/src/components/ui/Accordion.stories.tsx +2 -0
  5. package/dist/starter/src/components/ui/Accordion.tsx +4 -0
  6. package/dist/starter/src/components/ui/Alert.stories.tsx +2 -0
  7. package/dist/starter/src/components/ui/Alert.tsx +7 -0
  8. package/dist/starter/src/components/ui/AlertDialog.stories.tsx +2 -0
  9. package/dist/starter/src/components/ui/AlertDialog.tsx +15 -0
  10. package/dist/starter/src/components/ui/AspectRatio.stories.tsx +2 -0
  11. package/dist/starter/src/components/ui/AspectRatio.tsx +4 -0
  12. package/dist/starter/src/components/ui/Avatar.stories.tsx +3 -0
  13. package/dist/starter/src/components/ui/Avatar.tsx +11 -0
  14. package/dist/starter/src/components/ui/Badge.stories.tsx +5 -0
  15. package/dist/starter/src/components/ui/Badge.tsx +5 -0
  16. package/dist/starter/src/components/ui/Breadcrumb.stories.tsx +2 -0
  17. package/dist/starter/src/components/ui/Breadcrumb.tsx +12 -0
  18. package/dist/starter/src/components/ui/Button.stories.tsx +10 -0
  19. package/dist/starter/src/components/ui/Button.tsx +5 -0
  20. package/dist/starter/src/components/ui/ButtonGroup.stories.tsx +2 -0
  21. package/dist/starter/src/components/ui/ButtonGroup.tsx +6 -0
  22. package/dist/starter/src/components/ui/Calendar.stories.tsx +2 -0
  23. package/dist/starter/src/components/ui/Calendar.tsx +6 -0
  24. package/dist/starter/src/components/ui/Card.stories.tsx +2 -0
  25. package/dist/starter/src/components/ui/Card.tsx +10 -0
  26. package/dist/starter/src/components/ui/Carousel.stories.tsx +2 -0
  27. package/dist/starter/src/components/ui/Carousel.tsx +9 -0
  28. package/dist/starter/src/components/ui/Chart.stories.tsx +1 -0
  29. package/dist/starter/src/components/ui/Chart.tsx +9 -0
  30. package/dist/starter/src/components/ui/Checkbox.stories.tsx +4 -0
  31. package/dist/starter/src/components/ui/Checkbox.tsx +1 -0
  32. package/dist/starter/src/components/ui/Collapsible.stories.tsx +2 -0
  33. package/dist/starter/src/components/ui/Collapsible.tsx +3 -0
  34. package/dist/starter/src/components/ui/Combobox.stories.tsx +2 -0
  35. package/dist/starter/src/components/ui/Combobox.tsx +29 -0
  36. package/dist/starter/src/components/ui/Command.stories.tsx +2 -0
  37. package/dist/starter/src/components/ui/Command.tsx +20 -0
  38. package/dist/starter/src/components/ui/ContextMenu.stories.tsx +2 -0
  39. package/dist/starter/src/components/ui/ContextMenu.tsx +20 -0
  40. package/dist/starter/src/components/ui/Dialog.stories.tsx +2 -0
  41. package/dist/starter/src/components/ui/Dialog.tsx +18 -0
  42. package/dist/starter/src/components/ui/Direction.stories.tsx +2 -0
  43. package/dist/starter/src/components/ui/Direction.tsx +6 -0
  44. package/dist/starter/src/components/ui/Drawer.stories.tsx +2 -0
  45. package/dist/starter/src/components/ui/Drawer.tsx +18 -0
  46. package/dist/starter/src/components/ui/DropdownMenu.stories.tsx +2 -0
  47. package/dist/starter/src/components/ui/DropdownMenu.tsx +20 -0
  48. package/dist/starter/src/components/ui/Empty.stories.tsx +2 -0
  49. package/dist/starter/src/components/ui/Empty.tsx +13 -0
  50. package/dist/starter/src/components/ui/Field.stories.tsx +3 -0
  51. package/dist/starter/src/components/ui/Field.tsx +25 -0
  52. package/dist/starter/src/components/ui/Form.stories.tsx +1 -0
  53. package/dist/starter/src/components/ui/Form.tsx +15 -3
  54. package/dist/starter/src/components/ui/HoverCard.stories.tsx +2 -0
  55. package/dist/starter/src/components/ui/HoverCard.tsx +3 -0
  56. package/dist/starter/src/components/ui/Input.stories.tsx +4 -0
  57. package/dist/starter/src/components/ui/Input.tsx +1 -0
  58. package/dist/starter/src/components/ui/InputGroup.stories.tsx +3 -0
  59. package/dist/starter/src/components/ui/InputGroup.tsx +6 -0
  60. package/dist/starter/src/components/ui/InputOTP.stories.tsx +2 -0
  61. package/dist/starter/src/components/ui/InputOTP.tsx +4 -0
  62. package/dist/starter/src/components/ui/Item.stories.tsx +3 -0
  63. package/dist/starter/src/components/ui/Item.tsx +10 -0
  64. package/dist/starter/src/components/ui/Kbd.stories.tsx +5 -0
  65. package/dist/starter/src/components/ui/Kbd.tsx +4 -0
  66. package/dist/starter/src/components/ui/Label.stories.tsx +5 -0
  67. package/dist/starter/src/components/ui/Label.tsx +4 -0
  68. package/dist/starter/src/components/ui/Menubar.stories.tsx +2 -0
  69. package/dist/starter/src/components/ui/Menubar.tsx +15 -0
  70. package/dist/starter/src/components/ui/NativeSelect.stories.tsx +3 -0
  71. package/dist/starter/src/components/ui/NativeSelect.tsx +6 -0
  72. package/dist/starter/src/components/ui/NavigationMenu.stories.tsx +2 -0
  73. package/dist/starter/src/components/ui/NavigationMenu.tsx +10 -0
  74. package/dist/starter/src/components/ui/Pagination.stories.tsx +2 -0
  75. package/dist/starter/src/components/ui/Pagination.tsx +8 -0
  76. package/dist/starter/src/components/ui/Popover.stories.tsx +2 -0
  77. package/dist/starter/src/components/ui/Popover.tsx +5 -0
  78. package/dist/starter/src/components/ui/Progress.stories.tsx +4 -0
  79. package/dist/starter/src/components/ui/Progress.tsx +1 -0
  80. package/dist/starter/src/components/ui/RadioGroup.stories.tsx +2 -0
  81. package/dist/starter/src/components/ui/RadioGroup.tsx +5 -0
  82. package/dist/starter/src/components/ui/Resizable.stories.tsx +3 -0
  83. package/dist/starter/src/components/ui/Resizable.tsx +7 -0
  84. package/dist/starter/src/components/ui/ScrollArea.stories.tsx +2 -0
  85. package/dist/starter/src/components/ui/ScrollArea.tsx +5 -0
  86. package/dist/starter/src/components/ui/Select.stories.tsx +2 -0
  87. package/dist/starter/src/components/ui/Select.tsx +9 -0
  88. package/dist/starter/src/components/ui/Separator.stories.tsx +2 -0
  89. package/dist/starter/src/components/ui/Separator.tsx +1 -0
  90. package/dist/starter/src/components/ui/Sheet.stories.tsx +2 -0
  91. package/dist/starter/src/components/ui/Sheet.tsx +8 -0
  92. package/dist/starter/src/components/ui/Sidebar.stories.tsx +2 -0
  93. package/dist/starter/src/components/ui/Sidebar.tsx +20 -0
  94. package/dist/starter/src/components/ui/Skeleton.stories.tsx +2 -0
  95. package/dist/starter/src/components/ui/Skeleton.tsx +4 -0
  96. package/dist/starter/src/components/ui/Slider.stories.tsx +3 -0
  97. package/dist/starter/src/components/ui/Slider.tsx +1 -0
  98. package/dist/starter/src/components/ui/Sonner.stories.tsx +1 -0
  99. package/dist/starter/src/components/ui/Sonner.tsx +4 -0
  100. package/dist/starter/src/components/ui/Spinner.stories.tsx +3 -0
  101. package/dist/starter/src/components/ui/Spinner.tsx +4 -0
  102. package/dist/starter/src/components/ui/Switch.stories.tsx +4 -0
  103. package/dist/starter/src/components/ui/Switch.tsx +2 -0
  104. package/dist/starter/src/components/ui/Table.stories.tsx +2 -0
  105. package/dist/starter/src/components/ui/Table.tsx +11 -0
  106. package/dist/starter/src/components/ui/Tabs.stories.tsx +2 -0
  107. package/dist/starter/src/components/ui/Tabs.tsx +6 -0
  108. package/dist/starter/src/components/ui/Textarea.stories.tsx +3 -0
  109. package/dist/starter/src/components/ui/Textarea.tsx +4 -0
  110. package/dist/starter/src/components/ui/Toast.stories.tsx +4 -0
  111. package/dist/starter/src/components/ui/Toast.tsx +9 -0
  112. package/dist/starter/src/components/ui/Toaster.tsx +4 -0
  113. package/dist/starter/src/components/ui/Toggle.stories.tsx +4 -0
  114. package/dist/starter/src/components/ui/Toggle.tsx +1 -0
  115. package/dist/starter/src/components/ui/ToggleGroup.stories.tsx +3 -0
  116. package/dist/starter/src/components/ui/ToggleGroup.tsx +3 -0
  117. package/dist/starter/src/components/ui/Tooltip.stories.tsx +2 -0
  118. package/dist/starter/src/components/ui/Tooltip.tsx +6 -0
  119. package/package.json +2 -2
@@ -14,7 +14,13 @@ import {
14
14
  import { cn } from '@/lib/utils';
15
15
  import { Label } from '@/components/ui/Label';
16
16
 
17
- const Form = FormProvider;
17
+ /**
18
+ * Form context provider that wraps react-hook-form's FormProvider.
19
+ * Use with FormField, FormItem, FormLabel, FormControl, FormDescription, and FormMessage for accessible form layouts with validation.
20
+ */
21
+ function Form({ ...props }: React.ComponentProps<typeof FormProvider>) {
22
+ return <FormProvider {...props} />;
23
+ }
18
24
 
19
25
  type FormFieldContextValue<
20
26
  TFieldValues extends FieldValues = FieldValues,
@@ -25,12 +31,13 @@ type FormFieldContextValue<
25
31
 
26
32
  const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);
27
33
 
28
- const FormField = <
34
+ /** Connects a form input to react-hook-form via Controller, providing field context to child components. */
35
+ function FormField<
29
36
  TFieldValues extends FieldValues = FieldValues,
30
37
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
31
38
  >({
32
39
  ...props
33
- }: ControllerProps<TFieldValues, TName>) => {
40
+ }: ControllerProps<TFieldValues, TName>) {
34
41
  return (
35
42
  <FormFieldContext.Provider value={{ name: props.name }}>
36
43
  <Controller {...props} />
@@ -67,6 +74,7 @@ type FormItemContextValue = {
67
74
 
68
75
  const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);
69
76
 
77
+ /** Container for a single form field that provides ID context for accessibility linking between label, input, description, and error message. */
70
78
  function FormItem({ className, ...props }: React.ComponentProps<'div'>) {
71
79
  const id = React.useId();
72
80
 
@@ -77,6 +85,7 @@ function FormItem({ className, ...props }: React.ComponentProps<'div'>) {
77
85
  );
78
86
  }
79
87
 
88
+ /** Label for a form field that automatically links to its input and displays error styling when validation fails. */
80
89
  function FormLabel({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {
81
90
  const { error, formItemId } = useFormField();
82
91
 
@@ -91,6 +100,7 @@ function FormLabel({ className, ...props }: React.ComponentProps<typeof LabelPri
91
100
  );
92
101
  }
93
102
 
103
+ /** Wrapper that merges accessibility attributes (id, aria-describedby, aria-invalid) onto the form input element. */
94
104
  function FormControl({ ...props }: React.ComponentProps<typeof Slot.Root>) {
95
105
  const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
96
106
 
@@ -105,6 +115,7 @@ function FormControl({ ...props }: React.ComponentProps<typeof Slot.Root>) {
105
115
  );
106
116
  }
107
117
 
118
+ /** Helper text displayed below a form input, linked via aria-describedby for screen readers. */
108
119
  function FormDescription({ className, ...props }: React.ComponentProps<'p'>) {
109
120
  const { formDescriptionId } = useFormField();
110
121
 
@@ -118,6 +129,7 @@ function FormDescription({ className, ...props }: React.ComponentProps<'p'>) {
118
129
  );
119
130
  }
120
131
 
132
+ /** Displays validation error messages for a form field. Automatically shows the field's error message or custom children. */
121
133
  function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {
122
134
  const { error, formMessageId } = useFormField();
123
135
  const body = error ? String(error?.message ?? '') : props.children;
@@ -9,6 +9,7 @@ const meta: Meta<typeof HoverCard> = {
9
9
  export default meta;
10
10
  type Story = StoryObj<typeof HoverCard>;
11
11
 
12
+ /** Shows a user profile preview card triggered by hovering over a username link. */
12
13
  export const Default: Story = {
13
14
  render: () => (
14
15
  <HoverCard>
@@ -33,6 +34,7 @@ export const Default: Story = {
33
34
  ),
34
35
  };
35
36
 
37
+ /** Minimal hover card with just text content. */
36
38
  export const Simple: Story = {
37
39
  render: () => (
38
40
  <HoverCard>
@@ -3,14 +3,17 @@ import { HoverCard as HoverCardPrimitive } from 'radix-ui';
3
3
 
4
4
  import { cn } from '@/lib/utils';
5
5
 
6
+ /** A popup card that appears when hovering over a trigger element. Ideal for previewing content like user profiles or link destinations. */
6
7
  function HoverCard({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
7
8
  return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />;
8
9
  }
9
10
 
11
+ /** Element that activates the hover card on mouse enter. */
10
12
  function HoverCardTrigger({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
11
13
  return <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />;
12
14
  }
13
15
 
16
+ /** The popup content that appears when hovering. Portals to body and animates in/out. */
14
17
  function HoverCardContent({
15
18
  className,
16
19
  align = 'center',
@@ -9,10 +9,12 @@ const meta: Meta<typeof Input> = {
9
9
  export default meta;
10
10
  type Story = StoryObj<typeof Input>;
11
11
 
12
+ /** Basic empty input field. */
12
13
  export const Default: Story = {
13
14
  args: {},
14
15
  };
15
16
 
17
+ /** Email input with placeholder text. */
16
18
  export const WithPlaceholder: Story = {
17
19
  args: {
18
20
  placeholder: 'Enter your email...',
@@ -20,6 +22,7 @@ export const WithPlaceholder: Story = {
20
22
  },
21
23
  };
22
24
 
25
+ /** Disabled input that cannot be edited. */
23
26
  export const Disabled: Story = {
24
27
  args: {
25
28
  placeholder: 'Disabled input',
@@ -28,6 +31,7 @@ export const Disabled: Story = {
28
31
  },
29
32
  };
30
33
 
34
+ /** Input paired with a label for accessibility. */
31
35
  export const WithLabel: Story = {
32
36
  render: () => (
33
37
  <div className="grid w-full max-w-sm items-center gap-1.5">
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
 
3
3
  import { cn } from '@/lib/utils';
4
4
 
5
+ /** A styled text input field. Supports all native input types including file uploads. Shows validation error styling via aria-invalid. */
5
6
  function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
6
7
  return (
7
8
  <input
@@ -9,6 +9,7 @@ const meta: Meta<typeof InputGroup> = {
9
9
  export default meta;
10
10
  type Story = StoryObj<typeof InputGroup>;
11
11
 
12
+ /** Input with a leading email icon addon. */
12
13
  export const Default: Story = {
13
14
  render: () => (
14
15
  <InputGroup className="max-w-sm">
@@ -22,6 +23,7 @@ export const Default: Story = {
22
23
  ),
23
24
  };
24
25
 
26
+ /** URL input with text addons on both sides. */
25
27
  export const WithPrefixAndSuffix: Story = {
26
28
  render: () => (
27
29
  <InputGroup className="max-w-sm">
@@ -36,6 +38,7 @@ export const WithPrefixAndSuffix: Story = {
36
38
  ),
37
39
  };
38
40
 
41
+ /** Search input with a magnifying glass icon. */
39
42
  export const SearchInput: Story = {
40
43
  render: () => (
41
44
  <InputGroup className="max-w-sm">
@@ -6,6 +6,7 @@ import { Button } from '@/components/ui/Button';
6
6
  import { Input } from '@/components/ui/Input';
7
7
  import { Textarea } from '@/components/ui/Textarea';
8
8
 
9
+ /** Container that combines an input with addons like icons, buttons, or text. Supports inline and block-positioned addons. */
9
10
  function InputGroup({ className, ...props }: React.ComponentProps<'div'>) {
10
11
  return (
11
12
  <div
@@ -52,6 +53,7 @@ const inputGroupAddonVariants = cva(
52
53
  },
53
54
  );
54
55
 
56
+ /** Positioned container for icons, text, or buttons alongside the input. Use align prop to position at inline-start, inline-end, block-start, or block-end. */
55
57
  function InputGroupAddon({
56
58
  className,
57
59
  align = 'inline-start',
@@ -88,6 +90,7 @@ const inputGroupButtonVariants = cva('text-sm shadow-none flex gap-2 items-cente
88
90
  },
89
91
  });
90
92
 
93
+ /** A compact button sized for use inside InputGroupAddon. */
91
94
  function InputGroupButton({
92
95
  className,
93
96
  type = 'button',
@@ -106,6 +109,7 @@ function InputGroupButton({
106
109
  );
107
110
  }
108
111
 
112
+ /** Static text or icon displayed in an InputGroupAddon. */
109
113
  function InputGroupText({ className, ...props }: React.ComponentProps<'span'>) {
110
114
  return (
111
115
  <span
@@ -118,6 +122,7 @@ function InputGroupText({ className, ...props }: React.ComponentProps<'span'>) {
118
122
  );
119
123
  }
120
124
 
125
+ /** Input element styled to integrate seamlessly within an InputGroup. */
121
126
  function InputGroupInput({ className, ...props }: React.ComponentProps<'input'>) {
122
127
  return (
123
128
  <Input
@@ -131,6 +136,7 @@ function InputGroupInput({ className, ...props }: React.ComponentProps<'input'>)
131
136
  );
132
137
  }
133
138
 
139
+ /** Textarea element styled to integrate seamlessly within an InputGroup. */
134
140
  function InputGroupTextarea({ className, ...props }: React.ComponentProps<'textarea'>) {
135
141
  return (
136
142
  <Textarea
@@ -8,6 +8,7 @@ const meta: Meta<typeof InputOTP> = {
8
8
  export default meta;
9
9
  type Story = StoryObj<typeof InputOTP>;
10
10
 
11
+ /** 6-digit OTP input split into two groups of three with a separator. */
11
12
  export const Default: Story = {
12
13
  render: () => (
13
14
  <InputOTP maxLength={6}>
@@ -26,6 +27,7 @@ export const Default: Story = {
26
27
  ),
27
28
  };
28
29
 
30
+ /** Compact 4-digit PIN input without separator. */
29
31
  export const FourDigits: Story = {
30
32
  render: () => (
31
33
  <InputOTP maxLength={4}>
@@ -6,6 +6,7 @@ import { MinusIcon } from 'lucide-react';
6
6
 
7
7
  import { cn } from '@/lib/utils';
8
8
 
9
+ /** One-time password input with individual digit slots. Handles paste, backspace, and arrow key navigation automatically. */
9
10
  function InputOTP({
10
11
  className,
11
12
  containerClassName,
@@ -23,10 +24,12 @@ function InputOTP({
23
24
  );
24
25
  }
25
26
 
27
+ /** Groups InputOTPSlot elements together visually. */
26
28
  function InputOTPGroup({ className, ...props }: React.ComponentProps<'div'>) {
27
29
  return <div data-slot="input-otp-group" className={cn('flex items-center', className)} {...props} />;
28
30
  }
29
31
 
32
+ /** A single digit slot in the OTP input. Shows a blinking caret when active. */
30
33
  function InputOTPSlot({
31
34
  index,
32
35
  className,
@@ -57,6 +60,7 @@ function InputOTPSlot({
57
60
  );
58
61
  }
59
62
 
63
+ /** Visual separator between groups of OTP slots, typically a dash. */
60
64
  function InputOTPSeparator({ ...props }: React.ComponentProps<'div'>) {
61
65
  return (
62
66
  <div data-slot="input-otp-separator" role="separator" {...props}>
@@ -9,6 +9,7 @@ const meta: Meta<typeof Item> = {
9
9
  export default meta;
10
10
  type Story = StoryObj<typeof Item>;
11
11
 
12
+ /** Standard item with title, description, and action buttons. */
12
13
  export const Default: Story = {
13
14
  render: () => (
14
15
  <Item>
@@ -28,6 +29,7 @@ export const Default: Story = {
28
29
  ),
29
30
  };
30
31
 
32
+ /** Item with visible border using the outline variant. */
31
33
  export const OutlineVariant: Story = {
32
34
  render: () => (
33
35
  <Item variant="outline">
@@ -44,6 +46,7 @@ export const OutlineVariant: Story = {
44
46
  ),
45
47
  };
46
48
 
49
+ /** Compact item with reduced padding for dense lists. */
47
50
  export const SmallSize: Story = {
48
51
  render: () => (
49
52
  <Item size="sm">
@@ -5,12 +5,14 @@ import { Slot } from 'radix-ui';
5
5
  import { cn } from '@/lib/utils';
6
6
  import { Separator } from '@/components/ui/Separator';
7
7
 
8
+ /** Container for a list of Item components. Provides list semantics for accessibility. */
8
9
  function ItemGroup({ className, ...props }: React.ComponentProps<'div'>) {
9
10
  return (
10
11
  <div role="list" data-slot="item-group" className={cn('group/item-group flex flex-col', className)} {...props} />
11
12
  );
12
13
  }
13
14
 
15
+ /** Horizontal divider between items in an ItemGroup. */
14
16
  function ItemSeparator({ className, ...props }: React.ComponentProps<typeof Separator>) {
15
17
  return <Separator data-slot="item-separator" orientation="horizontal" className={cn('my-0', className)} {...props} />;
16
18
  }
@@ -36,6 +38,7 @@ const itemVariants = cva(
36
38
  },
37
39
  );
38
40
 
41
+ /** A flexible list item for displaying structured content like notifications, settings rows, or search results. Compose with ItemMedia, ItemContent, ItemTitle, ItemDescription, and ItemActions. */
39
42
  function Item({
40
43
  className,
41
44
  variant = 'default',
@@ -71,6 +74,7 @@ const itemMediaVariants = cva(
71
74
  },
72
75
  );
73
76
 
77
+ /** 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. */
74
78
  function ItemMedia({
75
79
  className,
76
80
  variant = 'default',
@@ -86,6 +90,7 @@ function ItemMedia({
86
90
  );
87
91
  }
88
92
 
93
+ /** Main content area of an Item, containing title and description. */
89
94
  function ItemContent({ className, ...props }: React.ComponentProps<'div'>) {
90
95
  return (
91
96
  <div
@@ -96,6 +101,7 @@ function ItemContent({ className, ...props }: React.ComponentProps<'div'>) {
96
101
  );
97
102
  }
98
103
 
104
+ /** Primary text label for an Item. */
99
105
  function ItemTitle({ className, ...props }: React.ComponentProps<'div'>) {
100
106
  return (
101
107
  <div
@@ -106,6 +112,7 @@ function ItemTitle({ className, ...props }: React.ComponentProps<'div'>) {
106
112
  );
107
113
  }
108
114
 
115
+ /** Secondary text below the title, limited to 2 lines. */
109
116
  function ItemDescription({ className, ...props }: React.ComponentProps<'p'>) {
110
117
  return (
111
118
  <p
@@ -120,10 +127,12 @@ function ItemDescription({ className, ...props }: React.ComponentProps<'p'>) {
120
127
  );
121
128
  }
122
129
 
130
+ /** Container for action buttons at the end of an Item. */
123
131
  function ItemActions({ className, ...props }: React.ComponentProps<'div'>) {
124
132
  return <div data-slot="item-actions" className={cn('flex items-center gap-2', className)} {...props} />;
125
133
  }
126
134
 
135
+ /** Full-width header row spanning the top of an Item, with space-between layout. */
127
136
  function ItemHeader({ className, ...props }: React.ComponentProps<'div'>) {
128
137
  return (
129
138
  <div
@@ -134,6 +143,7 @@ function ItemHeader({ className, ...props }: React.ComponentProps<'div'>) {
134
143
  );
135
144
  }
136
145
 
146
+ /** Full-width footer row spanning the bottom of an Item, with space-between layout. */
137
147
  function ItemFooter({ className, ...props }: React.ComponentProps<'div'>) {
138
148
  return (
139
149
  <div
@@ -13,24 +13,28 @@ const meta: Meta<typeof Kbd> = {
13
13
  export default meta;
14
14
  type Story = StoryObj<typeof meta>;
15
15
 
16
+ /** Shows a single keyboard key shortcut. */
16
17
  export const Default: Story = {
17
18
  args: {
18
19
  children: '⌘K',
19
20
  },
20
21
  };
21
22
 
23
+ /** Shows a key with a text label like "Ctrl". */
22
24
  export const WithText: Story = {
23
25
  args: {
24
26
  children: 'Ctrl',
25
27
  },
26
28
  };
27
29
 
30
+ /** Shows a key with an arrow symbol. */
28
31
  export const ArrowKeys: Story = {
29
32
  args: {
30
33
  children: '→',
31
34
  },
32
35
  };
33
36
 
37
+ /** Shows two keys composed together to represent a shortcut combination. */
34
38
  export const Multiple: Story = {
35
39
  render: () => (
36
40
  <div className="flex gap-2 items-center">
@@ -41,6 +45,7 @@ export const Multiple: Story = {
41
45
  ),
42
46
  };
43
47
 
48
+ /** Shows a three-key combination shortcut. */
44
49
  export const Combination: Story = {
45
50
  render: () => (
46
51
  <div className="flex gap-2 items-center">
@@ -6,6 +6,10 @@ interface KbdProps {
6
6
  className?: string;
7
7
  }
8
8
 
9
+ /**
10
+ * Renders inline keyboard key indicators, styled to look like physical keys.
11
+ * Use to display keyboard shortcuts or key combinations in documentation and UI hints.
12
+ */
9
13
  export function Kbd({ children, className }: KbdProps) {
10
14
  return (
11
15
  <kbd
@@ -28,6 +28,7 @@ const meta: Meta<typeof Label> = {
28
28
  export default meta;
29
29
  type Story = StoryObj<typeof meta>;
30
30
 
31
+ /** Shows a basic label associated with a form field. */
31
32
  export const Default: Story = {
32
33
  args: {
33
34
  children: 'Email address',
@@ -35,6 +36,7 @@ export const Default: Story = {
35
36
  },
36
37
  };
37
38
 
39
+ /** Shows the label with the required prop, which appends a red asterisk. */
38
40
  export const Required: Story = {
39
41
  args: {
40
42
  children: 'Email address',
@@ -43,6 +45,7 @@ export const Required: Story = {
43
45
  },
44
46
  };
45
47
 
48
+ /** Shows the label using the "required" variant prop directly. */
46
49
  export const RequiredVariant: Story = {
47
50
  args: {
48
51
  children: 'Email address',
@@ -51,6 +54,7 @@ export const RequiredVariant: Story = {
51
54
  },
52
55
  };
53
56
 
57
+ /** Shows the label paired with a text input in a form layout. */
54
58
  export const WithForm: Story = {
55
59
  render: (args) => (
56
60
  <div className="space-y-2">
@@ -67,6 +71,7 @@ export const WithForm: Story = {
67
71
  ),
68
72
  };
69
73
 
74
+ /** Demonstrates the dimmed appearance when the associated input is disabled. */
70
75
  export const DisabledField: Story = {
71
76
  render: (args) => (
72
77
  <div className="space-y-2">
@@ -23,6 +23,10 @@ export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement>,
23
23
  children?: React.ReactNode;
24
24
  }
25
25
 
26
+ /**
27
+ * An accessible label associated with a form control via the htmlFor prop.
28
+ * Supports a "required" variant that appends a red asterisk, and automatically dims when its peer input is disabled.
29
+ */
26
30
  const Label = React.forwardRef<HTMLLabelElement, LabelProps>(({ className, variant, required, ...props }, ref) => {
27
31
  const effectiveVariant = required ? 'required' : variant || 'default';
28
32
 
@@ -17,6 +17,7 @@ const meta: Meta<typeof Menubar> = {
17
17
  export default meta;
18
18
  type Story = StoryObj<typeof Menubar>;
19
19
 
20
+ /** Shows a menubar with File and Edit menus containing items and keyboard shortcuts. */
20
21
  export const Default: Story = {
21
22
  render: () => (
22
23
  <Menubar>
@@ -56,6 +57,7 @@ export const Default: Story = {
56
57
  ),
57
58
  };
58
59
 
60
+ /** Demonstrates menu sections organized with labels to group related items. */
59
61
  export const WithLabels: Story = {
60
62
  render: () => (
61
63
  <Menubar>
@@ -6,6 +6,10 @@ import { Menubar as MenubarPrimitive } from 'radix-ui';
6
6
 
7
7
  import { cn } from '@/lib/utils';
8
8
 
9
+ /**
10
+ * A horizontal menu bar for desktop applications, built on Radix UI Menubar primitive.
11
+ * Compose with MenubarMenu, MenubarTrigger, and MenubarContent to create top-level menu groups with keyboard navigation.
12
+ */
9
13
  function Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>) {
10
14
  return (
11
15
  <MenubarPrimitive.Root
@@ -16,6 +20,7 @@ function Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPri
16
20
  );
17
21
  }
18
22
 
23
+ /** A single menu within the menubar that wraps a trigger and its dropdown content. */
19
24
  function MenubarMenu({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
20
25
  return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />;
21
26
  }
@@ -32,6 +37,7 @@ function MenubarRadioGroup({ ...props }: React.ComponentProps<typeof MenubarPrim
32
37
  return <MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />;
33
38
  }
34
39
 
40
+ /** The button that toggles a menu open within the menubar. */
35
41
  function MenubarTrigger({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {
36
42
  return (
37
43
  <MenubarPrimitive.Trigger
@@ -45,6 +51,7 @@ function MenubarTrigger({ className, ...props }: React.ComponentProps<typeof Men
45
51
  );
46
52
  }
47
53
 
54
+ /** The dropdown panel that appears when a MenubarTrigger is activated. Renders via a portal. */
48
55
  function MenubarContent({
49
56
  className,
50
57
  align = 'start',
@@ -69,9 +76,12 @@ function MenubarContent({
69
76
  );
70
77
  }
71
78
 
79
+ /** An interactive item within a menubar dropdown. Supports an inset layout and a destructive variant. */
72
80
  function MenubarItem({
73
81
  className,
82
+ /** Adds left padding to align with items that have icons or indicators. */
74
83
  inset,
84
+ /** Use "destructive" for dangerous actions. */
75
85
  variant = 'default',
76
86
  ...props
77
87
  }: React.ComponentProps<typeof MenubarPrimitive.Item> & {
@@ -92,6 +102,7 @@ function MenubarItem({
92
102
  );
93
103
  }
94
104
 
105
+ /** A menu item with a checkbox indicator for toggling boolean options. */
95
106
  function MenubarCheckboxItem({
96
107
  className,
97
108
  children,
@@ -118,6 +129,7 @@ function MenubarCheckboxItem({
118
129
  );
119
130
  }
120
131
 
132
+ /** A menu item within a MenubarRadioGroup that shows a radio dot when selected. */
121
133
  function MenubarRadioItem({ className, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {
122
134
  return (
123
135
  <MenubarPrimitive.RadioItem
@@ -165,6 +177,7 @@ function MenubarSeparator({ className, ...props }: React.ComponentProps<typeof M
165
177
  );
166
178
  }
167
179
 
180
+ /** Displays a keyboard shortcut hint aligned to the right of a menu item. */
168
181
  function MenubarShortcut({ className, ...props }: React.ComponentProps<'span'>) {
169
182
  return (
170
183
  <span
@@ -179,6 +192,7 @@ function MenubarSub({ ...props }: React.ComponentProps<typeof MenubarPrimitive.S
179
192
  return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
180
193
  }
181
194
 
195
+ /** The trigger for a nested submenu, rendering a chevron icon to indicate expandability. */
182
196
  function MenubarSubTrigger({
183
197
  className,
184
198
  inset,
@@ -203,6 +217,7 @@ function MenubarSubTrigger({
203
217
  );
204
218
  }
205
219
 
220
+ /** The dropdown content panel for a nested submenu. */
206
221
  function MenubarSubContent({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {
207
222
  return (
208
223
  <MenubarPrimitive.SubContent
@@ -8,6 +8,7 @@ const meta: Meta<typeof NativeSelect> = {
8
8
  export default meta;
9
9
  type Story = StoryObj<typeof NativeSelect>;
10
10
 
11
+ /** Shows a native select with pre-selected value and several options. */
11
12
  export const Default: Story = {
12
13
  render: () => (
13
14
  <NativeSelect defaultValue="react">
@@ -19,6 +20,7 @@ export const Default: Story = {
19
20
  ),
20
21
  };
21
22
 
23
+ /** Shows the compact size variant with a disabled placeholder option. */
22
24
  export const Small: Story = {
23
25
  render: () => (
24
26
  <NativeSelect size="sm" defaultValue="">
@@ -32,6 +34,7 @@ export const Small: Story = {
32
34
  ),
33
35
  };
34
36
 
37
+ /** Shows the select in a disabled state. */
35
38
  export const Disabled: Story = {
36
39
  render: () => (
37
40
  <NativeSelect disabled defaultValue="react">
@@ -3,6 +3,10 @@ import { ChevronDownIcon } from 'lucide-react';
3
3
 
4
4
  import { cn } from '@/lib/utils';
5
5
 
6
+ /**
7
+ * A styled wrapper around the browser's native <select> element.
8
+ * Use instead of the custom Select component when native mobile pickers or simpler accessibility is preferred.
9
+ */
6
10
  function NativeSelect({
7
11
  className,
8
12
  size = 'default',
@@ -33,10 +37,12 @@ function NativeSelect({
33
37
  );
34
38
  }
35
39
 
40
+ /** An individual option within a NativeSelect dropdown. */
36
41
  function NativeSelectOption({ ...props }: React.ComponentProps<'option'>) {
37
42
  return <option data-slot="native-select-option" {...props} />;
38
43
  }
39
44
 
45
+ /** Groups related options under a label within a NativeSelect. */
40
46
  function NativeSelectOptGroup({ className, ...props }: React.ComponentProps<'optgroup'>) {
41
47
  return <optgroup data-slot="native-select-optgroup" className={cn(className)} {...props} />;
42
48
  }
@@ -15,6 +15,7 @@ const meta: Meta<typeof NavigationMenu> = {
15
15
  export default meta;
16
16
  type Story = StoryObj<typeof NavigationMenu>;
17
17
 
18
+ /** Shows a navigation menu with dropdown content panels and a direct link item. */
18
19
  export const Default: Story = {
19
20
  render: () => (
20
21
  <NavigationMenu>
@@ -59,6 +60,7 @@ export const Default: Story = {
59
60
  ),
60
61
  };
61
62
 
63
+ /** Shows a flat navigation menu with simple link items and no dropdowns. */
62
64
  export const SimpleLinks: Story = {
63
65
  render: () => (
64
66
  <NavigationMenu>
@@ -5,9 +5,14 @@ import { NavigationMenu as NavigationMenuPrimitive } from 'radix-ui';
5
5
 
6
6
  import { cn } from '@/lib/utils';
7
7
 
8
+ /**
9
+ * A site-wide navigation component with dropdown content panels, built on Radix UI NavigationMenu primitive.
10
+ * Compose with NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, and NavigationMenuContent for rich mega-menu layouts.
11
+ */
8
12
  function NavigationMenu({
9
13
  className,
10
14
  children,
15
+ /** Whether to render the shared viewport container for content panels. Set to false for inline dropdowns. */
11
16
  viewport = true,
12
17
  ...props
13
18
  }: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
@@ -26,6 +31,7 @@ function NavigationMenu({
26
31
  );
27
32
  }
28
33
 
34
+ /** The horizontal list container for navigation menu items. */
29
35
  function NavigationMenuList({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
30
36
  return (
31
37
  <NavigationMenuPrimitive.List
@@ -46,6 +52,7 @@ const navigationMenuTriggerStyle = cva(
46
52
  'group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1',
47
53
  );
48
54
 
55
+ /** The button that opens a NavigationMenuContent dropdown, with an animated chevron indicator. */
49
56
  function NavigationMenuTrigger({
50
57
  className,
51
58
  children,
@@ -66,6 +73,7 @@ function NavigationMenuTrigger({
66
73
  );
67
74
  }
68
75
 
76
+ /** The expandable content panel that appears below a NavigationMenuTrigger with animated transitions. */
69
77
  function NavigationMenuContent({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
70
78
  return (
71
79
  <NavigationMenuPrimitive.Content
@@ -98,6 +106,7 @@ function NavigationMenuViewport({
98
106
  );
99
107
  }
100
108
 
109
+ /** A styled link within the navigation menu, used for both top-level and dropdown links. */
101
110
  function NavigationMenuLink({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
102
111
  return (
103
112
  <NavigationMenuPrimitive.Link
@@ -111,6 +120,7 @@ function NavigationMenuLink({ className, ...props }: React.ComponentProps<typeof
111
120
  );
112
121
  }
113
122
 
123
+ /** An animated arrow indicator that tracks the active menu item position. */
114
124
  function NavigationMenuIndicator({
115
125
  className,
116
126
  ...props