Menus

Menus display a list of choices on temporary surfaces, typically triggered by buttons or context actions. They allow users to select from a set of options without cluttering the interface.


Installation

Copy the menu CSS from styles/docs.css or include the Standard stylesheet:

<link rel="stylesheet" href="standard.min.css">

Then use menu classes in your HTML:

<div class="Menu">
    <button class="Menu-item">Edit</button>
    <button class="Menu-item">Delete</button>
</div>

Usage

The base .Menu class provides the menu container styling. Add .Menu--open to show the menu, and use .Menu-item for each action.


Examples

Basic Menu

A simple dropdown menu with clickable items.

Add leading icons to menu items for visual recognition.

Display keyboard shortcuts alongside menu items.

Group related items with headers.

Checkable Menu

Menu items with checkboxes or radio buttons for toggling options.

Menu items that expand to show nested options.

Compact Menu

A denser menu variant for space-constrained areas or toolbars.

Add secondary text for more context on complex actions.

Context Menu

Right-click style context menu for in-place actions.

Right-click area (simulated)

Disabled Items

Menu items that are not currently available.


Common Patterns

User Account Menu

Toolbar Actions Menu

Table Row Actions

Project Proposal.pdf
2.4 MB · Jan 15, 2026

Customization

Override menu styles using CSS custom properties:

/* Custom menu appearance */
.Menu {
  --menu-bg: var(--bg);
  --menu-border: var(--border-primary);
  --menu-shadow: var(--shadow-lg);
  --menu-radius: var(--radius-lg);
}

/* Custom item styling */
.Menu-item {
  --menu-item-padding: var(--space-2) var(--space-3);
  --menu-item-hover: var(--bg-s);
}

/* Danger variant color */
.Menu-item--danger {
  --menu-item-color: var(--color-danger);
}

/* Custom compact variant */
.Menu--compact .Menu-item {
  --menu-item-padding: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
}

/* Wider menu */
.Menu--wide {
  min-width: 280px;
}

API Reference

Container Classes

Class Description
.Menu Base menu container (hidden by default)
.Menu--open Shows the menu (display: block)
.Menu--compact Denser padding for compact layouts
.Menu--context Context menu styling (absolute positioning)

Item Classes

Class Description
.Menu-item Clickable menu item (use on button/a/label)
.Menu-item--danger Destructive action styling (red text)
.Menu-item--checkbox Checkbox item (use on label)
.Menu-item--radio Radio item (use on label)
.Menu-item--submenu Item with nested submenu indicator
.Menu-item--multiline Item with title and description

Item Content Classes

Class Description
.Menu-item-icon Leading icon in menu item
.Menu-item-text Main text label (required with shortcuts)
.Menu-item-shortcut Keyboard shortcut display (right-aligned)
.Menu-item-chevron Submenu indicator arrow
.Menu-item-content Wrapper for multiline items
.Menu-item-title Primary text in multiline item
.Menu-item-description Secondary text in multiline item

Structural Classes

Class Description
.Menu-header Section header (non-interactive)
.Menu-divider Visual separator between groups

Data Attributes

Attribute Description
disabled Disables the menu item (grayed out, not clickable)

CSS Reference

/* Menu Container */
.Menu {
  display: none;
  flex-direction: column;
  background: var(--bg);
  border: 1px solid var(--bd);
  border-radius: var(--r-m);
  padding: var(--space-1);
  box-shadow: 0 4px 12px oklch(0% 0 0 / 0.1);
  min-width: 160px;
  z-index: 100;
}

.Menu--open {
  display: flex;
}

/* Menu Item */
.Menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: none;
  background: none;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--fg);
  border-radius: var(--r-s);
  width: 100%;
  text-align: left;
  transition: background-color 0.1s;
}

.Menu-item:hover {
  background-color: var(--bg-s);
}

.Menu-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Danger Item */
.Menu-item--danger {
  color: oklch(55% 0.2 25);
}

.Menu-item--danger:hover {
  background-color: oklch(55% 0.2 25 / 0.1);
}

/* Disabled Item */
.Menu-item:disabled,
.Menu-item[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.Menu-item:disabled:hover {
  background: none;
}

/* Item Icon */
.Menu-item-icon {
  font-size: 1.1rem;
  flex-shrink: 0;
  color: var(--fg-3);
}

.Menu-item--danger .Menu-item-icon {
  color: oklch(55% 0.2 25);
}

/* Item Text & Shortcut */
.Menu-item-text {
  flex: 1;
}

.Menu-item-shortcut {
  font-size: 0.75rem;
  color: var(--fg-3);
  margin-left: auto;
}

/* Submenu */
.Menu-item-chevron {
  font-size: 0.8rem;
  color: var(--fg-3);
  margin-left: auto;
}

/* Multiline Item */
.Menu-item--multiline {
  align-items: flex-start;
  padding: var(--space-3);
}

.Menu-item-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.Menu-item-title {
  font-weight: 500;
}

.Menu-item-description {
  font-size: 0.8rem;
  color: var(--fg-3);
}

/* Checkbox / Radio Items */
.Menu-item--checkbox,
.Menu-item--radio {
  gap: var(--space-2);
}

/* Divider */
.Menu-divider {
  height: 1px;
  background: var(--bd);
  margin: var(--space-1) 0;
}

/* Header */
.Menu-header {
  padding: var(--space-2) var(--space-3);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--fg-3);
}

/* Compact Variant */
.Menu--compact .Menu-item {
  padding: var(--space-1) var(--space-2);
  font-size: 0.85rem;
}

/* Context Menu */
.Menu--context {
  position: absolute;
}

Accessibility

Keyboard Support

Key Action
Enter / Space Activates focused menu item
Escape Closes the menu
Arrow Down Moves focus to next item
Arrow Up Moves focus to previous item
Arrow Right Opens submenu (if present)
Arrow Left Closes submenu, returns to parent
Home Moves focus to first item
End Moves focus to last item

Screen Readers

<!-- Menu trigger with aria-expanded -->
<button class="Button Button--secondary" 
        aria-haspopup="menu" 
        aria-expanded="false"
        aria-controls="options-menu">
    Options
    <i class="ph ph-caret-down"></i>
</button>

<!-- Menu container with role -->
<div class="Menu" role="menu" id="options-menu" aria-label="Options">
    <button class="Menu-item" role="menuitem">Edit</button>
    <button class="Menu-item" role="menuitem">Duplicate</button>
    <div class="Menu-divider" role="separator"></div>
    <button class="Menu-item" role="menuitem">Delete</button>
</div>

<!-- Disabled item -->
<button class="Menu-item" role="menuitem" aria-disabled="true">
    Paste
</button>

<!-- Checkbox item -->
<div class="Menu-item" role="menuitemcheckbox" aria-checked="true">
    <span class="Menu-item-text">Show Hidden Files</span>
</div>

<!-- Radio group -->
<div role="group" aria-label="Sort order">
    <div class="Menu-item" role="menuitemradio" aria-checked="true">
        Ascending
    </div>
    <div class="Menu-item" role="menuitemradio" aria-checked="false">
        Descending
    </div>
</div>

<!-- Submenu trigger -->
<button class="Menu-item" role="menuitem" aria-haspopup="menu" aria-expanded="false">
    <span class="Menu-item-text">Recent</span>
    <i class="Menu-item-chevron ph ph-caret-right"></i>
</button>

Focus Management

<!-- When menu opens: -->
<!-- 1. Set aria-expanded="true" on trigger -->
<!-- 2. Move focus to first menu item -->
<!-- 3. Trap focus within menu -->

<!-- When menu closes: -->
<!-- 1. Set aria-expanded="false" on trigger -->
<!-- 2. Return focus to trigger button -->

Best Practices

Do

  • Use clear, concise labels — “Delete” not “Remove this item from the list”
  • Group related items — Use headers and dividers to organize
  • Show keyboard shortcuts — Help power users work faster
  • Use icons consistently — All items with icons, or none
  • Put destructive actions last — Separated by a divider
  • Close on selection — Menu should dismiss after an action
  • Manage focus properly — Return focus to trigger on close

Don’t

  • Nest too deeply — More than 2 levels becomes confusing
  • Use menus for navigation — Use proper nav components instead
  • Mix icons and no-icons — Be consistent within a menu
  • Forget disabled states — Explain why items are unavailable
  • Make menus too wide — Keep them scannable (max ~300px)
  • Put too many items — Consider breaking into sections or submenus
  • Ignore touch targets — Minimum 44px height on mobile