Skip to content
Site volume
Colourway

Components

Menu

A list of actions behind a key, with shortcuts, checkbox and radio items and submenus.

  • Experimental
  • Reading layer
  • Client leaf
  • Since 0.9.0
  • Press check
Import from@maxgrits/overprint-react/menu
On this page

Menu holds a short list of actions behind a key. Rows are 40 px with an optional glyph at the start and a Kbd shortcut at the end; the highlighted row takes the hover face and a 4 px ink bar, so it reads without colour. Checkbox and radio items, group labels, separators and submenus are parts of the same file.

Example#

Look of this example
Live render of examples/menu/basic.tsx

Usage#

Use a menu for a short list of actions behind one key: duplicate, flag, archive. The trigger is a Button or an IconButton; rows are 40 px with an optional glyph and a keyboard shortcut.

  • Parts. MenuItem, MenuCheckboxItem, MenuRadioGroup with MenuRadioItem, MenuGroup with MenuLabel, MenuSeparator and MenuSubmenu for one level of nesting.
  • Keyboard. Arrows move, letters jump, Enter or Space activates, the right arrow opens a submenu and Escape closes.
  • The highlighted row takes the hover face and a 4 px ink bar at its start, so it reads without colour.
  • Navigation is a list of links or the Navbar, not a menu. Choosing a value in a form is a Select or a Combobox.

Recipe: view settings with check and radio items#

"use client";
import {
  Menu, MenuCheckboxItem, MenuContent, MenuGroup, MenuLabel,
  MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuTrigger,
} from "@maxgrits/overprint-react/menu";

export function ViewMenu() {
  return (
    <Menu>
      <MenuTrigger size="sm">View</MenuTrigger>
      <MenuContent>
        <MenuGroup>
          <MenuLabel>Show</MenuLabel>
          <MenuCheckboxItem defaultChecked>Archived projects</MenuCheckboxItem>
          <MenuCheckboxItem>Private notes</MenuCheckboxItem>
        </MenuGroup>
        <MenuSeparator />
        <MenuRadioGroup defaultValue="week">
          <MenuLabel>Group by</MenuLabel>
          <MenuRadioItem value="week">Week</MenuRadioItem>
          <MenuRadioItem value="client">Client</MenuRadioItem>
        </MenuRadioGroup>
      </MenuContent>
    </Menu>
  );
}

Check and radio items keep the menu open after a press, so several settings can change in one visit; Escape or a press outside closes it.

Anatomy#

The parts of examples/menu/anatomy.tsx, numbered:
  1. PlateRaised surface, 2 px rule, 200 px at least..mk-menu-popup
  2. Group labelLabel role in the second ink..mk-menu-label
  3. GlyphOptional, 18 px, from the shape alphabet..mk-menu-item-start
  4. LabelRow-title type, a verb..mk-menu-item-label
  5. ShortcutKbd caps for the keys..mk-menu-item-end
  6. Separator2 px soft rule between groups..mk-menu-separator

Volume#

Reading layer: identical at every volume.

  • Quiet

    Docs, forms, legal and long reads. Flat inks, no art in motion.

  • Studio

    The site default. Art on its own plates, one display moment per view.

  • Press

    Hero moments, covers and campaigns. Halftone fields and the second ink.

  • Rave

    Launches, posters and the 404. Every ink, and the words still win.

Content#

  • Items are verbs: "Duplicate", "Archive", "Flag for review".
  • Put the most common action first and destructive ones last, after a separator.
  • An action that cannot be undone says so in a confirming dialog, not in the menu label.

Do and don't#

Do

A handful of actions, grouped.

Don't

A menu of twelve items in three submenus.

A maze of submenus.

Menus are for a few actions people scan in a second. A long or nested list hides its options; split it, or move the actions onto the page.

Accessibility#

  • The APG menu pattern through Base UI: arrows, Home and End, typeahead, Enter and Space, Escape back to the trigger, Tab closes and moves on.
  • The trigger carries aria-haspopup="menu"; checkbox and radio items carry aria-checked.
  • It portals with its trigger's scope; reduced motion keeps only the fade.
KeysWhat happens
EnterorSpaceorArrow DownOn the trigger: opens the menu on its first item
Arrow UporArrow DownMoves between items
HomeorEndFirst or last item
A letterMoves to the next item starting with it
EnterorSpaceChooses the item
Arrow RightorArrow LeftOpens or closes a submenu
EscapeCloses the menu; focus returns to the trigger
TabCloses the menu and moves on

The colour pairs it prints, with their contrast on both papers:

TextSurfaceRoleBoneNight
--mk-text--mk-surface-raiseduinot in this looknot in this look
--mk-text--mk-hoveruinot in this looknot in this look

Process at Studio, normal contrast. Every look: the press check.

Props#

PropTypeDefaultDescription
openbooleannone
defaultOpenbooleannone
onOpenChange((open: boolean) => void)none
modalbooleantrueA modal menu locks the page while open (default true, Base UI's).
children requiredReactNodenone

Generated from MenuProps in packages/overprint-react/src/reading/menu/menu.tsx.

Tokens#

System tokens (18)

Its own properties (5)

  • --mk-menu-leading
  • --mk-menu-pad
  • --mk-menu-row
  • --mk-menu-start
  • --mk-menu-start-gap

Scanned from its CSS at build and checked against its registry entry; 2 read but not declared there.

Changelog#

Arrived in 0.9.0.

0.9.024 October 2026

  • MinorreactCombobox and ComboboxItem (a case- and accent-insensitive filter by default, groups, chips for multiple, "Searching…", an empty message, a live result count, and inline for a list printed in place), Popover with PopoverTrigger, PopoverContent and PopoverClose, Menu with its eleven parts (shortcuts as Kbd caps, checkbox and radio items, group labels, separators, submenus), and ToastProvider with useToast (a slab pill, one at a time with three waiting, 5.2 s with a drain bar that holds while the region is hovered, focused or the window is away). Read the whole entry