DropdownMenu
A value picker with a button trigger and a list of options.
import { DropdownMenu } from '@aksornproject/aksara-ui'For a labelled form field, use Select. To run actions, use Menu.
Sort picker
DropdownMenu has 11 parts. DropdownMenu.Root is Select.Root. DropdownMenu.Button is a library Button that shows leadingText, the selected value and a trailingNode that swaps between its open and closed nodes. DropdownMenu.List is the portal, positioner, popup and list in one part.
The popup is at least 230px wide and at most 256px tall, with a border and a 10px radius. A selected item shows a 24px accent tick. selectedIndicator replaces the tick, and an empty fragment hides it.
<DropdownMenu.Root items={options} value={sort}>
<DropdownMenu.Button
variant="secondary-accent"
leadingText="Sort by:"
trailingNode={{
open: <IconInterfaceEssentialArrow1 className="ml-auto" />,
closed: <IconInterfaceEssentialArrow className="ml-auto" />,
}}
className="w-[216px]"
/>
<DropdownMenu.List align="end">
{options.map((item) => (
<DropdownMenu.Item
key={item.value}
value={item.value}
onClick={() => setSort(item.value)}
>
{item.label}
</DropdownMenu.Item>
))}
</DropdownMenu.List>
</DropdownMenu.Root>With Select
This is the same sort picker built with Select. Select.Trigger puts the label above the field, and the popup is at least 280px wide. For a list of actions, use Menu, whose items are announced as menuitem rather than option.
<div className="w-[216px]">
<Select.Root
items={options}
value={sort}
onValueChange={(value) => value && setSort(value)}
>
<Select.Trigger label="Sort by" />
<Select.Portal>
<Select.Positioner align="end">
<Select.Popup>
<Select.List>
{options.map((item) => (
<Select.Item key={item.value} value={item.value}>
{item.label}
</Select.Item>
))}
</Select.List>
</Select.Popup>
</Select.Positioner>
</Select.Portal>
</Select.Root>
</div>Accessibility
DropdownMenu.Buttonis one native button withrole="combobox". Its defaulttypeisbutton, so opening it inside a form does not submit the form.- A
DropdownMenu.Triggerwith a libraryButtonchild makes that button the trigger, so buttons do not nest. - The popup is a
listboxofoptions. An action menu built on it announces values, not actions. UseMenufor actions. - Arrow keys reach disabled items, but Enter and clicks do not select them.
API
DropdownMenu.Root
DropdownMenu.Root is Select.Root.
Prop
Type
DropdownMenu.Button
A library Button, size="lg" by default, that takes every Button prop and these two. Its children are ignored. Its event handlers run before the Base UI handlers. disabled stops it opening.
| Prop | Type | Default |
|---|---|---|
leadingText | string | required |
trailingNode | { open: ReactNode; closed: ReactNode } | none |
Prop
Type
DropdownMenu.List
Takes the Base UI Select Popup props, children and these positioning props. className merges on the popup.
| Prop | Type | Default |
|---|---|---|
side | Side | 'bottom' |
sideOffset | number | OffsetFunction | 4 |
align | Align | 'start' |
alignOffset | number | OffsetFunction | 0 |
alignItemWithTrigger | boolean | false |
DropdownMenu.Item
Takes the Base UI Select Item props. className merges with the defaults instead of replacing them.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | required |
selectedIndicator | ReactNode | the 24px accent tick |
DropdownMenu.Trigger
Takes the Base UI Select Trigger props. A library Button child becomes the trigger. Other children render inside the Base UI trigger.
DropdownMenu.Positioner
DropdownMenu.Value, Icon, Positioner, Popup, ItemIndicator and ItemText are the unstyled Base UI Select parts.
Prop
Type