Client component

Menu

An action menu on the APG menu-button pattern: roving focus, typeahead, and full keyboard support.

Import#

import { Menu } from "astralis-ui";

Placement#

Props#

PropTypeDefaultDescription
open / defaultOpen / onOpenChangeboolean / boolean / (open: boolean) => voidNoneControlled/uncontrolled open state.
side"top" | "bottom" | "left" | "right""bottom"Preferred side (flips on collision).
align"start" | "center" | "end""start"Alignment along the trigger.
sideOffsetnumber6Gap to the trigger, px.
closeOnSelectbooleantrueClose after an item activates.
PropTypeDefaultDescription
onSelect() => voidNoneRuns on click, Enter or Space.
disabledbooleanfalseSkipped by arrow-key focus and can't be activated.
dangerbooleanfalseDestructive styling, for delete and remove.
iconReactNodeNoneLeading glyph.
shortcutReactNodeNoneTrailing hint, such as a Kbd shortcut.
closeOnSelectbooleanthe menu'sOverrides the menu's closeOnSelect for this item.

Parts#

Menu.Trigger (wraps your button; wires aria-haspopup/aria-expanded), Menu.Content, Menu.Label, Menu.Separator, Menu.Group.

Keyboard#

KeyAction
Enter / Space / ↓ on triggerOpen (focus moves to the first item)
↑ ↓Move focus (wraps)
Home / EndFirst / last item
type charactersJump to the item starting with what you typed
Enter / SpaceActivate the focused item
EscClose, return focus to the trigger
TabClose

Accessibility#

  • role="menu" / role="menuitem" with aria-haspopup="menu" and aria-expanded on the trigger; disabled items are aria-disabled and skipped by focus movement.
  • Hover focuses items, so pointer and keyboard share one highlight state.
  • Escape/outside-click dismissal runs through the shared overlay stack: a Menu inside a Modal peels first.