Components › Forms & input › Button › Menu button

Menu button

canon

The one action menu of the app: a labelled button with a chevron, or the kebab „⋯“ (iconOnly), opening a menu of actions; no action is the default one.

AD + owner 28 Sep 2026 („sjednotit popover do menu-button“): Menu button is THE action menu — the row anatomy moved here from Popover. Row: .ic (icon | iconNode) · label (.tx > .nm when something is on the right) · .tag · .acrm-kbd (aria-hidden) · .chk (checked rows); variants danger (auto separator before the first danger row), strong, disabled + title (tooltip + aria-describedby); empty/loading row {empty} = .acrm-popover-empty. Kebab = iconOnly → canonical IconButton (sm / framed), label = aria-label + phone sheet title, aria-haspopup/expanded + stopPropagation by the component. „Dimmed but clickable“ rows do not exist. Phone = BottomSheet. Mechanical refactor moved 18 hand-built Popover menus onto it (acrm MR, 28 Sep 2026); sub-menu (mail „Přesunout do složky ›“, reservation „Předat…“), menu header (account menu) and insert menus wait for an approved shape (MR-B). History: FA204, 26 Sep 2026 (acrm !3890) 1:1 port of „Přidat aktivitu“ (P144, TL-12); custom trigger({open, menu, onClick}) acrm !3899 (dialog chip row, rail link !4014). forceMenu (menu even with one item) and danger items (2026-09-28, acrm !4088). Touch (AD 28 Sep 2026, acrm !4111): in the phone sheet a disabled item shows its title as a visible second line .acrm-popover-reason (--hint, --ink-600, aligned with the label, outside the button) — MenuItems sheet; desktop keeps the tooltip. 3 Oct 2026: MenuButtonItem count / countTone / muted / actions / actionsLabel (acrm !4527). Registry repaired 17 Oct 2026 (review F6): added exported MenuPanel to react[].

Used in 63 files · 33 areas · 69× — components/AppShell, components/FilterBar, components/NavItemMenu, components/ReservationControl, components/accounting, components/assistant …

Keyboard

  • Tab reaches the button; Enter / Space opens the menu and focus moves to the first item.
  • Arrow Up / Down, Home and End move between items; Enter activates one, closes the menu and returns focus to the button.
  • Escape closes the menu and returns focus to the button (shared Popover behaviour).

ARIA

  • The button carries aria-haspopup="menu" and aria-expanded; the menu is role="menu" named by the button's label.
  • Items are role="menuitem" (menuitemradio + aria-checked for checked rows); the glyph and a custom mark are decorative, ariaLabel names a row whose label alone is ambiguous.
  • A disabled item with a title is described by it: tooltip + aria-describedby pointing to a visually hidden sibling (outside the button, so it does not join the accessible name). The phone sheet uses the same hidden sibling — no visible second line (owner 28 Sep 2026, ACRM-375–377).
  • Every row carries its full label in title, so a label cut by the ellipsis stays readable on hover; the accessible name is always the full label.
  • A submenu row carries aria-haspopup="menu"; its chevron is aria-hidden. Entering it replaces the rows in the same role="menu" — the back row is a menuitem named by the submenu's label („Zpět" in the phone sheet, whose title names the level). Enter / Space on the submenu row opens the level; Enter on the back row returns.
  • A switch row is role="menuitemcheckbox" with aria-checked; the .acrm-switch drawing is aria-hidden. Activating it keeps the menu open and focus on the row, so the new state is announced.
  • The header (identity block) is not an item: plain content above the first separator, skipped by arrow keys.
  • The keyboard shortcut (.acrm-kbd) is aria-hidden — the label names the action.
  • The empty / loading row is plain text, not an item; a menu holding only it is still role="menu".
  • Icon-only trigger (kebab): the canonical IconButton with aria-label = the required label; the component sets aria-haspopup / aria-expanded, the host never does.
  • With a single item there is no menu: the button carries neither attribute and runs the action directly.

Focus

  • The button draws the foundation focus ring of Button; items use the Popover item focus style.

Contrast

  • Same tokens as Button and Popover; nothing of its own.

Known limits

  • No typeahead (jump to an item by its first letter) — the shared Popover does not provide it.

Source: docs/button/menu-button.a11y.md · GitLab