Menu
ImplementedDropdown command list. Context menu or navigation menu with items, separators (item.divider), custom content rows (item.content — search fields, rich blocks), and submenus. Header's responsive MoreMenu overflow composes this molecule (L8b, Wave 3 Tier-2).
components/molecules/Menu/Menu.tsxDropdown menu anchored to a trigger element.
Menu
organisms
Portalled dropdown menu with keyboard navigation, dismiss layer, and placement control. Items are either canonical menuitem buttons (icon + label, destructive/disabled) or custom non-interactive content rows.
Usage
Provide any element as trigger — Menu clones it, wiring up aria-haspopup, aria-expanded, and the open/close toggle. The menu portals to document.body; keyboard navigation, focus management, and outside-click dismissal are built in.
import { Menu, Button } from '@epasslive/design-system'
const [open, setOpen] = useState(false)
<Menu
open={open}
onOpenChange={setOpen}
trigger={<Button variant="secondary">Event actions</Button>}
items={[
{ id: 'view', label: 'View event page', onSelect: () => setOpen(false) },
{ id: 'edit', label: 'Edit details', onSelect: () => setOpen(false) },
]}
/>Props
items*MenuItem[]Menu rows — button items (label, onSelect) or custom content rows.
trigger*React.ReactElementElement the menu anchors to; Menu injects aria-haspopup/expanded and the toggle handler.
placementDropdownPlacement"bottom-start"Anchor position relative to the trigger.
openbooleanControlled open state.
defaultOpenbooleanfalseInitial open state for uncontrolled usage.
onOpenChange(open: boolean) => voidCalled on toggle, Escape, and outside dismiss.
ariaLabelstringAccessible name for the menu (defaults to "Menu").
classNamestringAdditional CSS classes on the trigger wrapper.
idstringStable id prefix for the menu element.
Props
itemsMenuItem[]—Menu items
triggerReact.ReactNode—Trigger element
placement'bottom-start' | 'bottom-end' | 'top-start' | 'top-end''bottom-start'Menu position
onAction(key: string) => void—Item action handler
<Menu />Accessibility
ARIA
2 rulesKeyboard
1 ruleUsage
Import
import { Menu } from "@epasslive/design-system"Example 1
<Menu />Example 2
<Menu variant="default" />Anti-patterns
— Do not hardcode menu items — pass them via the items prop
— Avoid nesting menus deeper than two levels