@neynar/ui 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/components/ui/accordion.d.ts +1 -25
  2. package/dist/components/ui/accordion.d.ts.map +1 -1
  3. package/dist/components/ui/alert-dialog.d.ts +240 -46
  4. package/dist/components/ui/alert-dialog.d.ts.map +1 -1
  5. package/dist/components/ui/alert.d.ts +73 -11
  6. package/dist/components/ui/alert.d.ts.map +1 -1
  7. package/dist/components/ui/aspect-ratio.d.ts +44 -10
  8. package/dist/components/ui/aspect-ratio.d.ts.map +1 -1
  9. package/dist/components/ui/avatar.d.ts +117 -33
  10. package/dist/components/ui/avatar.d.ts.map +1 -1
  11. package/dist/components/ui/badge.d.ts +50 -71
  12. package/dist/components/ui/badge.d.ts.map +1 -1
  13. package/dist/components/ui/breadcrumb.d.ts +231 -49
  14. package/dist/components/ui/breadcrumb.d.ts.map +1 -1
  15. package/dist/components/ui/button.d.ts +189 -71
  16. package/dist/components/ui/button.d.ts.map +1 -1
  17. package/dist/components/ui/calendar.d.ts +197 -40
  18. package/dist/components/ui/calendar.d.ts.map +1 -1
  19. package/dist/components/ui/card.d.ts +7 -22
  20. package/dist/components/ui/card.d.ts.map +1 -1
  21. package/dist/components/ui/carousel.d.ts +369 -99
  22. package/dist/components/ui/carousel.d.ts.map +1 -1
  23. package/dist/components/ui/chart.d.ts.map +1 -1
  24. package/dist/components/ui/checkbox.d.ts +110 -38
  25. package/dist/components/ui/checkbox.d.ts.map +1 -1
  26. package/dist/components/ui/collapsible.d.ts +246 -61
  27. package/dist/components/ui/collapsible.d.ts.map +1 -1
  28. package/dist/components/ui/combobox.d.ts +207 -159
  29. package/dist/components/ui/combobox.d.ts.map +1 -1
  30. package/dist/components/ui/command.d.ts +336 -67
  31. package/dist/components/ui/command.d.ts.map +1 -1
  32. package/dist/components/ui/container.d.ts +159 -64
  33. package/dist/components/ui/container.d.ts.map +1 -1
  34. package/dist/components/ui/context-menu.d.ts +321 -39
  35. package/dist/components/ui/context-menu.d.ts.map +1 -1
  36. package/dist/components/ui/date-picker.d.ts +113 -86
  37. package/dist/components/ui/date-picker.d.ts.map +1 -1
  38. package/dist/components/ui/dialog.d.ts +106 -25
  39. package/dist/components/ui/dialog.d.ts.map +1 -1
  40. package/dist/components/ui/drawer.d.ts +388 -59
  41. package/dist/components/ui/drawer.d.ts.map +1 -1
  42. package/dist/components/ui/dropdown-menu.d.ts +521 -74
  43. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  44. package/dist/components/ui/empty-state.d.ts +148 -76
  45. package/dist/components/ui/empty-state.d.ts.map +1 -1
  46. package/dist/components/ui/hover-card.d.ts +253 -34
  47. package/dist/components/ui/hover-card.d.ts.map +1 -1
  48. package/dist/components/ui/input.d.ts +143 -44
  49. package/dist/components/ui/input.d.ts.map +1 -1
  50. package/dist/components/ui/label.d.ts +0 -8
  51. package/dist/components/ui/label.d.ts.map +1 -1
  52. package/dist/components/ui/menubar.d.ts +288 -46
  53. package/dist/components/ui/menubar.d.ts.map +1 -1
  54. package/dist/components/ui/navigation-menu.d.ts +444 -127
  55. package/dist/components/ui/navigation-menu.d.ts.map +1 -1
  56. package/dist/components/ui/pagination.d.ts +342 -66
  57. package/dist/components/ui/pagination.d.ts.map +1 -1
  58. package/dist/components/ui/popover.d.ts +0 -8
  59. package/dist/components/ui/popover.d.ts.map +1 -1
  60. package/dist/components/ui/progress.d.ts +88 -30
  61. package/dist/components/ui/progress.d.ts.map +1 -1
  62. package/dist/components/ui/radio-group.d.ts +189 -45
  63. package/dist/components/ui/radio-group.d.ts.map +1 -1
  64. package/dist/components/ui/resizable.d.ts +178 -62
  65. package/dist/components/ui/resizable.d.ts.map +1 -1
  66. package/dist/components/ui/scroll-area.d.ts +180 -21
  67. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  68. package/dist/components/ui/select.d.ts +382 -60
  69. package/dist/components/ui/select.d.ts.map +1 -1
  70. package/dist/components/ui/separator.d.ts +52 -39
  71. package/dist/components/ui/separator.d.ts.map +1 -1
  72. package/dist/components/ui/sheet.d.ts +144 -27
  73. package/dist/components/ui/sheet.d.ts.map +1 -1
  74. package/dist/components/ui/sidebar.d.ts +81 -31
  75. package/dist/components/ui/sidebar.d.ts.map +1 -1
  76. package/dist/components/ui/skeleton.d.ts +94 -32
  77. package/dist/components/ui/skeleton.d.ts.map +1 -1
  78. package/dist/components/ui/slider.d.ts +37 -31
  79. package/dist/components/ui/slider.d.ts.map +1 -1
  80. package/dist/components/ui/sonner.d.ts +280 -46
  81. package/dist/components/ui/sonner.d.ts.map +1 -1
  82. package/dist/components/ui/stack.d.ts +289 -148
  83. package/dist/components/ui/stack.d.ts.map +1 -1
  84. package/dist/components/ui/stories/aspect-ratio.stories.d.ts +1 -2
  85. package/dist/components/ui/stories/aspect-ratio.stories.d.ts.map +1 -1
  86. package/dist/components/ui/stories/container.stories.d.ts +2 -3
  87. package/dist/components/ui/stories/container.stories.d.ts.map +1 -1
  88. package/dist/components/ui/stories/empty-state.stories.d.ts +2 -2
  89. package/dist/components/ui/stories/scroll-area.stories.d.ts +1 -2
  90. package/dist/components/ui/stories/scroll-area.stories.d.ts.map +1 -1
  91. package/dist/components/ui/stories/stack.stories.d.ts +1 -1
  92. package/dist/components/ui/stories/text-field.stories.d.ts +7 -1
  93. package/dist/components/ui/stories/text-field.stories.d.ts.map +1 -1
  94. package/dist/components/ui/switch.d.ts +44 -38
  95. package/dist/components/ui/switch.d.ts.map +1 -1
  96. package/dist/components/ui/table.d.ts +33 -0
  97. package/dist/components/ui/table.d.ts.map +1 -1
  98. package/dist/components/ui/tabs.d.ts +4 -22
  99. package/dist/components/ui/tabs.d.ts.map +1 -1
  100. package/dist/components/ui/text-field.d.ts +170 -84
  101. package/dist/components/ui/text-field.d.ts.map +1 -1
  102. package/dist/components/ui/textarea.d.ts +106 -29
  103. package/dist/components/ui/textarea.d.ts.map +1 -1
  104. package/dist/components/ui/theme-toggle.d.ts +190 -65
  105. package/dist/components/ui/theme-toggle.d.ts.map +1 -1
  106. package/dist/components/ui/theme.d.ts +107 -23
  107. package/dist/components/ui/theme.d.ts.map +1 -1
  108. package/dist/components/ui/toggle-group.d.ts +143 -67
  109. package/dist/components/ui/toggle-group.d.ts.map +1 -1
  110. package/dist/components/ui/toggle.d.ts +118 -30
  111. package/dist/components/ui/toggle.d.ts.map +1 -1
  112. package/dist/components/ui/tooltip.d.ts +152 -28
  113. package/dist/components/ui/tooltip.d.ts.map +1 -1
  114. package/dist/components/ui/typography.d.ts +452 -134
  115. package/dist/components/ui/typography.d.ts.map +1 -1
  116. package/dist/index.js +9388 -8281
  117. package/dist/index.js.map +1 -1
  118. package/dist/tsconfig.tsbuildinfo +1 -1
  119. package/llms.txt +173 -3
  120. package/package.json +5 -2
  121. package/src/components/ui/accordion.tsx +112 -27
  122. package/src/components/ui/alert-dialog.tsx +401 -46
  123. package/src/components/ui/alert.tsx +114 -11
  124. package/src/components/ui/aspect-ratio.tsx +69 -14
  125. package/src/components/ui/avatar.tsx +179 -33
  126. package/src/components/ui/badge.tsx +74 -75
  127. package/src/components/ui/breadcrumb.tsx +335 -50
  128. package/src/components/ui/button.tsx +198 -90
  129. package/src/components/ui/calendar.tsx +867 -43
  130. package/src/components/ui/card.tsx +140 -33
  131. package/src/components/ui/carousel.tsx +529 -98
  132. package/src/components/ui/chart.tsx +222 -1
  133. package/src/components/ui/checkbox.tsx +176 -38
  134. package/src/components/ui/collapsible.tsx +321 -67
  135. package/src/components/ui/combobox.tsx +284 -83
  136. package/src/components/ui/command.tsx +527 -67
  137. package/src/components/ui/container.tsx +217 -65
  138. package/src/components/ui/context-menu.tsx +716 -51
  139. package/src/components/ui/date-picker.tsx +228 -38
  140. package/src/components/ui/dialog.tsx +270 -33
  141. package/src/components/ui/drawer.tsx +546 -67
  142. package/src/components/ui/dropdown-menu.tsx +657 -74
  143. package/src/components/ui/empty-state.tsx +241 -82
  144. package/src/components/ui/hover-card.tsx +328 -39
  145. package/src/components/ui/input.tsx +207 -44
  146. package/src/components/ui/label.tsx +98 -8
  147. package/src/components/ui/menubar.tsx +587 -54
  148. package/src/components/ui/navigation-menu.tsx +557 -128
  149. package/src/components/ui/pagination.tsx +561 -79
  150. package/src/components/ui/popover.tsx +119 -8
  151. package/src/components/ui/progress.tsx +131 -29
  152. package/src/components/ui/radio-group.tsx +260 -51
  153. package/src/components/ui/resizable.tsx +289 -63
  154. package/src/components/ui/scroll-area.tsx +377 -66
  155. package/src/components/ui/select.tsx +545 -60
  156. package/src/components/ui/separator.tsx +146 -40
  157. package/src/components/ui/sheet.tsx +348 -31
  158. package/src/components/ui/sidebar.tsx +471 -29
  159. package/src/components/ui/skeleton.tsx +114 -32
  160. package/src/components/ui/slider.tsx +77 -31
  161. package/src/components/ui/sonner.tsx +574 -46
  162. package/src/components/ui/stack.tsx +423 -101
  163. package/src/components/ui/switch.tsx +78 -39
  164. package/src/components/ui/table.tsx +170 -4
  165. package/src/components/ui/tabs.tsx +108 -22
  166. package/src/components/ui/text-field.tsx +226 -81
  167. package/src/components/ui/textarea.tsx +180 -29
  168. package/src/components/ui/theme-toggle.tsx +313 -65
  169. package/src/components/ui/theme.tsx +117 -23
  170. package/src/components/ui/toggle-group.tsx +280 -69
  171. package/src/components/ui/toggle.tsx +124 -35
  172. package/src/components/ui/tooltip.tsx +239 -29
  173. package/src/components/ui/typography.tsx +1115 -165
@@ -12,18 +12,160 @@ const ToggleGroupContext = React.createContext<
12
12
  variant: "default",
13
13
  });
14
14
 
15
+ /**
16
+ * Props for ToggleGroup (Documentation only - NOT used in component implementation)
17
+ * These types are for documentation generation and should not replace Radix inferred types
18
+ *
19
+ * Combines Radix UI ToggleGroup.Root props with visual variant options from CVA.
20
+ * Supports both single and multiple selection modes with keyboard navigation.
21
+ */
22
+ // eslint-disable-next-line unused-imports/no-unused-vars
23
+ type ToggleGroupDocsProps = {
24
+ /** Additional CSS classes to apply to the toggle group container */
25
+ className?: string;
26
+ /**
27
+ * Selection mode for the toggle group
28
+ * @description Determines how many items can be selected simultaneously
29
+ * - "single": Only one item can be selected at a time (radio-like behavior)
30
+ * - "multiple": Multiple items can be selected independently (checkbox-like behavior)
31
+ */
32
+ type: "single" | "multiple";
33
+ /**
34
+ * Visual style variant inherited by all child items
35
+ * @description Controls the appearance and visual emphasis of toggle items
36
+ * @default "default"
37
+ */
38
+ variant?: "default" | "outline";
39
+ /**
40
+ * Size variant inherited by all child items
41
+ * @description Controls the padding and dimensions of toggle items
42
+ * @default "default"
43
+ */
44
+ size?: "sm" | "default" | "lg";
45
+ /**
46
+ * Default selected value(s) for uncontrolled usage
47
+ * @description Initial selection state when not controlling the component
48
+ * - For type="single": string value of initially selected item
49
+ * - For type="multiple": array of string values for initially selected items
50
+ */
51
+ defaultValue?: string | string[];
52
+ /**
53
+ * Current selected value(s) for controlled usage
54
+ * @description Current selection state when controlling the component externally
55
+ * - For type="single": string value of currently selected item, or undefined for none
56
+ * - For type="multiple": array of string values for currently selected items
57
+ */
58
+ value?: string | string[];
59
+ /**
60
+ * Callback fired when selection changes
61
+ * @description Called whenever the user selects or deselects items
62
+ * - For type="single": receives string value or undefined
63
+ * - For type="multiple": receives array of selected string values
64
+ * @param value - The new selection value(s)
65
+ */
66
+ onValueChange?: (value: string | string[]) => void;
67
+ /**
68
+ * Whether the entire toggle group is disabled
69
+ * @description When true, all items become non-interactive and visually disabled
70
+ * @default false
71
+ */
72
+ disabled?: boolean;
73
+ /**
74
+ * Whether to enable roving focus behavior
75
+ * @description Controls keyboard navigation between items using arrow keys
76
+ * @default true
77
+ */
78
+ rovingFocus?: boolean;
79
+ /**
80
+ * Layout orientation of the toggle group
81
+ * @description Affects keyboard navigation direction and visual layout hints
82
+ * - "horizontal": Arrow Left/Right navigate, items laid out horizontally
83
+ * - "vertical": Arrow Up/Down navigate, items laid out vertically
84
+ * @default "horizontal"
85
+ */
86
+ orientation?: "horizontal" | "vertical";
87
+ /**
88
+ * Reading direction for internationalization
89
+ * @description Affects the logical navigation order and layout direction
90
+ * - "ltr": Left-to-right reading direction
91
+ * - "rtl": Right-to-left reading direction
92
+ */
93
+ dir?: "ltr" | "rtl";
94
+ /**
95
+ * Whether focus should loop from last to first item
96
+ * @description Controls behavior when navigating past the end of the group
97
+ * @default true
98
+ */
99
+ loop?: boolean;
100
+ /**
101
+ * Render as a different element or merge props
102
+ * @description When true, merges props into immediate child instead of rendering div
103
+ * @default false
104
+ */
105
+ asChild?: boolean;
106
+ /** Toggle group items and other React children */
107
+ children?: React.ReactNode;
108
+ } & React.ComponentProps<typeof ToggleGroupPrimitive.Root>;
109
+
110
+ /**
111
+ * Props for ToggleGroupItem (Documentation only - NOT used in component implementation)
112
+ * These types are for documentation generation and should not replace Radix inferred types
113
+ *
114
+ * Individual selectable items within a ToggleGroup. Inherits variant and size from
115
+ * parent ToggleGroup context but can override them for specific styling needs.
116
+ */
117
+ // eslint-disable-next-line unused-imports/no-unused-vars
118
+ type ToggleGroupItemDocsProps = {
119
+ /** Additional CSS classes to apply to the toggle item */
120
+ className?: string;
121
+ /**
122
+ * Unique identifier for this toggle item (required)
123
+ * @description Used to track selection state and must be unique within the group
124
+ */
125
+ value: string;
126
+ /**
127
+ * Whether this specific item is disabled
128
+ * @description When true, this item becomes non-interactive while others remain functional
129
+ * @default false
130
+ */
131
+ disabled?: boolean;
132
+ /**
133
+ * Override visual style variant from parent ToggleGroup
134
+ * @description When provided, overrides the variant inherited from ToggleGroup context
135
+ */
136
+ variant?: "default" | "outline";
137
+ /**
138
+ * Override size variant from parent ToggleGroup
139
+ * @description When provided, overrides the size inherited from ToggleGroup context
140
+ */
141
+ size?: "sm" | "default" | "lg";
142
+ /**
143
+ * Render as a different element or merge props
144
+ * @description When true, merges props into immediate child instead of rendering button
145
+ * @default false
146
+ */
147
+ asChild?: boolean;
148
+ /** Content to display within the toggle item (icons, text, or both) */
149
+ children?: React.ReactNode;
150
+ } & React.ComponentProps<typeof ToggleGroupPrimitive.Item>;
151
+
15
152
  /**
16
153
  * Toggle Group - A group of toggle buttons with single or multiple selection
17
154
  *
18
155
  * ToggleGroup provides a way to group related toggle buttons together, allowing users
19
156
  * to select from a set of mutually exclusive options (single selection) or independent
20
- * options (multiple selection). Built on Radix UI Toggle Group primitive with support
21
- * for keyboard navigation and accessibility features.
157
+ * options (multiple selection). Built on Radix UI Toggle Group primitive with enhanced
158
+ * styling through CVA variants and full accessibility support including keyboard navigation.
22
159
  *
23
- * @example
160
+ * The component supports both controlled and uncontrolled usage patterns, with automatic
161
+ * focus management and roving tabindex behavior. Visual variants are inherited by all child
162
+ * items but can be overridden per item if needed.
163
+ *
164
+ * @example Single selection with icons (radio button behavior)
24
165
  * ```tsx
25
- * // Single selection (like radio buttons)
26
- * <ToggleGroup type="single" defaultValue="center">
166
+ * import { AlignLeft, AlignCenter, AlignRight } from "lucide-react";
167
+ *
168
+ * <ToggleGroup type="single" defaultValue="center" aria-label="Text alignment">
27
169
  * <ToggleGroupItem value="left" aria-label="Align left">
28
170
  * <AlignLeft className="h-4 w-4" />
29
171
  * </ToggleGroupItem>
@@ -36,51 +178,92 @@ const ToggleGroupContext = React.createContext<
36
178
  * </ToggleGroup>
37
179
  * ```
38
180
  *
39
- * @example
181
+ * @example Multiple selection with controlled state
40
182
  * ```tsx
41
- * // Multiple selection (like checkboxes)
42
- * <ToggleGroup type="multiple" defaultValue={["bold", "italic"]}>
43
- * <ToggleGroupItem value="bold" aria-label="Toggle bold">
44
- * <Bold className="h-4 w-4" />
45
- * </ToggleGroupItem>
46
- * <ToggleGroupItem value="italic" aria-label="Toggle italic">
47
- * <Italic className="h-4 w-4" />
48
- * </ToggleGroupItem>
49
- * <ToggleGroupItem value="underline" aria-label="Toggle underline">
50
- * <Underline className="h-4 w-4" />
51
- * </ToggleGroupItem>
52
- * </ToggleGroup>
183
+ * import { Bold, Italic, Underline } from "lucide-react";
184
+ *
185
+ * function TextEditor() {
186
+ * const [formatting, setFormatting] = useState<string[]>(["bold"]);
187
+ *
188
+ * return (
189
+ * <ToggleGroup
190
+ * type="multiple"
191
+ * value={formatting}
192
+ * onValueChange={setFormatting}
193
+ * aria-label="Text formatting"
194
+ * >
195
+ * <ToggleGroupItem value="bold" aria-label="Toggle bold">
196
+ * <Bold className="h-4 w-4" />
197
+ * </ToggleGroupItem>
198
+ * <ToggleGroupItem value="italic" aria-label="Toggle italic">
199
+ * <Italic className="h-4 w-4" />
200
+ * </ToggleGroupItem>
201
+ * <ToggleGroupItem value="underline" aria-label="Toggle underline">
202
+ * <Underline className="h-4 w-4" />
203
+ * </ToggleGroupItem>
204
+ * </ToggleGroup>
205
+ * );
206
+ * }
53
207
  * ```
54
208
  *
55
- * @example
209
+ * @example Text-based options with outline variant
56
210
  * ```tsx
57
- * // Text-based options with variants
58
- * <ToggleGroup type="single" variant="outline" size="sm">
211
+ * <ToggleGroup type="single" variant="outline" size="sm" defaultValue="draft">
59
212
  * <ToggleGroupItem value="draft">Draft</ToggleGroupItem>
213
+ * <ToggleGroupItem value="review">In Review</ToggleGroupItem>
60
214
  * <ToggleGroupItem value="published">Published</ToggleGroupItem>
61
215
  * <ToggleGroupItem value="archived">Archived</ToggleGroupItem>
62
216
  * </ToggleGroup>
63
217
  * ```
64
218
  *
65
- * @param type - Selection mode: "single" for radio-like behavior, "multiple" for checkbox-like
66
- * @param variant - Visual style: "default" (subtle) or "outline" (bordered)
67
- * @param size - Size variant: "sm", "default", or "lg"
68
- * @param disabled - Whether the entire group is disabled
69
- * @param defaultValue - Initial selected value(s) - string for single, array for multiple
70
- * @param value - Controlled selected value(s) - string for single, array for multiple
71
- * @param onValueChange - Callback when selection changes
219
+ * @example Vertical orientation for sidebar controls
220
+ * ```tsx
221
+ * <ToggleGroup
222
+ * type="multiple"
223
+ * orientation="vertical"
224
+ * variant="outline"
225
+ * className="flex-col"
226
+ * >
227
+ * <ToggleGroupItem value="notifications">Notifications</ToggleGroupItem>
228
+ * <ToggleGroupItem value="sidebar">Show Sidebar</ToggleGroupItem>
229
+ * <ToggleGroupItem value="minimap">Show Minimap</ToggleGroupItem>
230
+ * </ToggleGroup>
231
+ * ```
232
+ *
233
+ * @example Mixed content with icons and text
234
+ * ```tsx
235
+ * <ToggleGroup type="single" variant="outline" size="lg">
236
+ * <ToggleGroupItem value="grid">
237
+ * <Grid className="h-4 w-4" />
238
+ * Grid View
239
+ * </ToggleGroupItem>
240
+ * <ToggleGroupItem value="list">
241
+ * <List className="h-4 w-4" />
242
+ * List View
243
+ * </ToggleGroupItem>
244
+ * </ToggleGroup>
245
+ * ```
246
+ *
247
+ * @variant default - Subtle background styling with transparent base, accent color when pressed
248
+ * @variant outline - Bordered styling with subtle shadow, maintains outline when pressed
72
249
  *
73
250
  * @accessibility
74
- * - Uses role="group" with appropriate ARIA attributes
75
- * - Arrow keys navigate between items with roving tabindex
76
- * - Space or Enter key toggles item selection
77
- * - Home/End keys jump to first/last items
251
+ * - Implements WAI-ARIA ToggleButton pattern with proper roles and states
252
+ * - Uses roving tabindex for keyboard navigation between items
253
+ * - Arrow keys navigate between items (direction based on orientation)
254
+ * - Space or Enter key toggles item selection state
255
+ * - Home key moves focus to first item, End key to last item
256
+ * - Focus wraps from last to first item when loop=true (default)
78
257
  * - Supports disabled state for individual items or entire group
79
- * - Screen readers announce selection state changes
258
+ * - Screen readers announce selection state changes via aria-pressed
259
+ * - Proper focus management with visible focus indicators
260
+ * - Group labeling via aria-label or aria-labelledby recommended
80
261
  *
81
- * @see {@link ToggleGroupItem} - Individual toggle items within the group
82
- * @see {@link Toggle} - Standalone toggle button component
83
- * @see {@link https://ui.shadcn.com/docs/components/toggle-group} - Design system documentation
262
+ * @see {@link ToggleGroupItem} Individual toggle items within the group
263
+ * @see {@link Toggle} Standalone toggle button component
264
+ * @see {@link https://www.radix-ui.com/primitives/docs/components/toggle-group} Radix UI ToggleGroup primitive
265
+ * @see {@link https://ui.shadcn.com/docs/components/toggle-group} Design system documentation
266
+ * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/button/} WAI-ARIA Toggle Button pattern
84
267
  * @since 1.0.0
85
268
  */
86
269
  function ToggleGroup({
@@ -89,8 +272,7 @@ function ToggleGroup({
89
272
  size,
90
273
  children,
91
274
  ...props
92
- }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
93
- VariantProps<typeof toggleVariants>) {
275
+ }: React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants>) {
94
276
  return (
95
277
  <ToggleGroupPrimitive.Root
96
278
  data-slot="toggle-group"
@@ -112,56 +294,86 @@ function ToggleGroup({
112
294
  /**
113
295
  * Toggle Group Item - Individual selectable item within a ToggleGroup
114
296
  *
115
- * Represents a single option within a ToggleGroup component. Automatically inherits
116
- * variant and size styling from the parent ToggleGroup context, but these can be
117
- * overridden for specific items if needed. Supports icons, text, or mixed content.
297
+ * Represents a single toggleable option within a ToggleGroup component. Each item
298
+ * automatically inherits variant and size styling from the parent ToggleGroup context
299
+ * through React Context, but these can be overridden for specific styling needs.
300
+ * Supports flexible content including icons, text, or mixed combinations.
301
+ *
302
+ * The component participates in the parent ToggleGroup's keyboard navigation and
303
+ * selection behavior, with proper ARIA attributes for accessibility. Focus management
304
+ * and selection state are handled automatically by the Radix UI primitive.
118
305
  *
119
- * @example
306
+ * @example Text-based item with inherited styling
120
307
  * ```tsx
121
- * // Text-based item
122
308
  * <ToggleGroupItem value="draft">Draft</ToggleGroupItem>
123
309
  * ```
124
310
  *
125
- * @example
311
+ * @example Icon-only item with required accessibility label
126
312
  * ```tsx
127
- * // Icon-only item (requires aria-label)
313
+ * import { Bold } from "lucide-react";
314
+ *
128
315
  * <ToggleGroupItem value="bold" aria-label="Toggle bold formatting">
129
316
  * <Bold className="h-4 w-4" />
130
317
  * </ToggleGroupItem>
131
318
  * ```
132
319
  *
133
- * @example
320
+ * @example Mixed content with icon and descriptive text
134
321
  * ```tsx
135
- * // Mixed content with icon and text
136
- * <ToggleGroupItem value="bold">
137
- * <Bold className="h-4 w-4" />
138
- * Bold
322
+ * import { Calendar } from "lucide-react";
323
+ *
324
+ * <ToggleGroupItem value="calendar">
325
+ * <Calendar className="h-4 w-4" />
326
+ * Calendar View
327
+ * </ToggleGroupItem>
328
+ * ```
329
+ *
330
+ * @example Override inherited styling for special emphasis
331
+ * ```tsx
332
+ * <ToggleGroupItem
333
+ * value="premium"
334
+ * variant="outline"
335
+ * size="lg"
336
+ * className="border-gold text-gold"
337
+ * >
338
+ * Premium Feature
139
339
  * </ToggleGroupItem>
140
340
  * ```
141
341
  *
142
- * @example
342
+ * @example Disabled item within functional group
143
343
  * ```tsx
144
- * // Override inherited styling
145
- * <ToggleGroupItem value="special" variant="outline" size="lg">
146
- * Special Option
344
+ * <ToggleGroupItem
345
+ * value="coming-soon"
346
+ * disabled
347
+ * aria-label="Feature coming soon"
348
+ * >
349
+ * <Sparkles className="h-4 w-4" />
350
+ * Coming Soon
147
351
  * </ToggleGroupItem>
148
352
  * ```
149
353
  *
150
- * @param value - Unique identifier for this item within the group (required)
151
- * @param disabled - Whether this specific item is disabled
152
- * @param variant - Override variant from parent ToggleGroup
153
- * @param size - Override size from parent ToggleGroup
154
- * @param children - Content to display (icons, text, or both)
354
+ * @example Using asChild for custom element composition
355
+ * ```tsx
356
+ * <ToggleGroupItem value="custom" asChild>
357
+ * <a href="/settings" className="no-underline">
358
+ * <Settings className="h-4 w-4" />
359
+ * Settings
360
+ * </a>
361
+ * </ToggleGroupItem>
362
+ * ```
155
363
  *
156
364
  * @accessibility
157
- * - Participates in parent ToggleGroup's keyboard navigation
158
- * - Uses aria-pressed to indicate selection state
159
- * - Supports focus management with visible focus indicators
160
- * - For icon-only items, always provide aria-label for screen readers
161
- * - Disabled items are excluded from keyboard navigation
162
- *
163
- * @see {@link ToggleGroup} - Parent container component
164
- * @see {@link Toggle} - Standalone toggle button
365
+ * - Participates in parent ToggleGroup's roving tabindex navigation
366
+ * - Uses aria-pressed attribute to indicate selection state ("true"/"false")
367
+ * - Supports focus management with visible focus indicators and proper focus ring
368
+ * - For icon-only items, always provide aria-label for screen reader users
369
+ * - Disabled items are excluded from keyboard navigation and marked non-interactive
370
+ * - Inherits semantic meaning from parent group's aria-label or aria-labelledby
371
+ * - Proper button semantics with keyboard activation (Space/Enter)
372
+ *
373
+ * @see {@link ToggleGroup} Parent container component that manages selection state
374
+ * @see {@link Toggle} Standalone toggle button for independent usage
375
+ * @see {@link https://www.radix-ui.com/primitives/docs/components/toggle-group} Radix UI primitive documentation
376
+ * @since 1.0.0
165
377
  */
166
378
  function ToggleGroupItem({
167
379
  className,
@@ -169,8 +381,7 @@ function ToggleGroupItem({
169
381
  variant,
170
382
  size,
171
383
  ...props
172
- }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
173
- VariantProps<typeof toggleVariants>) {
384
+ }: React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>) {
174
385
  const context = React.useContext(ToggleGroupContext);
175
386
 
176
387
  return (
@@ -1,22 +1,35 @@
1
1
  import * as React from "react";
2
2
  import * as TogglePrimitive from "@radix-ui/react-toggle";
3
- import { cva, type VariantProps } from "class-variance-authority";
3
+ import { cva } from "class-variance-authority";
4
4
 
5
5
  import { cn } from "@/lib/utils";
6
6
 
7
+ /**
8
+ * Toggle component variant configuration
9
+ *
10
+ * Defines visual styles and sizing options for the toggle component
11
+ * with proper state indicators and accessibility features.
12
+ *
13
+ * @variant default - Clean transparent background with hover states
14
+ * @variant outline - Bordered style with subtle shadow for emphasis
15
+ *
16
+ * @size sm - Compact 32px height for dense layouts
17
+ * @size default - Standard 36px height for general use
18
+ * @size lg - Large 40px height for prominent actions
19
+ */
7
20
  const toggleVariants = cva(
8
21
  "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
9
22
  {
10
23
  variants: {
11
24
  variant: {
12
- default: "bg-transparent",
25
+ default: "bg-transparent", // Clean transparent background with hover states
13
26
  outline:
14
- "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
27
+ "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground", // Bordered style with subtle shadow for emphasis
15
28
  },
16
29
  size: {
17
- default: "h-9 px-2 min-w-9",
18
- sm: "h-8 px-1.5 min-w-8",
19
- lg: "h-10 px-2.5 min-w-10",
30
+ default: "h-9 px-2 min-w-9", // Standard 36px height for general use
31
+ sm: "h-8 px-1.5 min-w-8", // Compact 32px height for dense layouts
32
+ lg: "h-10 px-2.5 min-w-10", // Large 40px height for prominent actions
20
33
  },
21
34
  },
22
35
  defaultVariants: {
@@ -26,18 +39,46 @@ const toggleVariants = cva(
26
39
  },
27
40
  );
28
41
 
42
+ /**
43
+ * Props for Toggle component
44
+ *
45
+ * Combines Radix UI Toggle primitive props with custom variant styling options.
46
+ * Supports both controlled and uncontrolled usage patterns.
47
+ */
48
+ type ToggleProps = {
49
+ /** Whether to render as a child element instead of the default button */
50
+ asChild?: boolean;
51
+ /** The pressed state of the toggle when initially rendered (uncontrolled) @default false */
52
+ defaultPressed?: boolean;
53
+ /** The controlled pressed state of the toggle */
54
+ pressed?: boolean;
55
+ /** Event handler called when the pressed state changes */
56
+ onPressedChange?: (pressed: boolean) => void;
57
+ /** When true, prevents user interaction with the toggle */
58
+ disabled?: boolean;
59
+ /** Visual style variant for the toggle appearance */
60
+ variant?: "default" | "outline";
61
+ /** Size variant that affects dimensions and padding */
62
+ size?: "sm" | "default" | "lg";
63
+ /** Additional CSS classes for custom styling */
64
+ className?: string;
65
+ /** Toggle content - typically icons, text, or both */
66
+ children?: React.ReactNode;
67
+ } & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'disabled' | 'children'>;
68
+
29
69
  /**
30
70
  * A two-state button that can be either on or off
31
71
  *
32
72
  * The Toggle component provides an accessible button with on/off state functionality.
33
73
  * Built on Radix UI Toggle primitives with customizable variants and sizes.
34
- * Ideal for text formatting controls, settings toggles, and any binary state controls.
74
+ * Perfect for text formatting controls, feature toggles, and any binary state controls.
75
+ * Automatically manages ARIA attributes and provides keyboard navigation.
35
76
  *
36
- * @example Basic usage with icon
77
+ * @example Basic toggle with icon
37
78
  * ```tsx
38
79
  * import { Bold } from "lucide-react"
39
80
  *
40
- * <Toggle aria-label="Toggle bold">
81
+ * <Toggle aria-label="Toggle bold formatting">
41
82
  * <Bold className="h-4 w-4" />
42
83
  * </Toggle>
43
84
  * ```
@@ -55,7 +96,7 @@ const toggleVariants = cva(
55
96
  * </Toggle>
56
97
  * ```
57
98
  *
58
- * @example With text and outline variant
99
+ * @example Toggle with text and outline variant
59
100
  * ```tsx
60
101
  * <Toggle variant="outline" size="lg">
61
102
  * <Italic className="h-4 w-4" />
@@ -65,42 +106,88 @@ const toggleVariants = cva(
65
106
  *
66
107
  * @example Text formatting toolbar
67
108
  * ```tsx
68
- * <div className="flex gap-1">
69
- * <Toggle pressed={bold} onPressedChange={setBold}>
109
+ * <div className="flex gap-1 p-2 border rounded-md">
110
+ * <Toggle
111
+ * pressed={formatting.bold}
112
+ * onPressedChange={(pressed) => setFormatting(prev => ({ ...prev, bold: pressed }))}
113
+ * aria-label="Bold"
114
+ * >
70
115
  * <Bold className="h-4 w-4" />
71
116
  * </Toggle>
72
- * <Toggle pressed={italic} onPressedChange={setItalic}>
117
+ * <Toggle
118
+ * pressed={formatting.italic}
119
+ * onPressedChange={(pressed) => setFormatting(prev => ({ ...prev, italic: pressed }))}
120
+ * aria-label="Italic"
121
+ * >
73
122
  * <Italic className="h-4 w-4" />
74
123
  * </Toggle>
124
+ * <Toggle
125
+ * pressed={formatting.underline}
126
+ * onPressedChange={(pressed) => setFormatting(prev => ({ ...prev, underline: pressed }))}
127
+ * aria-label="Underline"
128
+ * >
129
+ * <Underline className="h-4 w-4" />
130
+ * </Toggle>
75
131
  * </div>
76
132
  * ```
77
133
  *
134
+ * @example Toggle group for settings
135
+ * ```tsx
136
+ * <div className="space-y-2">
137
+ * <div className="flex items-center justify-between">
138
+ * <Label htmlFor="notifications">Notifications</Label>
139
+ * <Toggle
140
+ * id="notifications"
141
+ * pressed={settings.notifications}
142
+ * onPressedChange={(pressed) => updateSetting('notifications', pressed)}
143
+ * variant="outline"
144
+ * >
145
+ * <Bell className="h-4 w-4" />
146
+ * </Toggle>
147
+ * </div>
148
+ * <div className="flex items-center justify-between">
149
+ * <Label htmlFor="dark-mode">Dark Mode</Label>
150
+ * <Toggle
151
+ * id="dark-mode"
152
+ * pressed={settings.darkMode}
153
+ * onPressedChange={(pressed) => updateSetting('darkMode', pressed)}
154
+ * variant="outline"
155
+ * >
156
+ * <Moon className="h-4 w-4" />
157
+ * </Toggle>
158
+ * </div>
159
+ * </div>
160
+ * ```
161
+ *
162
+ * @example Disabled state with tooltip
163
+ * ```tsx
164
+ * <Tooltip>
165
+ * <TooltipTrigger asChild>
166
+ * <Toggle disabled aria-label="Unavailable feature">
167
+ * <Lock className="h-4 w-4" />
168
+ * Pro Feature
169
+ * </Toggle>
170
+ * </TooltipTrigger>
171
+ * <TooltipContent>
172
+ * <p>This feature requires a Pro subscription</p>
173
+ * </TooltipContent>
174
+ * </Tooltip>
175
+ * ```
176
+ *
78
177
  * @accessibility
79
- * - Supports keyboard navigation (Space/Enter to toggle)
80
- * - Automatically manages aria-pressed attribute
81
- * - Requires aria-label for icon-only toggles
82
- * - Focus management with visible focus indicators
83
- * - Disabled state properly communicated to assistive technology
178
+ * - Keyboard Support: Space and Enter keys activate/deactivate the toggle
179
+ * - Screen Reader Support: Automatically manages aria-pressed attribute ("true"/"false")
180
+ * - Focus Management: Visible focus indicators with customizable focus ring
181
+ * - State Communication: Uses data-state attribute ("on"/"off") for styling pressed state
182
+ * - Disabled State: Properly communicated to assistive technology with aria-disabled
183
+ * - Labeling: Requires accessible name via aria-label or aria-labelledby for icon-only toggles
184
+ * - High Contrast: Maintains visibility in high contrast mode with proper color combinations
84
185
  *
85
- * @see {@link https://ui.shadcn.com/docs/components/toggle} shadcn/ui Toggle documentation
86
- * @since 1.0.0
186
+ * @see {@link https://www.radix-ui.com/primitives/docs/components/toggle} Radix UI Toggle Documentation
187
+ * @see {@link https://ui.shadcn.com/docs/components/toggle} shadcn/ui Toggle Documentation
87
188
  * @see {@link ToggleGroup} For mutually exclusive toggle groups
189
+ * @since 1.0.0
88
190
  */
89
- /**
90
- * Toggle component props
91
- *
92
- * @param className - Additional CSS classes to apply
93
- * @param variant - Visual style variant ("default" | "outline")
94
- * @param size - Size variant ("sm" | "default" | "lg")
95
- * @param pressed - Controlled pressed state
96
- * @param defaultPressed - Default pressed state for uncontrolled usage
97
- * @param onPressedChange - Callback fired when pressed state changes
98
- * @param disabled - Whether the toggle is disabled
99
- * @param children - Toggle content (typically icons or text)
100
- * @param ...props - Additional props passed to Radix Toggle primitive
101
- */
102
- type ToggleProps = React.ComponentProps<typeof TogglePrimitive.Root> &
103
- VariantProps<typeof toggleVariants>;
104
191
 
105
192
  function Toggle({ className, variant, size, ...props }: ToggleProps) {
106
193
  return (
@@ -112,4 +199,6 @@ function Toggle({ className, variant, size, ...props }: ToggleProps) {
112
199
  );
113
200
  }
114
201
 
202
+ Toggle.displayName = "Toggle";
203
+
115
204
  export { Toggle, toggleVariants };