Actions
IDropdownMenu
A menu opened from a button. Entries are data, and their shape decides what they render as — the same rule ISelect and INavigationMenu follow.
Nothing chosen yet.
Four shapes, one array, decided in this order:
| The entry | Renders as |
|---|---|
The string '-' | A separator |
Has its own items | A submenu |
Has an onSelect | A menu item |
| Has neither | A group label |
An entry with no onSelect and no items is a heading
onSelect silently turns an action into a heading. If an item does nothing when you click it, this is why. Group labels are the intended use:
Danger items
danger colours a destructive entry. It does not confirm anything — pair it with useConfirm() when the action cannot be undone.
const items = [
{ label: 'Archive', onSelect: () => archive() },
'-',
{
label: 'Delete invoice',
danger: true,
onSelect: async () => {
if (await confirm({ title: 'Delete this invoice?' }))
remove()
},
},
]Placement
side and align position the menu against its trigger, and sideOffset sets the distance. Like the tooltip, side is a preference — the menu flips when there is not enough room.
Icons
An entry's icon takes a Hugeicons icon or any component that renders an SVG.
import { Delete02Icon, PencilEdit02Icon } from '@hugeicons/core-free-icons'
const items = [
{ label: 'Edit', icon: PencilEdit02Icon, onSelect: () => edit() },
{ label: 'Delete', icon: Delete02Icon, danger: true, onSelect: () => remove() },
]Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | DropdownMenuEntry[] | [] | The menu contents |
align | 'start' | 'center' | 'end' | 'start' | Alignment against the trigger |
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Preferred side; flips when it will not fit |
sideOffset | number | 4 | Distance from the trigger, in px |
unstyled | boolean | — | Drop built-in classes |
class | string | — | Merged with the built-in classes |
ui | { content?, item?, label?, separator?, subTrigger?, subContent? } | — | Per-slot class overrides |
interface DropdownMenuItemOption {
label: string
icon?: IconLike
disabled?: boolean
danger?: boolean
onSelect?: () => void
/** Makes this entry a submenu. */
items?: DropdownMenuEntry[]
}
type DropdownMenuEntry = DropdownMenuItemOption | '-'Slots
| Slot | When to use it |
|---|---|
trigger | The button that opens the menu. Required |
A dropdown menu is for actions. For choosing a value, use ISelect — it has a model, the right ARIA roles, and typeahead.