# Core/Menu - Design

## Properties

### Label

A label is required for all menu items. Their length may vary based on application but should always be succinct.

### Description

Descriptions can provide secondary information to menu items.

### Icon

Capra does not suggest the use of icons in menu items, but an optional slot is available when an icon adds significant recognition.

### Shortcut

Shortcuts enable users to more easily access common commands. If available, shortcuts to a command should be shown at the right. A menu does not need to be open for a shortcut to work.

### Indent

Use `Menu.Section` to group `Menu.Item` rows. Add an optional `Menu.Header` inside the section to label the group; items in that section indent automatically to show hierarchy. A `Menu.Header` outside a section is only a label and does not indent following items—wrap the header and its items in `Menu.Section` when you want indentation. Sections without a header must be named for assistive technology with `aria-label` or `aria-labelledby`. You can still set `indent` on an item to override the default.

## Content

### Ellipsis

Use ellipsis to indicate when the menu item leads to additional steps. This is normally followed by a modal.

### Divider

Dividers provide subtle separation between list items. They can be used to group items when a header is not necessary. Use `Menu.Divider` between menu items to create visual separation.

## Selection

### Single selection

Single selection items act as radio buttons within a menu. Use the `active` prop to indicate the current page or selected item.

### Multiple selection

Multiple selection items act as checkboxes within a menu. Users can select more than one item. Use the `active` prop on each `Menu.Item` to indicate selected items. Manage selection state in your application.

### Section-level selection

When single and/or multiple section options are used alongside other option types, use Sections to group each selection type.

## Behavior

### Focus containment (`trapFocus`)

Set **`trapFocus`** on **`Menu`** when keyboard focus must stay inside the menu panel while it is open—for example horizontal **`TabNav`** flyouts that sit next to other tab stops. The popover stays **non-modal**, so outside pointer dismiss still works. Focus **containment** turns on once focus has entered the panel (so the trigger can still move focus into the menu on open); **`restoreFocus`** returns focus to the trigger when the menu closes.

When **`trapFocus`** is omitted (**default `false`**), focus follows the usual tab sequence for a non-modal overlay.

### Submenu

Use `Menu.Submenu` for nested flyouts: Capra requires `SubmenuTrigger` → `Popover` → `Menu` so the nested panel is positioned to the side (not stacked under the trigger). The parent row shows a trailing chevron; hover or keyboard opens the submenu. The `parent` prop on `Menu.Item` only adds the chevron for labels without a submenu.

### Minimum and maximum width

Menu items have a minimum width of 152px and maximum width of 256px. Content that extends beyond the maximum width is truncated. An ellipsis is *not* added due to the special meaning of the ellipsis following an item label. Care should be taken to ensure menu item labels remain short and succinct to avoid running over the maximum width.

## Best Practices

### Menu Size

**Do**

<img className="w-full" src="images/guidelines/menu/bestpractices-size-do.png" alt="Menu with appropriate number of items" />

<p>
  Do keep menus to as few items as possible, aim for no more than 5 items.
</p>

**Don't**

<img className="w-full" src="images/guidelines/menu/bestpractices-size-dont.png" alt="Overly long menu" />

<p>
  Don't overload menu item choices.
</p>

## Accessibility

### Keyboard interaction

| Key                   | Function                                                                                                                                                  |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Tab` / `Shift + Tab` | Moves focus to, or away from, the trigger. If the menu is open, focus shifts away from the trigger and the menu closes.                                   |
| `Enter`               | If the trigger has focus: opens the menu and focuses the first item. If a menu item has focus: activates that item and closes the menu.                   |
| `Space`               | If the trigger has focus, opens the menu and focuses the first item.                                                                                      |
| `Down Arrow`          | If the trigger has focus: opens the menu and focuses the first item. If a menu item has focus: moves focus to the next item, wrapping from last to first. |
| `Up Arrow`            | If a menu item has focus: moves focus to the previous item, wrapping from first to last.                                                                  |
| `Esc`                 | Closes the menu and returns focus to the trigger.                                                                                                         |
| `[a-z]`               | Move focus to the next item whose label begins with that printable character.                                                                             |

### Aria considerations

* Triggers must have an accessible name (`aria-label` or `aria-labelledby`) or label.
* Triggers must have `aria-haspopup="menu"` and use `aria-expanded="true|false"`.
* Use `role="menu"` on menu container.
* Use `role="menuitem"` on each menu item.
* Use `role="separator"` if a separator is used.
* Group related items with `Menu.Section` (`role="group"`). When the section includes `Menu.Header`, the section is named via `aria-labelledby` (the header gets an id). Headerless sections must expose a name with `aria-label` or `aria-labelledby`.