General
Menu from @prepared911/ui-core is a Radix Dropdown Menu. The primitive wires menu roles, keyboard flow, and focus trap; your job is to keep item labels clear, name icon-only items, and avoid menus whose only discoverable path is hover.
role="menu"; items expose role="menuitem", menuitemcheckbox, or menuitemradio.MenuItemRadio description does not change type-ahead.Button or IconButton so the trigger exposes aria-haspopup="menu" and aria-expanded.MenuItemCheckbox, MenuItemSwitch, or MenuItemRadio—see Interactive MenuItem children. Do not nest a separate interactive checkbox, switch, or radio inside a menu item.Checkbox, switch, and radio rows are still one interactive widget: the menu item itself. Nesting a real Checkbox, Switch, or radio control inside a MenuItem creates a nested-interactive violation—screen readers and keyboard focus then see two controls where there should be one.
| Need | Component | Role | Visual indicator |
|---|---|---|---|
| Multi-select / independent on-off | MenuItemCheckbox | menuitemcheckbox | CheckboxVisual |
| Persistent preference toggle | MenuItemSwitch | menuitemcheckbox | SwitchVisual |
| Single choice in a set | MenuItemRadio inside MenuGroup | menuitemradio | Decorative radio mark |
| Select-all over an expandable category | MenuCollapsibleGroup | menuitemcheckbox + aria-expanded | CheckboxVisual, tri-state |
MenuItemSwitch paints like a switch for sighted users but uses the same Radix checkbox-item primitive as MenuItemCheckbox, so assistive tech still gets menuitemcheckbox + aria-checked.
aria-checked live on the menuitemcheckbox / menuitemradio. Arrow keys move between items; do not add a nested tab stop.CheckboxVisual and SwitchVisual are always aria-hidden. Do not use them as standalone form controls, and do not nest interactive Checkbox / Switch for the checkmark or thumb.aria-checked. Controlled checked (checkbox/switch) or MenuGroup value (radio) drives both the indicator and the announced state. A partial selection must be "indeterminate", which paints the dash and announces aria-checked="mixed"; never round it to checked or unchecked.MenuCollapsibleGroup puts aria-checked and aria-expanded on the same row. Its chevron is aria-hidden and pointer-only; keyboard users expand with ArrowRight and collapse with ArrowLeft, so no nested tab stop is introduced.MenuItemRadio trailing is aria-hidden paint; pointer isolation may handle extra clicks, but keyboard extras go on the radio item's onKeyDown. Extra state that trailing represents (for example sort direction) belongs on the radio via aria-label / description.label (or equivalent accessible name). Don't rely on the decorative indicator alone.For attribute-level detail, see ARIA Attributes. Combobox multi-select overflow rows follow the same decorative-indicator pattern—see Combobox accessibility.