DropdownMenu

A trigger button that opens a floating menu of actions with arrow-key navigation, typeahead, separators, and disabled items.

Installation

npx dafink-ui add dropdown-menu

Demo

Props

NameTypeDefaultDescription
itemsDropdownMenuEntry[]-Array of items ({ label, onSelect?, disabled? }) and separators ({ separator: true }).
triggerReactNode-Content of the built-in trigger button.
side'top' | 'right' | 'bottom' | 'left''bottom'Which side of the trigger the menu appears on.
align'start' | 'center' | 'end''start'Alignment along the chosen side.
onSelect(item: DropdownMenuItem) => voidundefinedCalled with the activated item, in addition to the item's own onSelect.
disabledbooleanfalseDisables the trigger.
classNamestring''Additional classes on the menu list.
triggerClassNamestring''Additional classes on the trigger button.

Accessibility

DropdownMenu uses virtual focus, not roving tabindex: the menu list itself takes DOM focus (tabIndex={-1}) on open, and the highlighted item is tracked purely via aria-activedescendant rather than moving real DOM focus between <li role="menuitem"> items. It is a non-modal popup: Tab is never trapped, it closes the menu and continues to the next page element. The trigger carries aria-haspopup="menu"/aria-expanded/aria-controls; the list is role="menu"; separators are role="separator".

KeyFunction
enterOn trigger: opens the menu. In the menu: activates the active item and closes.
spaceSame as Enter.
down arrowOn trigger: opens with the first item active. In the menu: moves to the next enabled item, wrapping.
up arrowOn trigger: opens with the last item active. In the menu: moves to the previous enabled item, wrapping.
homeMoves to the first enabled item.
endMoves to the last enabled item.
escapeCloses the menu and returns focus to the trigger.
tabCloses the menu without intercepting the keypress, so focus continues to the next page element.