Settings Menu Style
Usage in Gaia
Perfect for settings menus, context menus, and multi-level navigation. Hover-based submenus that feel responsive and natural.Installation
Usage
Examples
Settings Menu
Create a comprehensive settings menu with submenus:Context Menu with Sections
Organize menu items into multiple sections:Custom Icon Colors
Highlight specific menu items with custom icon colors:With Separators
Add visual separators between menu items:Controlled State
Control the menu open state externally:Custom Positioning
Control where the menu appears:Using the Hook
For custom implementations, use theuseNestedMenu hook:
Features
- Hover Activation: Submenus open on hover with smooth transitions
- Multi-level Support: Nested submenus up to any depth
- Smart Timing: Delay handling prevents accidental closes
- Section Support: Organize items into titled sections
- Icon Support: Add icons to menu items with custom colors
- Variants: Built-in “danger” variant for destructive actions
- Separators: Visual dividers between items or sections
- Custom Styling: Full className support for customization
- Keyboard Accessible: Proper focus management and keyboard support
- Controlled/Uncontrolled: Works both ways
- Position Control: Flexible positioning options
Props
NestedMenu
| Prop | Type | Default | Description |
|---|---|---|---|
| sections | NestedMenuSectionProps[] | - | Array of menu sections |
| trigger | React.ReactNode | - | Element that triggers the menu |
| iconClassName | string | ”h-4 w-4” | Size for icons |
| arrowIcon | React.ComponentType | - | Custom arrow icon for submenus |
| side | ”top” | “right” | “bottom” | “left" | "right” | Menu placement |
| align | ”start” | “center” | “end" | "start” | Alignment relative to trigger |
| sideOffset | number | 8 | Distance from trigger |
| className | string | - | Additional CSS classes |
| open | boolean | - | Controlled open state |
| onOpenChange | (open: boolean) => void | - | Callback when open state changes |
NestedMenuSection
| Property | Type | Default | Description |
|---|---|---|---|
| title | string | - | Section title |
| items | NestedMenuItem[] | - | Menu items in this section |
| showDivider | boolean | false | Show divider after section |
NestedMenuItem
| Property | Type | Default | Description |
|---|---|---|---|
| key | string | - | Unique key for the item |
| label | string | - | Display text |
| icon | React.ComponentType | - | Icon component |
| onSelect | () => void | - | Click handler |
| hasSubmenu | boolean | false | Whether item has submenu |
| submenuItems | NestedMenuItem[] | - | Submenu items (if hasSubmenu) |
| variant | ”default” | “danger" | "default” | Visual variant |
| className | string | - | Additional CSS classes |
| iconColor | string | - | Custom icon color (CSS value) |
| separator | boolean | false | Show divider after this item |
useNestedMenu Hook
Returns:| Property | Type | Description |
|---|---|---|
| isOpen | boolean | Whether submenu is open |
| setIsOpen | (open: boolean) => void | Set open state |
| itemRef | HTMLElement | null | Reference to trigger element |
| handleMouseEnter | (e: React.MouseEvent) => void | Mouse enter handler |
| handleMouseLeave | () => void | Mouse leave handler |
| cancelClose | () => void | Cancel pending close |
NestedMenuTooltip
| Prop | Type | Default | Description |
|---|---|---|---|
| isOpen | boolean | - | Whether tooltip is visible |
| onOpenChange | (open: boolean) => void | - | Callback when open state changes |
| itemRef | HTMLElement | null | - | Reference element for positioning |
| menuItems | NestedMenuItem[] | - | Items to display |
| iconClassName | string | ”h-4 w-4” | Icon size |
| className | string | - | Additional CSS classes |
| onMouseEnter | () => void | - | Mouse enter handler |
| onMouseLeave | () => void | - | Mouse leave handler |
Accessibility
- Keyboard Navigation: Full keyboard support for navigation
- Focus Management: Proper focus indicators and management
- ARIA Attributes: Proper roles and attributes for screen readers
- Auto Focus Prevention: Prevents unwanted focus stealing
- Interaction Outside: Handles clicks outside gracefully
Notes
- The component uses Radix UI Popover primitive for robust positioning
- Hover delays are tuned for a natural feel (300ms before closing)
- Submenus automatically position themselves to avoid viewport edges
- The component handles cleanup of timers on unmount
- Works with both controlled and uncontrolled state management