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();Config
Section titled “Config”| Option | Type | Default | Notes |
|---|---|---|---|
defaultOpen | boolean | false | |
onOpenChange | (isOpen: boolean) => void | — | |
closeOnSelect | boolean | true | Forwarded to createMenuSelection. |
onSelect | (e: { itemId?: string }) => void | — | Forwarded to createMenuSelection. |
placement | 'top' | 'bottom' | 'left' | 'right' | 'bottom' | |
disabled | boolean | false | Setting true while open force-closes it. |
isOpen, placement, disabled.
Actions & queries
Section titled “Actions & queries”| Member | Signature |
|---|---|
actions.open() / close() / toggle() | () => void |
actions.selectItem(itemId?) | (itemId?: string) => void |
actions.setDisabled(v) | (disabled: boolean) => void |
queries.isOpen() | () => boolean |
Prop-getters & handlers
Section titled “Prop-getters & handlers”| Getter | Returns |
|---|---|
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).
Live example
Section titled “Live example”Next steps
Section titled “Next steps”Context Menu shares the same
createMenuSelection-based selectItem action, for pointer-position-anchored
menus instead of trigger-anchored ones.