@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.
- package/dist/components/ui/accordion.d.ts +1 -25
- package/dist/components/ui/accordion.d.ts.map +1 -1
- package/dist/components/ui/alert-dialog.d.ts +240 -46
- package/dist/components/ui/alert-dialog.d.ts.map +1 -1
- package/dist/components/ui/alert.d.ts +73 -11
- package/dist/components/ui/alert.d.ts.map +1 -1
- package/dist/components/ui/aspect-ratio.d.ts +44 -10
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -1
- package/dist/components/ui/avatar.d.ts +117 -33
- package/dist/components/ui/avatar.d.ts.map +1 -1
- package/dist/components/ui/badge.d.ts +50 -71
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb.d.ts +231 -49
- package/dist/components/ui/breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/button.d.ts +189 -71
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/calendar.d.ts +197 -40
- package/dist/components/ui/calendar.d.ts.map +1 -1
- package/dist/components/ui/card.d.ts +7 -22
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/carousel.d.ts +369 -99
- package/dist/components/ui/carousel.d.ts.map +1 -1
- package/dist/components/ui/chart.d.ts.map +1 -1
- package/dist/components/ui/checkbox.d.ts +110 -38
- package/dist/components/ui/checkbox.d.ts.map +1 -1
- package/dist/components/ui/collapsible.d.ts +246 -61
- package/dist/components/ui/collapsible.d.ts.map +1 -1
- package/dist/components/ui/combobox.d.ts +207 -159
- package/dist/components/ui/combobox.d.ts.map +1 -1
- package/dist/components/ui/command.d.ts +336 -67
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/container.d.ts +159 -64
- package/dist/components/ui/container.d.ts.map +1 -1
- package/dist/components/ui/context-menu.d.ts +321 -39
- package/dist/components/ui/context-menu.d.ts.map +1 -1
- package/dist/components/ui/date-picker.d.ts +113 -86
- package/dist/components/ui/date-picker.d.ts.map +1 -1
- package/dist/components/ui/dialog.d.ts +106 -25
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/drawer.d.ts +388 -59
- package/dist/components/ui/drawer.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.d.ts +521 -74
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/empty-state.d.ts +148 -76
- package/dist/components/ui/empty-state.d.ts.map +1 -1
- package/dist/components/ui/hover-card.d.ts +253 -34
- package/dist/components/ui/hover-card.d.ts.map +1 -1
- package/dist/components/ui/input.d.ts +143 -44
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/label.d.ts +0 -8
- package/dist/components/ui/label.d.ts.map +1 -1
- package/dist/components/ui/menubar.d.ts +288 -46
- package/dist/components/ui/menubar.d.ts.map +1 -1
- package/dist/components/ui/navigation-menu.d.ts +444 -127
- package/dist/components/ui/navigation-menu.d.ts.map +1 -1
- package/dist/components/ui/pagination.d.ts +342 -66
- package/dist/components/ui/pagination.d.ts.map +1 -1
- package/dist/components/ui/popover.d.ts +0 -8
- package/dist/components/ui/popover.d.ts.map +1 -1
- package/dist/components/ui/progress.d.ts +88 -30
- package/dist/components/ui/progress.d.ts.map +1 -1
- package/dist/components/ui/radio-group.d.ts +189 -45
- package/dist/components/ui/radio-group.d.ts.map +1 -1
- package/dist/components/ui/resizable.d.ts +178 -62
- package/dist/components/ui/resizable.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.d.ts +180 -21
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/select.d.ts +382 -60
- package/dist/components/ui/select.d.ts.map +1 -1
- package/dist/components/ui/separator.d.ts +52 -39
- package/dist/components/ui/separator.d.ts.map +1 -1
- package/dist/components/ui/sheet.d.ts +144 -27
- package/dist/components/ui/sheet.d.ts.map +1 -1
- package/dist/components/ui/sidebar.d.ts +81 -31
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/skeleton.d.ts +94 -32
- package/dist/components/ui/skeleton.d.ts.map +1 -1
- package/dist/components/ui/slider.d.ts +37 -31
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/sonner.d.ts +280 -46
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/stack.d.ts +289 -148
- package/dist/components/ui/stack.d.ts.map +1 -1
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts +1 -2
- package/dist/components/ui/stories/aspect-ratio.stories.d.ts.map +1 -1
- package/dist/components/ui/stories/container.stories.d.ts +2 -3
- package/dist/components/ui/stories/container.stories.d.ts.map +1 -1
- package/dist/components/ui/stories/empty-state.stories.d.ts +2 -2
- package/dist/components/ui/stories/scroll-area.stories.d.ts +1 -2
- package/dist/components/ui/stories/scroll-area.stories.d.ts.map +1 -1
- package/dist/components/ui/stories/stack.stories.d.ts +1 -1
- package/dist/components/ui/stories/text-field.stories.d.ts +7 -1
- package/dist/components/ui/stories/text-field.stories.d.ts.map +1 -1
- package/dist/components/ui/switch.d.ts +44 -38
- package/dist/components/ui/switch.d.ts.map +1 -1
- package/dist/components/ui/table.d.ts +33 -0
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/tabs.d.ts +4 -22
- package/dist/components/ui/tabs.d.ts.map +1 -1
- package/dist/components/ui/text-field.d.ts +170 -84
- package/dist/components/ui/text-field.d.ts.map +1 -1
- package/dist/components/ui/textarea.d.ts +106 -29
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/theme-toggle.d.ts +190 -65
- package/dist/components/ui/theme-toggle.d.ts.map +1 -1
- package/dist/components/ui/theme.d.ts +107 -23
- package/dist/components/ui/theme.d.ts.map +1 -1
- package/dist/components/ui/toggle-group.d.ts +143 -67
- package/dist/components/ui/toggle-group.d.ts.map +1 -1
- package/dist/components/ui/toggle.d.ts +118 -30
- package/dist/components/ui/toggle.d.ts.map +1 -1
- package/dist/components/ui/tooltip.d.ts +152 -28
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/typography.d.ts +452 -134
- package/dist/components/ui/typography.d.ts.map +1 -1
- package/dist/index.js +9388 -8281
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/llms.txt +173 -3
- package/package.json +5 -2
- package/src/components/ui/accordion.tsx +112 -27
- package/src/components/ui/alert-dialog.tsx +401 -46
- package/src/components/ui/alert.tsx +114 -11
- package/src/components/ui/aspect-ratio.tsx +69 -14
- package/src/components/ui/avatar.tsx +179 -33
- package/src/components/ui/badge.tsx +74 -75
- package/src/components/ui/breadcrumb.tsx +335 -50
- package/src/components/ui/button.tsx +198 -90
- package/src/components/ui/calendar.tsx +867 -43
- package/src/components/ui/card.tsx +140 -33
- package/src/components/ui/carousel.tsx +529 -98
- package/src/components/ui/chart.tsx +222 -1
- package/src/components/ui/checkbox.tsx +176 -38
- package/src/components/ui/collapsible.tsx +321 -67
- package/src/components/ui/combobox.tsx +284 -83
- package/src/components/ui/command.tsx +527 -67
- package/src/components/ui/container.tsx +217 -65
- package/src/components/ui/context-menu.tsx +716 -51
- package/src/components/ui/date-picker.tsx +228 -38
- package/src/components/ui/dialog.tsx +270 -33
- package/src/components/ui/drawer.tsx +546 -67
- package/src/components/ui/dropdown-menu.tsx +657 -74
- package/src/components/ui/empty-state.tsx +241 -82
- package/src/components/ui/hover-card.tsx +328 -39
- package/src/components/ui/input.tsx +207 -44
- package/src/components/ui/label.tsx +98 -8
- package/src/components/ui/menubar.tsx +587 -54
- package/src/components/ui/navigation-menu.tsx +557 -128
- package/src/components/ui/pagination.tsx +561 -79
- package/src/components/ui/popover.tsx +119 -8
- package/src/components/ui/progress.tsx +131 -29
- package/src/components/ui/radio-group.tsx +260 -51
- package/src/components/ui/resizable.tsx +289 -63
- package/src/components/ui/scroll-area.tsx +377 -66
- package/src/components/ui/select.tsx +545 -60
- package/src/components/ui/separator.tsx +146 -40
- package/src/components/ui/sheet.tsx +348 -31
- package/src/components/ui/sidebar.tsx +471 -29
- package/src/components/ui/skeleton.tsx +114 -32
- package/src/components/ui/slider.tsx +77 -31
- package/src/components/ui/sonner.tsx +574 -46
- package/src/components/ui/stack.tsx +423 -101
- package/src/components/ui/switch.tsx +78 -39
- package/src/components/ui/table.tsx +170 -4
- package/src/components/ui/tabs.tsx +108 -22
- package/src/components/ui/text-field.tsx +226 -81
- package/src/components/ui/textarea.tsx +180 -29
- package/src/components/ui/theme-toggle.tsx +313 -65
- package/src/components/ui/theme.tsx +117 -23
- package/src/components/ui/toggle-group.tsx +280 -69
- package/src/components/ui/toggle.tsx +124 -35
- package/src/components/ui/tooltip.tsx +239 -29
- package/src/components/ui/typography.tsx +1115 -165
|
@@ -4,6 +4,142 @@ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
|
|
4
4
|
|
|
5
5
|
import { cn } from "@/lib/utils";
|
|
6
6
|
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Documentation Props Types (Internal - Not exported)
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Props for DropdownMenu (Documentation only - NOT used in component implementation)
|
|
13
|
+
* These types are for documentation generation and should not replace Radix inferred types
|
|
14
|
+
*/
|
|
15
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
16
|
+
type DropdownMenuDocsProps = {
|
|
17
|
+
/** Whether the dropdown is initially open (uncontrolled mode) @default false */
|
|
18
|
+
defaultOpen?: boolean;
|
|
19
|
+
/** Whether the dropdown is open (controlled mode) */
|
|
20
|
+
open?: boolean;
|
|
21
|
+
/** Callback fired when the open state changes */
|
|
22
|
+
onOpenChange?: (open: boolean) => void;
|
|
23
|
+
/** Whether the dropdown should be modal (blocks interaction with outside elements) @default true */
|
|
24
|
+
modal?: boolean;
|
|
25
|
+
/** The reading direction of the dropdown menu @default "ltr" */
|
|
26
|
+
dir?: "ltr" | "rtl";
|
|
27
|
+
/** Child elements - typically DropdownMenuTrigger and DropdownMenuContent */
|
|
28
|
+
children?: React.ReactNode;
|
|
29
|
+
} & React.ComponentProps<typeof DropdownMenuPrimitive.Root>;
|
|
30
|
+
|
|
31
|
+
/** Props for DropdownMenuTrigger (Documentation only) */
|
|
32
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
33
|
+
type DropdownMenuTriggerDocsProps = {
|
|
34
|
+
/** Merge props onto the immediate child instead of rendering a wrapper element @default false */
|
|
35
|
+
asChild?: boolean;
|
|
36
|
+
/** Child element that will trigger the dropdown menu */
|
|
37
|
+
children?: React.ReactNode;
|
|
38
|
+
} & React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>;
|
|
39
|
+
|
|
40
|
+
/** Props for DropdownMenuContent (Documentation only) */
|
|
41
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
42
|
+
type DropdownMenuContentDocsProps = {
|
|
43
|
+
/** Merge props onto the immediate child instead of rendering a wrapper element @default false */
|
|
44
|
+
asChild?: boolean;
|
|
45
|
+
/** When true, keyboard navigation will loop from last to first item and vice versa @default false */
|
|
46
|
+
loop?: boolean;
|
|
47
|
+
/** The preferred side of the trigger to render against @default "bottom" */
|
|
48
|
+
side?: "top" | "right" | "bottom" | "left";
|
|
49
|
+
/** Distance in pixels from the trigger @default 4 */
|
|
50
|
+
sideOffset?: number;
|
|
51
|
+
/** The preferred alignment against the trigger @default "center" */
|
|
52
|
+
align?: "start" | "center" | "end";
|
|
53
|
+
/** Distance in pixels from the align point @default 0 */
|
|
54
|
+
alignOffset?: number;
|
|
55
|
+
/** Whether to avoid collisions with viewport boundaries @default true */
|
|
56
|
+
avoidCollisions?: boolean;
|
|
57
|
+
/** Element positioning behavior relative to the viewport */
|
|
58
|
+
sticky?: "partial" | "always";
|
|
59
|
+
/** Whether to hide the content when the reference element is fully occluded @default false */
|
|
60
|
+
hideWhenDetached?: boolean;
|
|
61
|
+
/** CSS class name for custom styling */
|
|
62
|
+
className?: string;
|
|
63
|
+
/** Child menu items, labels, separators, and groups */
|
|
64
|
+
children?: React.ReactNode;
|
|
65
|
+
} & React.ComponentProps<typeof DropdownMenuPrimitive.Content>;
|
|
66
|
+
|
|
67
|
+
/** Props for DropdownMenuItem (Documentation only) */
|
|
68
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
69
|
+
type DropdownMenuItemDocsProps = {
|
|
70
|
+
/** Whether the item is disabled and cannot be selected @default false */
|
|
71
|
+
disabled?: boolean;
|
|
72
|
+
/** Callback fired when the item is selected via click or keyboard */
|
|
73
|
+
onSelect?: (event: Event) => void;
|
|
74
|
+
/** Optional text value used for typeahead search functionality */
|
|
75
|
+
textValue?: string;
|
|
76
|
+
/** Whether to add extra left padding to align with items that have icons @default false */
|
|
77
|
+
inset?: boolean;
|
|
78
|
+
/** Visual variant of the menu item for semantic distinction @default "default" */
|
|
79
|
+
variant?: "default" | "destructive";
|
|
80
|
+
/** CSS class name for custom styling */
|
|
81
|
+
className?: string;
|
|
82
|
+
/** Item content - text, icons, or other React elements */
|
|
83
|
+
children?: React.ReactNode;
|
|
84
|
+
} & React.ComponentProps<typeof DropdownMenuPrimitive.Item>;
|
|
85
|
+
|
|
86
|
+
/** Props for DropdownMenuCheckboxItem (Documentation only) */
|
|
87
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
88
|
+
type DropdownMenuCheckboxItemDocsProps = {
|
|
89
|
+
/** The checked state of the checkbox item */
|
|
90
|
+
checked?: boolean | "indeterminate";
|
|
91
|
+
/** Callback fired when the checked state changes */
|
|
92
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
93
|
+
/** Whether the item is disabled and cannot be interacted with @default false */
|
|
94
|
+
disabled?: boolean;
|
|
95
|
+
/** Callback fired when the item is selected via click or keyboard */
|
|
96
|
+
onSelect?: (event: Event) => void;
|
|
97
|
+
/** Optional text value used for typeahead search functionality */
|
|
98
|
+
textValue?: string;
|
|
99
|
+
/** Whether to add extra left padding to align with items that have icons @default false */
|
|
100
|
+
inset?: boolean;
|
|
101
|
+
/** CSS class name for custom styling */
|
|
102
|
+
className?: string;
|
|
103
|
+
/** Item content - automatically includes checkbox indicator */
|
|
104
|
+
children?: React.ReactNode;
|
|
105
|
+
} & React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>;
|
|
106
|
+
|
|
107
|
+
/** Props for DropdownMenuRadioGroup (Documentation only) */
|
|
108
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
109
|
+
type DropdownMenuRadioGroupDocsProps = {
|
|
110
|
+
/** The currently selected value in the radio group */
|
|
111
|
+
value?: string;
|
|
112
|
+
/** Callback fired when the selection changes to a different value */
|
|
113
|
+
onValueChange?: (value: string) => void;
|
|
114
|
+
/** Whether the entire radio group is disabled @default false */
|
|
115
|
+
disabled?: boolean;
|
|
116
|
+
/** Radio item children within the group */
|
|
117
|
+
children?: React.ReactNode;
|
|
118
|
+
} & React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>;
|
|
119
|
+
|
|
120
|
+
/** Props for DropdownMenuRadioItem (Documentation only) */
|
|
121
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
122
|
+
type DropdownMenuRadioItemDocsProps = {
|
|
123
|
+
/** The unique value this radio item represents */
|
|
124
|
+
value: string;
|
|
125
|
+
/** Whether the item is disabled and cannot be selected @default false */
|
|
126
|
+
disabled?: boolean;
|
|
127
|
+
/** Callback fired when the item is selected via click or keyboard */
|
|
128
|
+
onSelect?: (event: Event) => void;
|
|
129
|
+
/** Optional text value used for typeahead search functionality */
|
|
130
|
+
textValue?: string;
|
|
131
|
+
/** Whether to add extra left padding to align with items that have icons @default false */
|
|
132
|
+
inset?: boolean;
|
|
133
|
+
/** CSS class name for custom styling */
|
|
134
|
+
className?: string;
|
|
135
|
+
/** Item content - automatically includes radio indicator */
|
|
136
|
+
children?: React.ReactNode;
|
|
137
|
+
} & React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>;
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// Main Component
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
7
143
|
/**
|
|
8
144
|
* A versatile dropdown menu component built on Radix UI primitives
|
|
9
145
|
*
|
|
@@ -11,10 +147,15 @@ import { cn } from "@/lib/utils";
|
|
|
11
147
|
* They're typically triggered by a button and appear as a floating panel with full
|
|
12
148
|
* keyboard navigation support, submenus, and various interactive item types.
|
|
13
149
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
150
|
+
* Built on Radix UI's DropdownMenu primitive with enhanced styling and type safety.
|
|
151
|
+
* Follows the WAI-ARIA Menu Button pattern for accessibility compliance.
|
|
152
|
+
*
|
|
153
|
+
* @param defaultOpen - Whether the dropdown is initially open (uncontrolled mode)
|
|
154
|
+
* @param open - Whether the dropdown is open (controlled mode)
|
|
155
|
+
* @param onOpenChange - Callback fired when the open state changes
|
|
156
|
+
* @param modal - Whether the dropdown should be modal (blocks interaction with outside elements)
|
|
157
|
+
* @param dir - The reading direction of the dropdown menu
|
|
16
158
|
*
|
|
17
|
-
* @component
|
|
18
159
|
* @example
|
|
19
160
|
* ```tsx
|
|
20
161
|
* // Basic dropdown menu
|
|
@@ -33,8 +174,10 @@ import { cn } from "@/lib/utils";
|
|
|
33
174
|
*
|
|
34
175
|
* @example
|
|
35
176
|
* ```tsx
|
|
36
|
-
* //
|
|
37
|
-
*
|
|
177
|
+
* // Controlled dropdown with alignment
|
|
178
|
+
* const [open, setOpen] = useState(false);
|
|
179
|
+
*
|
|
180
|
+
* <DropdownMenu open={open} onOpenChange={setOpen}>
|
|
38
181
|
* <DropdownMenuTrigger asChild>
|
|
39
182
|
* <Button variant="ghost" size="icon">
|
|
40
183
|
* <MoreHorizontal />
|
|
@@ -52,6 +195,9 @@ import { cn } from "@/lib/utils";
|
|
|
52
195
|
* @example
|
|
53
196
|
* ```tsx
|
|
54
197
|
* // Complex menu with checkboxes, radio groups, and submenus
|
|
198
|
+
* const [showPanel, setShowPanel] = useState(true);
|
|
199
|
+
* const [position, setPosition] = useState("top");
|
|
200
|
+
*
|
|
55
201
|
* <DropdownMenu>
|
|
56
202
|
* <DropdownMenuTrigger asChild>
|
|
57
203
|
* <Button>Advanced Menu</Button>
|
|
@@ -82,17 +228,19 @@ import { cn } from "@/lib/utils";
|
|
|
82
228
|
* @accessibility
|
|
83
229
|
* - Full keyboard navigation with arrow keys (Up/Down for navigation)
|
|
84
230
|
* - Enter/Space to activate items
|
|
85
|
-
* - Escape key closes the menu and restores focus
|
|
231
|
+
* - Escape key closes the menu and restores focus to the trigger
|
|
86
232
|
* - Home/End keys navigate to first/last item
|
|
87
233
|
* - Type-ahead search to jump to items by first letter
|
|
88
234
|
* - Left/Right arrow keys for submenu navigation
|
|
89
235
|
* - Proper ARIA roles (menu, menuitem, menuitemcheckbox, menuitemradio)
|
|
90
236
|
* - Focus management with focus trapping and restoration
|
|
91
237
|
* - Screen reader announcements for state changes
|
|
238
|
+
* - Supports roving tabindex for focus movement
|
|
92
239
|
*
|
|
93
240
|
* @see {@link ContextMenu} - For right-click context menus
|
|
94
241
|
* @see {@link Popover} - For rich content overlays
|
|
95
242
|
* @see {@link Select} - For single selection dropdowns
|
|
243
|
+
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu} - Radix UI documentation
|
|
96
244
|
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu} - shadcn/ui documentation
|
|
97
245
|
* @since 1.0.0
|
|
98
246
|
*/
|
|
@@ -107,10 +255,18 @@ function DropdownMenu({
|
|
|
107
255
|
*
|
|
108
256
|
* Renders dropdown content outside of the normal DOM hierarchy to avoid
|
|
109
257
|
* z-index and overflow issues. Automatically used by DropdownMenuContent
|
|
110
|
-
* but can be used explicitly for
|
|
258
|
+
* but can be used explicitly for advanced positioning scenarios.
|
|
259
|
+
*
|
|
260
|
+
* @param container - Optional container element for portal rendering. If not provided, portals to document.body
|
|
111
261
|
*
|
|
112
|
-
* @
|
|
113
|
-
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```tsx
|
|
264
|
+
* <DropdownMenuPortal container={customContainer}>
|
|
265
|
+
* <DropdownMenuContent>
|
|
266
|
+
* <DropdownMenuItem>Item</DropdownMenuItem>
|
|
267
|
+
* </DropdownMenuContent>
|
|
268
|
+
* </DropdownMenuPortal>
|
|
269
|
+
* ```
|
|
114
270
|
* @since 1.0.0
|
|
115
271
|
*/
|
|
116
272
|
function DropdownMenuPortal({
|
|
@@ -122,13 +278,29 @@ function DropdownMenuPortal({
|
|
|
122
278
|
}
|
|
123
279
|
|
|
124
280
|
/**
|
|
125
|
-
*
|
|
281
|
+
* The element that triggers the dropdown menu
|
|
282
|
+
*
|
|
283
|
+
* Renders the interactive element that opens and closes the dropdown menu.
|
|
284
|
+
* Typically wraps a button or other interactive element using the asChild prop.
|
|
285
|
+
* Automatically receives proper ARIA attributes and keyboard event handlers.
|
|
286
|
+
*
|
|
287
|
+
* @param asChild - Merge props onto the immediate child instead of rendering a wrapper element
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```tsx
|
|
291
|
+
* // Basic trigger with button
|
|
292
|
+
* <DropdownMenuTrigger asChild>
|
|
293
|
+
* <Button variant="outline">Open Menu</Button>
|
|
294
|
+
* </DropdownMenuTrigger>
|
|
295
|
+
* ```
|
|
126
296
|
*
|
|
127
|
-
* @component
|
|
128
297
|
* @example
|
|
129
298
|
* ```tsx
|
|
299
|
+
* // Icon button trigger
|
|
130
300
|
* <DropdownMenuTrigger asChild>
|
|
131
|
-
* <Button>
|
|
301
|
+
* <Button variant="ghost" size="icon" aria-label="More options">
|
|
302
|
+
* <MoreVertical className="h-4 w-4" />
|
|
303
|
+
* </Button>
|
|
132
304
|
* </DropdownMenuTrigger>
|
|
133
305
|
* ```
|
|
134
306
|
* @since 1.0.0
|
|
@@ -145,13 +317,44 @@ function DropdownMenuTrigger({
|
|
|
145
317
|
}
|
|
146
318
|
|
|
147
319
|
/**
|
|
148
|
-
*
|
|
320
|
+
* The content container for dropdown menu items
|
|
321
|
+
*
|
|
322
|
+
* Contains all menu items and handles positioning relative to the trigger.
|
|
323
|
+
* Automatically portals content to avoid z-index issues and includes sophisticated
|
|
324
|
+
* collision detection to keep the menu visible within viewport boundaries.
|
|
325
|
+
*
|
|
326
|
+
* @param side - The preferred side of the trigger to render against
|
|
327
|
+
* @param sideOffset - Distance in pixels from the trigger
|
|
328
|
+
* @param align - The preferred alignment against the trigger
|
|
329
|
+
* @param alignOffset - Distance in pixels from the align point
|
|
330
|
+
* @param avoidCollisions - Whether to avoid collisions with viewport boundaries
|
|
331
|
+
* @param loop - When true, keyboard navigation will loop from last to first item
|
|
332
|
+
* @param sticky - Element positioning behavior relative to the viewport
|
|
333
|
+
* @param hideWhenDetached - Whether to hide the content when the reference element is fully occluded
|
|
149
334
|
*
|
|
150
|
-
* @component
|
|
151
335
|
* @example
|
|
152
336
|
* ```tsx
|
|
153
|
-
*
|
|
154
|
-
*
|
|
337
|
+
* // Basic content with default positioning
|
|
338
|
+
* <DropdownMenuContent>
|
|
339
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
340
|
+
* <DropdownMenuItem>Settings</DropdownMenuItem>
|
|
341
|
+
* </DropdownMenuContent>
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```tsx
|
|
346
|
+
* // Content with custom alignment and offset
|
|
347
|
+
* <DropdownMenuContent align="end" sideOffset={8}>
|
|
348
|
+
* <DropdownMenuItem>Edit</DropdownMenuItem>
|
|
349
|
+
* <DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
|
|
350
|
+
* </DropdownMenuContent>
|
|
351
|
+
* ```
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```tsx
|
|
355
|
+
* // Content with collision avoidance disabled
|
|
356
|
+
* <DropdownMenuContent avoidCollisions={false} side="top">
|
|
357
|
+
* <DropdownMenuItem>Always above trigger</DropdownMenuItem>
|
|
155
358
|
* </DropdownMenuContent>
|
|
156
359
|
* ```
|
|
157
360
|
* @since 1.0.0
|
|
@@ -160,7 +363,9 @@ function DropdownMenuContent({
|
|
|
160
363
|
className,
|
|
161
364
|
sideOffset = 4,
|
|
162
365
|
...props
|
|
163
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>
|
|
366
|
+
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content> & {
|
|
367
|
+
className?: string;
|
|
368
|
+
}) {
|
|
164
369
|
return (
|
|
165
370
|
<DropdownMenuPrimitive.Portal>
|
|
166
371
|
<DropdownMenuPrimitive.Content
|
|
@@ -181,15 +386,23 @@ function DropdownMenuContent({
|
|
|
181
386
|
*
|
|
182
387
|
* Used to create logical groupings of menu items, typically separated by
|
|
183
388
|
* DropdownMenuSeparator components. Helps with semantic organization and
|
|
184
|
-
*
|
|
389
|
+
* improves accessibility by providing proper group semantics to screen readers.
|
|
390
|
+
*
|
|
391
|
+
* @param asChild - Merge props onto the immediate child instead of rendering a wrapper element
|
|
185
392
|
*
|
|
186
|
-
* @component
|
|
187
393
|
* @example
|
|
188
394
|
* ```tsx
|
|
189
|
-
* <
|
|
190
|
-
* <
|
|
191
|
-
*
|
|
192
|
-
* </
|
|
395
|
+
* <DropdownMenuContent>
|
|
396
|
+
* <DropdownMenuGroup>
|
|
397
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
398
|
+
* <DropdownMenuItem>Account Settings</DropdownMenuItem>
|
|
399
|
+
* </DropdownMenuGroup>
|
|
400
|
+
* <DropdownMenuSeparator />
|
|
401
|
+
* <DropdownMenuGroup>
|
|
402
|
+
* <DropdownMenuItem>Help</DropdownMenuItem>
|
|
403
|
+
* <DropdownMenuItem>Support</DropdownMenuItem>
|
|
404
|
+
* </DropdownMenuGroup>
|
|
405
|
+
* </DropdownMenuContent>
|
|
193
406
|
* ```
|
|
194
407
|
* @since 1.0.0
|
|
195
408
|
*/
|
|
@@ -202,16 +415,51 @@ function DropdownMenuGroup({
|
|
|
202
415
|
}
|
|
203
416
|
|
|
204
417
|
/**
|
|
205
|
-
*
|
|
418
|
+
* A single interactive item in the dropdown menu
|
|
419
|
+
*
|
|
420
|
+
* Renders a clickable menu item with proper focus management and keyboard navigation.
|
|
421
|
+
* Supports different visual variants for semantic meaning (e.g., destructive actions).
|
|
422
|
+
* Includes built-in styling for icons, disabled states, and focus indicators.
|
|
423
|
+
*
|
|
424
|
+
* @param disabled - Whether the item is disabled and cannot be selected
|
|
425
|
+
* @param onSelect - Callback fired when the item is selected via click or keyboard
|
|
426
|
+
* @param textValue - Optional text value used for typeahead search functionality
|
|
427
|
+
* @param inset - Whether to add extra left padding to align with items that have icons
|
|
428
|
+
* @param variant - Visual variant of the menu item for semantic distinction
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```tsx
|
|
432
|
+
* // Basic menu item with click handler
|
|
433
|
+
* <DropdownMenuItem onSelect={() => console.log('Profile clicked')}>
|
|
434
|
+
* <User className="mr-2 h-4 w-4" />
|
|
435
|
+
* Profile
|
|
436
|
+
* </DropdownMenuItem>
|
|
437
|
+
* ```
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* ```tsx
|
|
441
|
+
* // Destructive action item
|
|
442
|
+
* <DropdownMenuItem variant="destructive" onSelect={handleDelete}>
|
|
443
|
+
* <Trash className="mr-2 h-4 w-4" />
|
|
444
|
+
* Delete Account
|
|
445
|
+
* </DropdownMenuItem>
|
|
446
|
+
* ```
|
|
206
447
|
*
|
|
207
|
-
* @component
|
|
208
448
|
* @example
|
|
209
449
|
* ```tsx
|
|
210
|
-
*
|
|
211
|
-
*
|
|
450
|
+
* // Disabled item
|
|
451
|
+
* <DropdownMenuItem disabled>
|
|
452
|
+
* <Settings className="mr-2 h-4 w-4" />
|
|
453
|
+
* Settings (Coming Soon)
|
|
212
454
|
* </DropdownMenuItem>
|
|
213
|
-
*
|
|
214
|
-
*
|
|
455
|
+
* ```
|
|
456
|
+
*
|
|
457
|
+
* @example
|
|
458
|
+
* ```tsx
|
|
459
|
+
* // Item with keyboard shortcut
|
|
460
|
+
* <DropdownMenuItem onSelect={handleSave}>
|
|
461
|
+
* Save Document
|
|
462
|
+
* <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
|
|
215
463
|
* </DropdownMenuItem>
|
|
216
464
|
* ```
|
|
217
465
|
* @since 1.0.0
|
|
@@ -224,6 +472,7 @@ function DropdownMenuItem({
|
|
|
224
472
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
|
225
473
|
inset?: boolean;
|
|
226
474
|
variant?: "default" | "destructive";
|
|
475
|
+
className?: string;
|
|
227
476
|
}) {
|
|
228
477
|
return (
|
|
229
478
|
<DropdownMenuPrimitive.Item
|
|
@@ -243,25 +492,64 @@ function DropdownMenuItem({
|
|
|
243
492
|
* A checkable menu item with visual state indication
|
|
244
493
|
*
|
|
245
494
|
* Displays a checkbox that can be toggled on/off. The checked state is
|
|
246
|
-
* visually indicated with a checkmark icon.
|
|
247
|
-
*
|
|
495
|
+
* visually indicated with a checkmark icon. Supports indeterminate state
|
|
496
|
+
* for partial selections. Ideal for menu options that represent toggleable
|
|
497
|
+
* settings, features, or multi-selection scenarios.
|
|
248
498
|
*
|
|
249
|
-
* @
|
|
250
|
-
* @param
|
|
251
|
-
* @param
|
|
252
|
-
* @param
|
|
499
|
+
* @param checked - The checked state of the checkbox item (boolean or "indeterminate")
|
|
500
|
+
* @param onCheckedChange - Callback fired when the checked state changes
|
|
501
|
+
* @param disabled - Whether the item is disabled and cannot be interacted with
|
|
502
|
+
* @param onSelect - Callback fired when the item is selected via click or keyboard
|
|
503
|
+
* @param textValue - Optional text value used for typeahead search functionality
|
|
504
|
+
* @param inset - Whether to add extra left padding to align with items that have icons
|
|
253
505
|
*
|
|
254
506
|
* @example
|
|
255
507
|
* ```tsx
|
|
508
|
+
* // Basic checkbox item with state
|
|
256
509
|
* const [showSidebar, setShowSidebar] = useState(true);
|
|
257
510
|
*
|
|
258
511
|
* <DropdownMenuCheckboxItem
|
|
259
512
|
* checked={showSidebar}
|
|
260
513
|
* onCheckedChange={setShowSidebar}
|
|
261
514
|
* >
|
|
515
|
+
* <Sidebar className="mr-2 h-4 w-4" />
|
|
262
516
|
* Show Sidebar
|
|
263
517
|
* </DropdownMenuCheckboxItem>
|
|
264
518
|
* ```
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```tsx
|
|
522
|
+
* // Multiple checkbox items for feature toggles
|
|
523
|
+
* const [features, setFeatures] = useState({
|
|
524
|
+
* notifications: true,
|
|
525
|
+
* autoSave: false,
|
|
526
|
+
* darkMode: true
|
|
527
|
+
* });
|
|
528
|
+
*
|
|
529
|
+
* <DropdownMenuCheckboxItem
|
|
530
|
+
* checked={features.notifications}
|
|
531
|
+
* onCheckedChange={(checked) => setFeatures(prev => ({ ...prev, notifications: checked }))}
|
|
532
|
+
* >
|
|
533
|
+
* Enable Notifications
|
|
534
|
+
* </DropdownMenuCheckboxItem>
|
|
535
|
+
* <DropdownMenuCheckboxItem
|
|
536
|
+
* checked={features.autoSave}
|
|
537
|
+
* onCheckedChange={(checked) => setFeatures(prev => ({ ...prev, autoSave: checked }))}
|
|
538
|
+
* >
|
|
539
|
+
* Auto-save Changes
|
|
540
|
+
* </DropdownMenuCheckboxItem>
|
|
541
|
+
* ```
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```tsx
|
|
545
|
+
* // Indeterminate state for partial selections
|
|
546
|
+
* <DropdownMenuCheckboxItem
|
|
547
|
+
* checked="indeterminate"
|
|
548
|
+
* onCheckedChange={handleSelectAll}
|
|
549
|
+
* >
|
|
550
|
+
* Select All Items (Some selected)
|
|
551
|
+
* </DropdownMenuCheckboxItem>
|
|
552
|
+
* ```
|
|
265
553
|
* @since 1.0.0
|
|
266
554
|
*/
|
|
267
555
|
function DropdownMenuCheckboxItem({
|
|
@@ -269,7 +557,9 @@ function DropdownMenuCheckboxItem({
|
|
|
269
557
|
children,
|
|
270
558
|
checked,
|
|
271
559
|
...props
|
|
272
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>
|
|
560
|
+
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & {
|
|
561
|
+
className?: string;
|
|
562
|
+
}) {
|
|
273
563
|
return (
|
|
274
564
|
<DropdownMenuPrimitive.CheckboxItem
|
|
275
565
|
data-slot="dropdown-menu-checkbox-item"
|
|
@@ -294,20 +584,44 @@ function DropdownMenuCheckboxItem({
|
|
|
294
584
|
* Groups radio items for single selection
|
|
295
585
|
*
|
|
296
586
|
* Creates a group where only one radio item can be selected at a time.
|
|
297
|
-
*
|
|
587
|
+
* Manages the selection state and ensures mutual exclusivity between options.
|
|
588
|
+
* Use with DropdownMenuRadioItem components to create single-choice scenarios
|
|
589
|
+
* like theme selection, sorting options, or view modes.
|
|
298
590
|
*
|
|
299
|
-
* @
|
|
300
|
-
* @param
|
|
301
|
-
* @param
|
|
591
|
+
* @param value - The currently selected value in the radio group
|
|
592
|
+
* @param onValueChange - Callback fired when the selection changes to a different value
|
|
593
|
+
* @param disabled - Whether the entire radio group is disabled
|
|
302
594
|
*
|
|
303
595
|
* @example
|
|
304
596
|
* ```tsx
|
|
597
|
+
* // Theme selection with radio group
|
|
305
598
|
* const [theme, setTheme] = useState("light");
|
|
306
599
|
*
|
|
307
600
|
* <DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
308
|
-
* <DropdownMenuRadioItem value="light">
|
|
309
|
-
*
|
|
310
|
-
*
|
|
601
|
+
* <DropdownMenuRadioItem value="light">
|
|
602
|
+
* <Sun className="mr-2 h-4 w-4" />
|
|
603
|
+
* Light Theme
|
|
604
|
+
* </DropdownMenuRadioItem>
|
|
605
|
+
* <DropdownMenuRadioItem value="dark">
|
|
606
|
+
* <Moon className="mr-2 h-4 w-4" />
|
|
607
|
+
* Dark Theme
|
|
608
|
+
* </DropdownMenuRadioItem>
|
|
609
|
+
* <DropdownMenuRadioItem value="system">
|
|
610
|
+
* <Monitor className="mr-2 h-4 w-4" />
|
|
611
|
+
* System Theme
|
|
612
|
+
* </DropdownMenuRadioItem>
|
|
613
|
+
* </DropdownMenuRadioGroup>
|
|
614
|
+
* ```
|
|
615
|
+
*
|
|
616
|
+
* @example
|
|
617
|
+
* ```tsx
|
|
618
|
+
* // Sorting options
|
|
619
|
+
* const [sortBy, setSortBy] = useState("name");
|
|
620
|
+
*
|
|
621
|
+
* <DropdownMenuRadioGroup value={sortBy} onValueChange={setSortBy}>
|
|
622
|
+
* <DropdownMenuRadioItem value="name">Sort by Name</DropdownMenuRadioItem>
|
|
623
|
+
* <DropdownMenuRadioItem value="date">Sort by Date</DropdownMenuRadioItem>
|
|
624
|
+
* <DropdownMenuRadioItem value="size">Sort by Size</DropdownMenuRadioItem>
|
|
311
625
|
* </DropdownMenuRadioGroup>
|
|
312
626
|
* ```
|
|
313
627
|
* @since 1.0.0
|
|
@@ -327,21 +641,44 @@ function DropdownMenuRadioGroup({
|
|
|
327
641
|
* A radio button menu item for single selection within a group
|
|
328
642
|
*
|
|
329
643
|
* Must be used within a DropdownMenuRadioGroup. Shows a filled circle
|
|
330
|
-
* indicator when selected. Only one radio item can be selected per group
|
|
644
|
+
* indicator when selected. Only one radio item can be selected per group,
|
|
645
|
+
* ensuring mutually exclusive selection behavior.
|
|
331
646
|
*
|
|
332
|
-
* @
|
|
333
|
-
* @param
|
|
334
|
-
* @param
|
|
647
|
+
* @param value - The unique value this radio item represents
|
|
648
|
+
* @param disabled - Whether the item is disabled and cannot be selected
|
|
649
|
+
* @param onSelect - Callback fired when the item is selected via click or keyboard
|
|
650
|
+
* @param textValue - Optional text value used for typeahead search functionality
|
|
651
|
+
* @param inset - Whether to add extra left padding to align with items that have icons
|
|
335
652
|
*
|
|
336
653
|
* @example
|
|
337
654
|
* ```tsx
|
|
655
|
+
* // Basic radio group for theme selection
|
|
338
656
|
* <DropdownMenuRadioGroup value={selectedTheme} onValueChange={setSelectedTheme}>
|
|
339
657
|
* <DropdownMenuRadioItem value="light">
|
|
658
|
+
* <Sun className="mr-2 h-4 w-4" />
|
|
340
659
|
* Light Theme
|
|
341
660
|
* </DropdownMenuRadioItem>
|
|
342
661
|
* <DropdownMenuRadioItem value="dark">
|
|
662
|
+
* <Moon className="mr-2 h-4 w-4" />
|
|
343
663
|
* Dark Theme
|
|
344
664
|
* </DropdownMenuRadioItem>
|
|
665
|
+
* <DropdownMenuRadioItem value="system">
|
|
666
|
+
* <Monitor className="mr-2 h-4 w-4" />
|
|
667
|
+
* System Theme
|
|
668
|
+
* </DropdownMenuRadioItem>
|
|
669
|
+
* </DropdownMenuRadioGroup>
|
|
670
|
+
* ```
|
|
671
|
+
*
|
|
672
|
+
* @example
|
|
673
|
+
* ```tsx
|
|
674
|
+
* // Priority selection with disabled option
|
|
675
|
+
* <DropdownMenuRadioGroup value={priority} onValueChange={setPriority}>
|
|
676
|
+
* <DropdownMenuRadioItem value="low">Low Priority</DropdownMenuRadioItem>
|
|
677
|
+
* <DropdownMenuRadioItem value="medium">Medium Priority</DropdownMenuRadioItem>
|
|
678
|
+
* <DropdownMenuRadioItem value="high">High Priority</DropdownMenuRadioItem>
|
|
679
|
+
* <DropdownMenuRadioItem value="urgent" disabled>
|
|
680
|
+
* Urgent (Premium Only)
|
|
681
|
+
* </DropdownMenuRadioItem>
|
|
345
682
|
* </DropdownMenuRadioGroup>
|
|
346
683
|
* ```
|
|
347
684
|
* @since 1.0.0
|
|
@@ -350,7 +687,9 @@ function DropdownMenuRadioItem({
|
|
|
350
687
|
className,
|
|
351
688
|
children,
|
|
352
689
|
...props
|
|
353
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>
|
|
690
|
+
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & {
|
|
691
|
+
className?: string;
|
|
692
|
+
}) {
|
|
354
693
|
return (
|
|
355
694
|
<DropdownMenuPrimitive.RadioItem
|
|
356
695
|
data-slot="dropdown-menu-radio-item"
|
|
@@ -371,12 +710,45 @@ function DropdownMenuRadioItem({
|
|
|
371
710
|
}
|
|
372
711
|
|
|
373
712
|
/**
|
|
374
|
-
*
|
|
713
|
+
* A non-interactive label for grouping and organizing menu items
|
|
714
|
+
*
|
|
715
|
+
* Used to provide semantic headers for groups of related menu items.
|
|
716
|
+
* Labels are not focusable and serve as visual and accessibility landmarks
|
|
717
|
+
* within the menu structure. Helps users understand the organization of menu options.
|
|
718
|
+
*
|
|
719
|
+
* @param asChild - Merge props onto the immediate child instead of rendering a wrapper element
|
|
720
|
+
* @param inset - Whether to add extra left padding to align with items that have icons
|
|
721
|
+
*
|
|
722
|
+
* @example
|
|
723
|
+
* ```tsx
|
|
724
|
+
* // Basic label for menu section
|
|
725
|
+
* <DropdownMenuContent>
|
|
726
|
+
* <DropdownMenuLabel>Account Actions</DropdownMenuLabel>
|
|
727
|
+
* <DropdownMenuSeparator />
|
|
728
|
+
* <DropdownMenuItem>View Profile</DropdownMenuItem>
|
|
729
|
+
* <DropdownMenuItem>Account Settings</DropdownMenuItem>
|
|
730
|
+
*
|
|
731
|
+
* <DropdownMenuSeparator />
|
|
732
|
+
* <DropdownMenuLabel>Preferences</DropdownMenuLabel>
|
|
733
|
+
* <DropdownMenuItem>Theme Settings</DropdownMenuItem>
|
|
734
|
+
* <DropdownMenuItem>Notification Settings</DropdownMenuItem>
|
|
735
|
+
* </DropdownMenuContent>
|
|
736
|
+
* ```
|
|
375
737
|
*
|
|
376
|
-
* @component
|
|
377
738
|
* @example
|
|
378
739
|
* ```tsx
|
|
379
|
-
*
|
|
740
|
+
* // Label with inset alignment
|
|
741
|
+
* <DropdownMenuContent>
|
|
742
|
+
* <DropdownMenuLabel inset>File Operations</DropdownMenuLabel>
|
|
743
|
+
* <DropdownMenuItem>
|
|
744
|
+
* <Download className="mr-2 h-4 w-4" />
|
|
745
|
+
* Download
|
|
746
|
+
* </DropdownMenuItem>
|
|
747
|
+
* <DropdownMenuItem>
|
|
748
|
+
* <Upload className="mr-2 h-4 w-4" />
|
|
749
|
+
* Upload
|
|
750
|
+
* </DropdownMenuItem>
|
|
751
|
+
* </DropdownMenuContent>
|
|
380
752
|
* ```
|
|
381
753
|
* @since 1.0.0
|
|
382
754
|
*/
|
|
@@ -386,6 +758,7 @@ function DropdownMenuLabel({
|
|
|
386
758
|
...props
|
|
387
759
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
|
388
760
|
inset?: boolean;
|
|
761
|
+
className?: string;
|
|
389
762
|
}) {
|
|
390
763
|
return (
|
|
391
764
|
<DropdownMenuPrimitive.Label
|
|
@@ -401,15 +774,49 @@ function DropdownMenuLabel({
|
|
|
401
774
|
}
|
|
402
775
|
|
|
403
776
|
/**
|
|
404
|
-
*
|
|
777
|
+
* A visual separator between menu items or groups
|
|
778
|
+
*
|
|
779
|
+
* Renders a thin horizontal line to visually separate different sections
|
|
780
|
+
* of menu items. Improves visual hierarchy and helps users understand
|
|
781
|
+
* the logical grouping of menu options. Commonly used after labels
|
|
782
|
+
* or between different types of actions.
|
|
783
|
+
*
|
|
784
|
+
* @param asChild - Merge props onto the immediate child instead of rendering a wrapper element
|
|
405
785
|
*
|
|
406
|
-
* @
|
|
786
|
+
* @example
|
|
787
|
+
* ```tsx
|
|
788
|
+
* // Separating different action groups
|
|
789
|
+
* <DropdownMenuContent>
|
|
790
|
+
* <DropdownMenuItem>View</DropdownMenuItem>
|
|
791
|
+
* <DropdownMenuItem>Edit</DropdownMenuItem>
|
|
792
|
+
* <DropdownMenuSeparator />
|
|
793
|
+
* <DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
|
|
794
|
+
* </DropdownMenuContent>
|
|
795
|
+
* ```
|
|
796
|
+
*
|
|
797
|
+
* @example
|
|
798
|
+
* ```tsx
|
|
799
|
+
* // Separating sections with labels
|
|
800
|
+
* <DropdownMenuContent>
|
|
801
|
+
* <DropdownMenuLabel>User Actions</DropdownMenuLabel>
|
|
802
|
+
* <DropdownMenuSeparator />
|
|
803
|
+
* <DropdownMenuItem>Profile</DropdownMenuItem>
|
|
804
|
+
* <DropdownMenuItem>Settings</DropdownMenuItem>
|
|
805
|
+
*
|
|
806
|
+
* <DropdownMenuSeparator />
|
|
807
|
+
* <DropdownMenuLabel>System</DropdownMenuLabel>
|
|
808
|
+
* <DropdownMenuSeparator />
|
|
809
|
+
* <DropdownMenuItem>Logout</DropdownMenuItem>
|
|
810
|
+
* </DropdownMenuContent>
|
|
811
|
+
* ```
|
|
407
812
|
* @since 1.0.0
|
|
408
813
|
*/
|
|
409
814
|
function DropdownMenuSeparator({
|
|
410
815
|
className,
|
|
411
816
|
...props
|
|
412
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>
|
|
817
|
+
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator> & {
|
|
818
|
+
className?: string;
|
|
819
|
+
}) {
|
|
413
820
|
return (
|
|
414
821
|
<DropdownMenuPrimitive.Separator
|
|
415
822
|
data-slot="dropdown-menu-separator"
|
|
@@ -423,23 +830,64 @@ function DropdownMenuSeparator({
|
|
|
423
830
|
* Displays keyboard shortcut hints in menu items
|
|
424
831
|
*
|
|
425
832
|
* Shows keyboard shortcut text aligned to the right side of menu items.
|
|
426
|
-
* Purely visual - does not implement the actual keyboard functionality.
|
|
427
|
-
* Use standard keyboard shortcut notation (⌘, ⌃, ⌥,
|
|
833
|
+
* Purely visual component - does not implement the actual keyboard functionality.
|
|
834
|
+
* Use standard keyboard shortcut notation and symbols (⌘, ⌃, ⌥, ⇧, Ctrl, Alt, Shift).
|
|
835
|
+
* Helps users discover and remember keyboard shortcuts for menu actions.
|
|
428
836
|
*
|
|
429
|
-
* @component
|
|
430
837
|
* @example
|
|
431
838
|
* ```tsx
|
|
432
|
-
*
|
|
839
|
+
* // macOS style shortcuts
|
|
840
|
+
* <DropdownMenuItem onSelect={handleSave}>
|
|
433
841
|
* Save Document
|
|
434
842
|
* <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
|
|
435
843
|
* </DropdownMenuItem>
|
|
436
844
|
* ```
|
|
845
|
+
*
|
|
846
|
+
* @example
|
|
847
|
+
* ```tsx
|
|
848
|
+
* // Windows/Linux style shortcuts
|
|
849
|
+
* <DropdownMenuItem onSelect={handleCopy}>
|
|
850
|
+
* Copy
|
|
851
|
+
* <DropdownMenuShortcut>Ctrl+C</DropdownMenuShortcut>
|
|
852
|
+
* </DropdownMenuItem>
|
|
853
|
+
* ```
|
|
854
|
+
*
|
|
855
|
+
* @example
|
|
856
|
+
* ```tsx
|
|
857
|
+
* // Complex shortcuts with multiple modifiers
|
|
858
|
+
* <DropdownMenuItem onSelect={handleForceRefresh}>
|
|
859
|
+
* Force Refresh
|
|
860
|
+
* <DropdownMenuShortcut>⌘⇧R</DropdownMenuShortcut>
|
|
861
|
+
* </DropdownMenuItem>
|
|
862
|
+
* ```
|
|
863
|
+
*
|
|
864
|
+
* @example
|
|
865
|
+
* ```tsx
|
|
866
|
+
* // Multiple menu items with shortcuts
|
|
867
|
+
* <DropdownMenuContent>
|
|
868
|
+
* <DropdownMenuItem>
|
|
869
|
+
* New File <DropdownMenuShortcut>⌘N</DropdownMenuShortcut>
|
|
870
|
+
* </DropdownMenuItem>
|
|
871
|
+
* <DropdownMenuItem>
|
|
872
|
+
* Open File <DropdownMenuShortcut>⌘O</DropdownMenuShortcut>
|
|
873
|
+
* </DropdownMenuItem>
|
|
874
|
+
* <DropdownMenuSeparator />
|
|
875
|
+
* <DropdownMenuItem>
|
|
876
|
+
* Save <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
|
|
877
|
+
* </DropdownMenuItem>
|
|
878
|
+
* <DropdownMenuItem>
|
|
879
|
+
* Save As <DropdownMenuShortcut>⌘⇧S</DropdownMenuShortcut>
|
|
880
|
+
* </DropdownMenuItem>
|
|
881
|
+
* </DropdownMenuContent>
|
|
882
|
+
* ```
|
|
437
883
|
* @since 1.0.0
|
|
438
884
|
*/
|
|
439
885
|
function DropdownMenuShortcut({
|
|
440
886
|
className,
|
|
441
887
|
...props
|
|
442
|
-
}: React.ComponentProps<"span">
|
|
888
|
+
}: React.ComponentProps<"span"> & {
|
|
889
|
+
className?: string;
|
|
890
|
+
}) {
|
|
443
891
|
return (
|
|
444
892
|
<span
|
|
445
893
|
data-slot="dropdown-menu-shortcut"
|
|
@@ -456,19 +904,66 @@ function DropdownMenuShortcut({
|
|
|
456
904
|
* Container for creating nested submenus
|
|
457
905
|
*
|
|
458
906
|
* Wraps a submenu trigger and content to create hierarchical menu structures.
|
|
459
|
-
*
|
|
907
|
+
* Enables multi-level navigation within dropdown menus. Use with
|
|
908
|
+
* DropdownMenuSubTrigger and DropdownMenuSubContent to build complex
|
|
909
|
+
* menu hierarchies with proper focus management and keyboard navigation.
|
|
910
|
+
*
|
|
911
|
+
* @param defaultOpen - Whether the submenu is initially open (uncontrolled mode)
|
|
912
|
+
* @param open - Whether the submenu is open (controlled mode)
|
|
913
|
+
* @param onOpenChange - Callback fired when the submenu open state changes
|
|
460
914
|
*
|
|
461
|
-
* @component
|
|
462
915
|
* @example
|
|
463
916
|
* ```tsx
|
|
917
|
+
* // Basic submenu structure
|
|
464
918
|
* <DropdownMenuSub>
|
|
919
|
+
* <DropdownMenuSubTrigger>
|
|
920
|
+
* <Share className="mr-2 h-4 w-4" />
|
|
921
|
+
* Share Options
|
|
922
|
+
* </DropdownMenuSubTrigger>
|
|
923
|
+
* <DropdownMenuSubContent>
|
|
924
|
+
* <DropdownMenuItem>Email Link</DropdownMenuItem>
|
|
925
|
+
* <DropdownMenuItem>Copy to Clipboard</DropdownMenuItem>
|
|
926
|
+
* <DropdownMenuItem>Generate QR Code</DropdownMenuItem>
|
|
927
|
+
* </DropdownMenuSubContent>
|
|
928
|
+
* </DropdownMenuSub>
|
|
929
|
+
* ```
|
|
930
|
+
*
|
|
931
|
+
* @example
|
|
932
|
+
* ```tsx
|
|
933
|
+
* // Controlled submenu with state management
|
|
934
|
+
* const [isShareOpen, setIsShareOpen] = useState(false);
|
|
935
|
+
*
|
|
936
|
+
* <DropdownMenuSub open={isShareOpen} onOpenChange={setIsShareOpen}>
|
|
465
937
|
* <DropdownMenuSubTrigger>Share</DropdownMenuSubTrigger>
|
|
466
938
|
* <DropdownMenuSubContent>
|
|
467
|
-
* <DropdownMenuItem>Email</DropdownMenuItem>
|
|
468
|
-
* <DropdownMenuItem>Copy Link</DropdownMenuItem>
|
|
939
|
+
* <DropdownMenuItem onSelect={() => handleShare('email')}>Email</DropdownMenuItem>
|
|
940
|
+
* <DropdownMenuItem onSelect={() => handleShare('link')}>Copy Link</DropdownMenuItem>
|
|
469
941
|
* </DropdownMenuSubContent>
|
|
470
942
|
* </DropdownMenuSub>
|
|
471
943
|
* ```
|
|
944
|
+
*
|
|
945
|
+
* @example
|
|
946
|
+
* ```tsx
|
|
947
|
+
* // Complex nested menu structure
|
|
948
|
+
* <DropdownMenuContent>
|
|
949
|
+
* <DropdownMenuItem>Edit</DropdownMenuItem>
|
|
950
|
+
* <DropdownMenuSeparator />
|
|
951
|
+
* <DropdownMenuSub>
|
|
952
|
+
* <DropdownMenuSubTrigger>Export</DropdownMenuSubTrigger>
|
|
953
|
+
* <DropdownMenuSubContent>
|
|
954
|
+
* <DropdownMenuItem>Export as PDF</DropdownMenuItem>
|
|
955
|
+
* <DropdownMenuItem>Export as PNG</DropdownMenuItem>
|
|
956
|
+
* <DropdownMenuSub>
|
|
957
|
+
* <DropdownMenuSubTrigger>Advanced Export</DropdownMenuSubTrigger>
|
|
958
|
+
* <DropdownMenuSubContent>
|
|
959
|
+
* <DropdownMenuItem>Custom Resolution</DropdownMenuItem>
|
|
960
|
+
* <DropdownMenuItem>Batch Export</DropdownMenuItem>
|
|
961
|
+
* </DropdownMenuSubContent>
|
|
962
|
+
* </DropdownMenuSub>
|
|
963
|
+
* </DropdownMenuSubContent>
|
|
964
|
+
* </DropdownMenuSub>
|
|
965
|
+
* </DropdownMenuContent>
|
|
966
|
+
* ```
|
|
472
967
|
* @since 1.0.0
|
|
473
968
|
*/
|
|
474
969
|
function DropdownMenuSub({
|
|
@@ -480,25 +975,57 @@ function DropdownMenuSub({
|
|
|
480
975
|
/**
|
|
481
976
|
* Trigger element for opening a submenu
|
|
482
977
|
*
|
|
483
|
-
* Displays an arrow indicator and opens the associated submenu on hover or
|
|
484
|
-
* Must be used within a DropdownMenuSub component.
|
|
978
|
+
* Displays an arrow indicator and opens the associated submenu on hover or keyboard
|
|
979
|
+
* navigation. Must be used within a DropdownMenuSub component. Automatically
|
|
980
|
+
* includes a chevron icon to indicate submenu availability and handles focus states.
|
|
485
981
|
*
|
|
486
|
-
* @
|
|
982
|
+
* @param asChild - Merge props onto the immediate child instead of rendering a wrapper element
|
|
983
|
+
* @param disabled - Whether the trigger is disabled and cannot open the submenu
|
|
984
|
+
* @param textValue - Optional text value used for typeahead search functionality
|
|
487
985
|
* @param inset - Whether to add left padding to align with items that have icons
|
|
488
986
|
*
|
|
489
987
|
* @example
|
|
490
988
|
* ```tsx
|
|
989
|
+
* // Basic submenu trigger with icon
|
|
491
990
|
* <DropdownMenuSub>
|
|
492
991
|
* <DropdownMenuSubTrigger>
|
|
493
992
|
* <Share className="mr-2 h-4 w-4" />
|
|
494
993
|
* Share Options
|
|
495
994
|
* </DropdownMenuSubTrigger>
|
|
496
995
|
* <DropdownMenuSubContent>
|
|
497
|
-
* <DropdownMenuItem>Email</DropdownMenuItem>
|
|
498
|
-
* <DropdownMenuItem>Copy
|
|
996
|
+
* <DropdownMenuItem>Email Link</DropdownMenuItem>
|
|
997
|
+
* <DropdownMenuItem>Copy to Clipboard</DropdownMenuItem>
|
|
499
998
|
* </DropdownMenuSubContent>
|
|
500
999
|
* </DropdownMenuSub>
|
|
501
1000
|
* ```
|
|
1001
|
+
*
|
|
1002
|
+
* @example
|
|
1003
|
+
* ```tsx
|
|
1004
|
+
* // Submenu trigger with inset alignment
|
|
1005
|
+
* <DropdownMenuContent>
|
|
1006
|
+
* <DropdownMenuItem>
|
|
1007
|
+
* <FileText className="mr-2 h-4 w-4" />
|
|
1008
|
+
* Open File
|
|
1009
|
+
* </DropdownMenuItem>
|
|
1010
|
+
* <DropdownMenuSub>
|
|
1011
|
+
* <DropdownMenuSubTrigger inset>
|
|
1012
|
+
* Recent Files
|
|
1013
|
+
* </DropdownMenuSubTrigger>
|
|
1014
|
+
* <DropdownMenuSubContent>
|
|
1015
|
+
* <DropdownMenuItem>Document.pdf</DropdownMenuItem>
|
|
1016
|
+
* <DropdownMenuItem>Presentation.pptx</DropdownMenuItem>
|
|
1017
|
+
* </DropdownMenuSubContent>
|
|
1018
|
+
* </DropdownMenuSub>
|
|
1019
|
+
* </DropdownMenuContent>
|
|
1020
|
+
* ```
|
|
1021
|
+
*
|
|
1022
|
+
* @example
|
|
1023
|
+
* ```tsx
|
|
1024
|
+
* // Disabled submenu trigger
|
|
1025
|
+
* <DropdownMenuSubTrigger disabled>
|
|
1026
|
+
* Advanced Options (Pro Only)
|
|
1027
|
+
* </DropdownMenuSubTrigger>
|
|
1028
|
+
* ```
|
|
502
1029
|
* @since 1.0.0
|
|
503
1030
|
*/
|
|
504
1031
|
function DropdownMenuSubTrigger({
|
|
@@ -508,6 +1035,7 @@ function DropdownMenuSubTrigger({
|
|
|
508
1035
|
...props
|
|
509
1036
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
510
1037
|
inset?: boolean;
|
|
1038
|
+
className?: string;
|
|
511
1039
|
}) {
|
|
512
1040
|
return (
|
|
513
1041
|
<DropdownMenuPrimitive.SubTrigger
|
|
@@ -529,16 +1057,69 @@ function DropdownMenuSubTrigger({
|
|
|
529
1057
|
* Content container for submenu items
|
|
530
1058
|
*
|
|
531
1059
|
* Contains the items displayed when a submenu is opened. Positioned relative
|
|
532
|
-
* to the trigger
|
|
1060
|
+
* to the submenu trigger with intelligent collision detection. Supports all
|
|
1061
|
+
* the same item types as the main menu content, enabling complex nested
|
|
1062
|
+
* menu structures with consistent behavior and styling.
|
|
1063
|
+
*
|
|
1064
|
+
* @param asChild - Merge props onto the immediate child instead of rendering a wrapper element
|
|
1065
|
+
* @param loop - When true, keyboard navigation will loop from last to first item
|
|
1066
|
+
* @param side - The preferred side of the trigger to render against
|
|
1067
|
+
* @param sideOffset - Distance in pixels from the trigger
|
|
1068
|
+
* @param align - The preferred alignment against the trigger
|
|
1069
|
+
* @param alignOffset - Distance in pixels from the align point
|
|
1070
|
+
* @param avoidCollisions - Whether to avoid collisions with viewport boundaries
|
|
1071
|
+
* @param sticky - Element positioning behavior relative to the viewport
|
|
1072
|
+
* @param hideWhenDetached - Whether to hide content when reference element is occluded
|
|
533
1073
|
*
|
|
534
|
-
* @component
|
|
535
1074
|
* @example
|
|
536
1075
|
* ```tsx
|
|
1076
|
+
* // Basic submenu content with various item types
|
|
537
1077
|
* <DropdownMenuSubContent>
|
|
538
|
-
* <DropdownMenuItem>
|
|
539
|
-
*
|
|
1078
|
+
* <DropdownMenuItem>
|
|
1079
|
+
* <Mail className="mr-2 h-4 w-4" />
|
|
1080
|
+
* Send via Email
|
|
1081
|
+
* </DropdownMenuItem>
|
|
1082
|
+
* <DropdownMenuItem>
|
|
1083
|
+
* <Link className="mr-2 h-4 w-4" />
|
|
1084
|
+
* Copy Share Link
|
|
1085
|
+
* </DropdownMenuItem>
|
|
540
1086
|
* <DropdownMenuSeparator />
|
|
541
|
-
* <DropdownMenuItem>
|
|
1087
|
+
* <DropdownMenuItem>
|
|
1088
|
+
* <QrCode className="mr-2 h-4 w-4" />
|
|
1089
|
+
* Generate QR Code
|
|
1090
|
+
* </DropdownMenuItem>
|
|
1091
|
+
* </DropdownMenuSubContent>
|
|
1092
|
+
* ```
|
|
1093
|
+
*
|
|
1094
|
+
* @example
|
|
1095
|
+
* ```tsx
|
|
1096
|
+
* // Submenu with checkbox items for multi-selection
|
|
1097
|
+
* <DropdownMenuSubContent>
|
|
1098
|
+
* <DropdownMenuLabel>Export Options</DropdownMenuLabel>
|
|
1099
|
+
* <DropdownMenuSeparator />
|
|
1100
|
+
* <DropdownMenuCheckboxItem checked={includeMetadata} onCheckedChange={setIncludeMetadata}>
|
|
1101
|
+
* Include Metadata
|
|
1102
|
+
* </DropdownMenuCheckboxItem>
|
|
1103
|
+
* <DropdownMenuCheckboxItem checked={compressFile} onCheckedChange={setCompressFile}>
|
|
1104
|
+
* Compress File
|
|
1105
|
+
* </DropdownMenuCheckboxItem>
|
|
1106
|
+
* <DropdownMenuSeparator />
|
|
1107
|
+
* <DropdownMenuItem>Export Now</DropdownMenuItem>
|
|
1108
|
+
* </DropdownMenuSubContent>
|
|
1109
|
+
* ```
|
|
1110
|
+
*
|
|
1111
|
+
* @example
|
|
1112
|
+
* ```tsx
|
|
1113
|
+
* // Nested submenu structure
|
|
1114
|
+
* <DropdownMenuSubContent>
|
|
1115
|
+
* <DropdownMenuItem>Basic Export</DropdownMenuItem>
|
|
1116
|
+
* <DropdownMenuSub>
|
|
1117
|
+
* <DropdownMenuSubTrigger>Advanced Settings</DropdownMenuSubTrigger>
|
|
1118
|
+
* <DropdownMenuSubContent>
|
|
1119
|
+
* <DropdownMenuItem>High Quality</DropdownMenuItem>
|
|
1120
|
+
* <DropdownMenuItem>Custom Resolution</DropdownMenuItem>
|
|
1121
|
+
* </DropdownMenuSubContent>
|
|
1122
|
+
* </DropdownMenuSub>
|
|
542
1123
|
* </DropdownMenuSubContent>
|
|
543
1124
|
* ```
|
|
544
1125
|
* @since 1.0.0
|
|
@@ -546,7 +1127,9 @@ function DropdownMenuSubTrigger({
|
|
|
546
1127
|
function DropdownMenuSubContent({
|
|
547
1128
|
className,
|
|
548
1129
|
...props
|
|
549
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>
|
|
1130
|
+
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent> & {
|
|
1131
|
+
className?: string;
|
|
1132
|
+
}) {
|
|
550
1133
|
return (
|
|
551
1134
|
<DropdownMenuPrimitive.SubContent
|
|
552
1135
|
data-slot="dropdown-menu-sub-content"
|