Skip to content

Headless Core — Dropdown

Powers Dropdown internally. Built on createMenuSelection for its selectItem action.

import { createDropdown } from '@andersseen/headless-components/dropdown';
const dropdown = createDropdown({
placement: 'bottom',
closeOnSelect: true,
onOpenChange: isOpen => console.log('Open:', isOpen),
onSelect: e => console.log('Selected:', e.itemId),
});
dropdown.actions.toggle();
OptionTypeDefaultNotes
defaultOpenbooleanfalse
onOpenChange(isOpen: boolean) => void
closeOnSelectbooleantrueForwarded to createMenuSelection.
onSelect(e: { itemId?: string }) => voidForwarded to createMenuSelection.
placement'top' | 'bottom' | 'left' | 'right''bottom'
disabledbooleanfalseSetting true while open force-closes it.

isOpen, placement, disabled.

MemberSignature
actions.open() / close() / toggle()() => void
actions.selectItem(itemId?)(itemId?: string) => void
actions.setDisabled(v)(disabled: boolean) => void
queries.isOpen()() => boolean
GetterReturns
getTriggerProps()aria-haspopup: 'menu', aria-expanded, aria-disabled, data-state
getContentProps()role: 'menu', data-state, hidden
getItemProps(itemId?)role: 'menuitem', tabindex (0 only while open)

handleTriggerKeyDown(event) opens on Enter/Space/ArrowDown/ArrowUp (actual focus-into-menu is left to the consuming component). handleContentKeyDown(event, allItemIds) closes on Escape or Tab — it takes allItemIds in its signature but doesn’t currently use it for navigation (arrow-key movement inside the open menu is left to Menu List if you compose the two, or to your own handler).

Toggle dropdown

Context Menu shares the same createMenuSelection-based selectItem action, for pointer-position-anchored menus instead of trigger-anchored ones.