Dropdown Menu

Composable WAI-ARIA dropdown menu that springs open with a scale and fade from the trigger side, with a gliding active-row highlight, checkbox and radio items, icons and shortcuts, a destructive variant, hover-intent submenus, typeahead, full arrow/Home/End/Escape keyboard support and viewport-aware flipping.

Preview

Dropdown Menu preview width

Install

Add it with the shadcn CLI, or copy the source manually.

$ bunx --bun shadcn add @karaui/dropdown-menu
@karaui not found? Add it to components.json
{
  "registries": {
    "@karaui": "https://karaui.kamisama-v0.my.id/r/{name}.json"
  }
}

@karaui is in shadcn's public registry directory, so the latest CLI needs no setup. On an older CLI, merge this into the existing file once and every @karaui/… install resolves.

API Reference

DropdownMenu

open?
boolean

Controlled open state.

—
defaultOpen?
boolean

Uncontrolled initial open state.

false
onOpenChange?
((open: boolean) => void)
—
className?
string
—

DropdownMenuTrigger

children
ReactElement<TriggerChildProps, string | JSXElementConstructor<any>>

A single element, normally a `<button>`. Its own handlers still run.

—
className?
string
—

DropdownMenuContent

side?
"bottom" | "top"

Preferred side; flips when the viewport lacks room. Default "bottom".

bottom
align?
"end" | "start" | "center"

Alignment against the trigger. Default "start".

start
sideOffset?
number

Gap between trigger and panel, in px. Default 6.

6
alignOffset?
number
0
ariaLabel?
string

Accessible name; defaults to the trigger's text via aria-labelledby.

—
className?
string
—

DropdownMenuItem

icon?
ReactNode

Leading icon (sized to 16px).

—
shortcut?
ReactNode

Trailing shortcut hint, e.g. "⌘K" or a `KbdCombo`. Decorative.

—
variant?
"default" | "destructive"
—
disabled?
boolean
—
inset?
boolean

Indent to line up with checkbox/radio rows.

—
textValue?
string

Text used by typeahead when children aren't plain text.

—
onSelect?
((event: MouseEvent<HTMLButtonElement, MouseEvent>) => void)

Call `event.preventDefault()` to keep the menu open.

—
closeOnSelect?
boolean

Default true.

true
className?
string
—

DropdownMenuCheckboxItem

checked?
boolean
—
defaultChecked?
boolean
false
onCheckedChange?
((checked: boolean) => void)
—
disabled?
boolean
—
className?
string
—
variant?
"default" | "destructive"
—
closeOnSelect?
boolean

Default true.

false
textValue?
string

Text used by typeahead when children aren't plain text.

—
shortcut?
ReactNode

Trailing shortcut hint, e.g. "⌘K" or a `KbdCombo`. Decorative.

—

DropdownMenuRadioGroup

value?
string
—
defaultValue?
string
—
onValueChange?
((value: string) => void)
—
ariaLabel?
string

Accessible name for the group.

—
className?
string
—

DropdownMenuRadioItem

value
string
—
disabled?
boolean
—
className?
string
—
variant?
"default" | "destructive"
—
closeOnSelect?
boolean

Default true.

false
textValue?
string

Text used by typeahead when children aren't plain text.

—
shortcut?
ReactNode

Trailing shortcut hint, e.g. "⌘K" or a `KbdCombo`. Decorative.

—

DropdownMenuLabel

inset?
boolean
false
className?
string
—

DropdownMenuGroup

ariaLabel?
string
—
className?
string
—

DropdownMenuSeparator

className?
string
—

DropdownMenuSubTrigger

icon?
ReactNode
—
disabled?
boolean
—
inset?
boolean
—
textValue?
string
—
className?
string
—

DropdownMenuSubContent

side?
"left" | "right"

Preferred side; flips when the viewport lacks room. Default "right".

right
sideOffset?
number

Gap from the parent panel, in px. Default 8.

8
alignOffset?
number

Shift so the first row lines up with the trigger row. Default -7.

-7
ariaLabel?
string
—
className?
string
—

Updated