Menu
The Menu component provides dropdown navigation and action lists with support for icons, submenus, and various interaction patterns for organizing application functions.
Usage
import { Menu, MenuAlignment, MenuSide, MenuItemV2Variant, MenuItemV2ActionType, } from 'blend-v1' import { Button, ButtonType } from 'blend-v1' import { Settings, User, LogOut, ChevronDown } from 'lucide-react' function MyComponent() { const menuItems = [ { label: 'Profile', slot1: <User size={16} />, onClick: () => console.log('Profile clicked'), }, { label: 'Settings', slot1: <Settings size={16} />, onClick: () => console.log('Settings clicked'), }, { label: 'Logout', slot1: <LogOut size={16} />, variant: MenuItemV2Variant.ACTION, actionType: MenuItemV2ActionType.DANGER, onClick: () => console.log('Logout clicked'), }, ] return ( <Menu trigger={ <Button text="Open Menu" buttonType={ButtonType.SECONDARY} trailingIcon={<ChevronDown size={16} />} /> } items={[{ items: menuItems }]} alignment={MenuAlignment.CENTER} side={MenuSide.BOTTOM} /> ) }
API Reference
Prop Name | Type |
---|---|
trigger | React.ReactNode |
items | MenuV2GroupType[] |
maxHeight | number |
minHeight | number |
maxWidth | number |
minWidth | number |
enableSearch | boolean |
searchPlaceholder | string |
open | boolean |
onOpenChange | (open: boolean) => void |
asModal | boolean |
alignment | MenuAlignment |
side | MenuSide |
sideOffset | number |
alignOffset | number |
collisonBoundaryRef | Element | null | Array<Element | null> |
MenuItem API Reference
Prop Name | Type |
---|---|
label | string |
subLabel | string |
slot1 | React.ReactNode |
slot2 | React.ReactNode |
slot3 | React.ReactNode |
slot4 | React.ReactNode |
variant | MenuItemV2Variant |
actionType | MenuItemV2ActionType |
disabled | boolean |
onClick | () => void |
subMenu | MenuItemV2Type[] |
Features
- Dropdown menu with customizable positioning
- Support for menu groups with labels and separators
- Icon support with multiple slot positions
- Sub-menu support for nested navigation
- Search functionality for filtering menu items
- Action variants with primary and danger types
- Disabled state support
- Keyboard navigation and accessibility
- Customizable dimensions and styling
- Modal and non-modal rendering modes
Usage Examples
Basic Menu
Simple menu with basic items
const menuItems = [ { label: 'Profile', onClick: () => console.log('Profile clicked'), }, { label: 'Settings', onClick: () => console.log('Settings clicked'), }, ] ;<Menu trigger={<Button text="Open Menu" buttonType={ButtonType.SECONDARY} />} items={[{ items: menuItems }]} />
Menu with Icons
Menu items with leading icons
const menuItems = [ { label: 'Profile', slot1: <User size={16} />, onClick: () => console.log('Profile clicked'), }, { label: 'Settings', slot1: <Settings size={16} />, onClick: () => console.log('Settings clicked'), }, ] ;<Menu trigger={<Button text="Open Menu" buttonType={ButtonType.SECONDARY} />} items={[{ items: menuItems }]} />
Menu with Groups
Menu organized into groups with labels
const menuGroups = [ { label: 'Account', items: [ { label: 'Profile', slot1: <User size={16} /> }, { label: 'Settings', slot1: <Settings size={16} /> }, ], }, { label: 'Actions', items: [ { label: 'Logout', slot1: <LogOut size={16} />, variant: MenuItemV2Variant.ACTION, actionType: MenuItemV2ActionType.DANGER, }, ], showSeparator: true, }, ] ;<Menu trigger={<Button text="Open Menu" buttonType={ButtonType.SECONDARY} />} items={menuGroups} />
Menu with Search
Menu with search functionality
<Menu trigger={<Button text="Search Menu" buttonType={ButtonType.SECONDARY} />} items={[{ items: menuItems }]} enableSearch={true} searchPlaceholder="Search options..." />
Sub-menu
Menu with nested sub-menus
const menuItems = [ { label: 'More Options', slot1: <Settings size={16} />, subMenu: [ { label: 'Edit', slot1: <Edit size={16} /> }, { label: 'Delete', slot1: <Trash size={16} />, variant: MenuItemV2Variant.ACTION, actionType: MenuItemV2ActionType.DANGER, }, ], }, ] ;<Menu trigger={<Button text="Sub Menu" buttonType={ButtonType.SECONDARY} />} items={[{ items: menuItems }]} />
Component Tokens
You can style the menu component using the following tokens:
export type MenuItemStates = | 'default' | 'hover' | 'active' | 'focus' | 'focusVisible' | 'disabled' export type MenuTokensType = { shadow: CSSObject['boxShadow'] backgroundColor: CSSObject['backgroundColor'] paddingTop: CSSObject['paddingTop'] paddingBottom: CSSObject['paddingBottom'] border: CSSObject['border'] outline: CSSObject['outline'] borderRadius: CSSObject['borderRadius'] item: { padding: CSSObject['padding'] margin: CSSObject['margin'] borderRadius: CSSObject['borderRadius'] backgroundColor: { [MenuItemV2Variant.DEFAULT]: { enabled: { [key in MenuItemStates]: CSSObject['backgroundColor'] } disabled: { [key in MenuItemStates]: CSSObject['backgroundColor'] } } [MenuItemV2Variant.ACTION]: { [key in MenuItemV2ActionType]: { enabled: { [key in MenuItemStates]: CSSObject['backgroundColor'] } disabled: { [key in MenuItemStates]: CSSObject['backgroundColor'] } } } } cursor: CSSObject['cursor'] gap: CSSObject['gap'] label: { fontSize: CSSObject['fontSize'] fontWeight: CSSObject['fontWeight'] color: { [MenuItemV2Variant.DEFAULT]: { enabled: { [key in MenuItemStates]: CSSObject['color'] } disabled: { [key in MenuItemStates]: CSSObject['color'] } } [MenuItemV2Variant.ACTION]: { [key in MenuItemV2ActionType]: { enabled: { [key in MenuItemStates]: CSSObject['color'] } disabled: { [key in MenuItemStates]: CSSObject['color'] } } } } } subLabel: { fontSize: CSSObject['fontSize'] fontWeight: CSSObject['fontWeight'] color: { [MenuItemV2Variant.DEFAULT]: { enabled: { [key in MenuItemStates]: CSSObject['color'] } disabled: { [key in MenuItemStates]: CSSObject['color'] } } [MenuItemV2Variant.ACTION]: { [key in MenuItemV2ActionType]: { enabled: { [key in MenuItemStates]: CSSObject['color'] } disabled: { [key in MenuItemStates]: CSSObject['color'] } } } } } } seperator: { color: CSSObject['color'] height: CSSObject['height'] margin: CSSObject['margin'] } }