A React dropdown menu component library providing accessible dropdown menu functionality with keyboard navigation and focus management.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Components for creating nested dropdown menus with submenu triggers and content areas. These components enable complex menu hierarchies with multiple levels of navigation.
Container component that manages the state and behavior of a submenu.
/**
* Container for submenu functionality
* @param children - Child components (typically SubTrigger and SubContent)
* @param open - Controlled open state of the submenu
* @param defaultOpen - Default open state (uncontrolled)
* @param onOpenChange - Callback when submenu open state changes
*/
interface DropdownMenuSubProps {
children?: React.ReactNode;
open?: boolean;
defaultOpen?: boolean;
onOpenChange?(open: boolean): void;
}
const DropdownMenuSub: React.FC<DropdownMenuSubProps>;Usage Examples:
// Uncontrolled submenu
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>More Options</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Item>Nested Option 1</DropdownMenu.Item>
<DropdownMenu.Item>Nested Option 2</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
// Controlled submenu
const [subOpen, setSubOpen] = React.useState(false);
<DropdownMenu.Sub open={subOpen} onOpenChange={setSubOpen}>
<DropdownMenu.SubTrigger>Controlled Submenu</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Item>Nested Item</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>Trigger component that opens a submenu when hovered or activated with keyboard.
/**
* Trigger for opening submenu
* @param disabled - Whether the trigger is disabled
* @param textValue - Text value for typeahead functionality
* @param asChild - Compose with child element
*/
interface DropdownMenuSubTriggerProps {
disabled?: boolean;
textValue?: string;
asChild?: boolean;
children?: React.ReactNode;
}
const DropdownMenuSubTrigger: React.ForwardRefExoticComponent<DropdownMenuSubTriggerProps>;Usage Examples:
// Basic submenu trigger
<DropdownMenu.SubTrigger>
Share
<ChevronRightIcon />
</DropdownMenu.SubTrigger>
// Disabled submenu trigger
<DropdownMenu.SubTrigger disabled>
Unavailable Options
</DropdownMenu.SubTrigger>
// Custom submenu trigger using asChild
<DropdownMenu.SubTrigger asChild>
<button className="custom-submenu-trigger">
<ShareIcon />
Share Options
<ArrowIcon />
</button>
</DropdownMenu.SubTrigger>Content container for submenu items that appears when the submenu is triggered.
/**
* Content container for submenu items
* Similar to DropdownMenuContent but for nested menus
* @param loop - Whether focus should loop when navigating
* @param onEscapeKeyDown - Callback when Escape key is pressed
* @param onKeyDown - Callback for key events
* @param forceMount - Force mounting regardless of open state
* @param container - Container element for portaling
*/
interface DropdownMenuSubContentProps {
loop?: boolean;
onEscapeKeyDown?: (event: KeyboardEvent) => void;
onKeyDown?: (event: KeyboardEvent) => void;
forceMount?: boolean;
container?: HTMLElement;
children?: React.ReactNode;
}
const DropdownMenuSubContent: React.ForwardRefExoticComponent<DropdownMenuSubContentProps>;Usage Examples:
// Basic submenu content
<DropdownMenu.SubContent>
<DropdownMenu.Item>Copy Link</DropdownMenu.Item>
<DropdownMenu.Item>Email</DropdownMenu.Item>
<DropdownMenu.Item>Print</DropdownMenu.Item>
</DropdownMenu.SubContent>
// Submenu content with custom behavior
<DropdownMenu.SubContent
loop={false}
onEscapeKeyDown={(e) => console.log('Escaping submenu')}
>
<DropdownMenu.Item>Option A</DropdownMenu.Item>
<DropdownMenu.Item>Option B</DropdownMenu.Item>
</DropdownMenu.SubContent>function MultiLevelDropdownMenu() {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>File</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content>
<DropdownMenu.Item>New File</DropdownMenu.Item>
<DropdownMenu.Item>Open</DropdownMenu.Item>
<DropdownMenu.Separator />
{/* First level submenu */}
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>
Recent Files
<ChevronRightIcon />
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Item>document1.txt</DropdownMenu.Item>
<DropdownMenu.Item>document2.txt</DropdownMenu.Item>
{/* Second level submenu */}
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>
More Recent
<ChevronRightIcon />
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Item>old-file1.txt</DropdownMenu.Item>
<DropdownMenu.Item>old-file2.txt</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>
Export
<ChevronRightIcon />
</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Item>Export as PDF</DropdownMenu.Item>
<DropdownMenu.Item>Export as HTML</DropdownMenu.Item>
<DropdownMenu.Item>Export as Markdown</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
<DropdownMenu.Separator />
<DropdownMenu.Item>Close</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);
}Submenus support full keyboard navigation:
// Short aliases for composition patterns
const Sub = DropdownMenuSub;
const SubTrigger = DropdownMenuSubTrigger;
const SubContent = DropdownMenuSubContent;These submenu components enable the creation of complex, multi-level dropdown menus while maintaining full accessibility and keyboard navigation support.
Install with Tessl CLI
npx tessl i tessl/npm-radix-ui--react-dropdown-menu