Browse Components

Menu

Related actions and destinations in a compact popup.

Basic

Open related component pages. Arrow keys and typing move between options; Escape returns to the trigger.

View Code
HTML
<div>
  <button class="btn secondary" type="button" data-menu popovertarget="component-menu">
    Explore Components
    <svg
      class="icon"
      aria-hidden="true"
      focusable="false"
      xmlns="http://www.w3.org/2000/svg"
      viewbox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="1.75"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
      <path d="m6 9 6 6 6-6">
      </path>
    </svg>
  </button>
  <div
    class="menu popup-panel"
    id="component-menu"
    popover="auto"
    aria-label="Explore components"
  >
    <a href="/components/button">
      Button
    </a>
    <a href="/components/select">
      Select
    </a>
    <a href="/components/dialog">
      Dialog
    </a>
  </div>
</div>

With icons

Optional decorative icons align with text using shared menu spacing.

View Code
HTML
<div>
  <button class="btn secondary" type="button" data-menu popovertarget="component-menu">
    Explore Components
    <svg
      class="icon"
      aria-hidden="true"
      focusable="false"
      xmlns="http://www.w3.org/2000/svg"
      viewbox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="1.75"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
      <path d="m6 9 6 6 6-6">
      </path>
    </svg>
  </button>
  <div
    class="menu popup-panel"
    id="component-menu"
    popover="auto"
    aria-label="Explore components"
  >
    <a href="/components/button">
      <svg
        class="icon"
        aria-hidden="true"
        focusable="false"
        xmlns="http://www.w3.org/2000/svg"
        viewbox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="1.75"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <rect x="3" y="3" width="7" height="7" rx="1.5">
        </rect>
        <rect x="14" y="3" width="7" height="7" rx="1.5">
        </rect>
        <rect x="3" y="14" width="7" height="7" rx="1.5">
        </rect>
        <rect x="14" y="14" width="7" height="7" rx="1.5">
        </rect>
      </svg>
      <span>
        Button
      </span>
    </a>
    <a href="/components/select">
      <svg
        class="icon"
        aria-hidden="true"
        focusable="false"
        xmlns="http://www.w3.org/2000/svg"
        viewbox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="1.75"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <path d="M8 6h13M8 12h13M8 18h13M3 6h.1M3 12h.1M3 18h.1">
        </path>
      </svg>
      <span>
        Select
      </span>
    </a>
    <a href="/components/dialog">
      <svg
        class="icon"
        aria-hidden="true"
        focusable="false"
        xmlns="http://www.w3.org/2000/svg"
        viewbox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="1.75"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <path d="M4 9V5a1 1 0 0 1 1-1h4M4 4l5 5m6-5h4a1 1 0 0 1 1 1v4m0-5-5 5M4 15v4a1 1 0 0 0 1 1h4m-5 0 5-5m6 5h4a1 1 0 0 0 1-1v-4m0 5-5-5">
        </path>
      </svg>
      <span>
        Dialog
      </span>
    </a>
  </div>
</div>

Groups and disabled items

Labels and separators organize destinations. Unavailable actions are skipped by keyboard navigation.

View Code
HTML
<div>
  <button class="btn secondary" type="button" data-menu popovertarget="component-menu">
    Explore Components
    <svg
      class="icon"
      aria-hidden="true"
      focusable="false"
      xmlns="http://www.w3.org/2000/svg"
      viewbox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="1.75"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
      <path d="m6 9 6 6 6-6">
      </path>
    </svg>
  </button>
  <div
    class="menu popup-panel"
    id="component-menu"
    popover="auto"
    aria-label="Explore components"
  >
    <span class="menu-label">
      Form controls
    </span>
    <a href="/components/button">
      <svg
        class="icon"
        aria-hidden="true"
        focusable="false"
        xmlns="http://www.w3.org/2000/svg"
        viewbox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="1.75"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <rect x="3" y="3" width="7" height="7" rx="1.5">
        </rect>
        <rect x="14" y="3" width="7" height="7" rx="1.5">
        </rect>
        <rect x="3" y="14" width="7" height="7" rx="1.5">
        </rect>
        <rect x="14" y="14" width="7" height="7" rx="1.5">
        </rect>
      </svg>
      <span>
        Button
      </span>
    </a>
    <a href="/components/select">
      <svg
        class="icon"
        aria-hidden="true"
        focusable="false"
        xmlns="http://www.w3.org/2000/svg"
        viewbox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="1.75"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <path d="M8 6h13M8 12h13M8 18h13M3 6h.1M3 12h.1M3 18h.1">
        </path>
      </svg>
      <span>
        Select
      </span>
    </a>
    <hr role="separator">
    <span class="menu-label">
      Overlays
    </span>
    <a href="/components/dialog">
      <svg
        class="icon"
        aria-hidden="true"
        focusable="false"
        xmlns="http://www.w3.org/2000/svg"
        viewbox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="1.75"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <path d="M4 9V5a1 1 0 0 1 1-1h4M4 4l5 5m6-5h4a1 1 0 0 1 1 1v4m0-5-5 5M4 15v4a1 1 0 0 0 1 1h4m-5 0 5-5m6 5h4a1 1 0 0 0 1-1v-4m0 5-5-5">
        </path>
      </svg>
      <span>
        Dialog
      </span>
    </a>
    <button type="button" disabled>
      Coming Soon
    </button>
  </div>
</div>

Placement

Prefer opening above and align the starting edge. The popup flips when space is limited.

View Code
HTML
<div>
  <button
    class="btn secondary"
    type="button"
    data-menu
    data-menu-side="top"
    data-menu-align="start"
    popovertarget="component-menu"
  >
    Explore Components
    <svg
      class="icon"
      aria-hidden="true"
      focusable="false"
      xmlns="http://www.w3.org/2000/svg"
      viewbox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="1.75"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
      <path d="m6 9 6 6 6-6">
      </path>
    </svg>
  </button>
  <div
    class="menu popup-panel"
    id="component-menu"
    popover="auto"
    aria-label="Explore components"
  >
    <a href="/components/button">
      Button
    </a>
    <a href="/components/select">
      Select
    </a>
    <a href="/components/dialog">
      Dialog
    </a>
  </div>
</div>

Right to left

Logical alignment follows the Hebrew reading direction.

View Code
HTML
<div>
  <button
    class="btn secondary"
    type="button"
    data-menu
    dir="rtl"
    lang="he"
    popovertarget="component-menu"
  >
    רכיבים
    <svg
      class="icon"
      aria-hidden="true"
      focusable="false"
      xmlns="http://www.w3.org/2000/svg"
      viewbox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="1.75"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
      <path d="m6 9 6 6 6-6">
      </path>
    </svg>
  </button>
  <div
    class="menu popup-panel"
    dir="rtl"
    lang="he"
    id="component-menu"
    popover="auto"
    aria-label="רכיבים"
  >
    <a href="/components/button">
      כפתור
    </a>
    <button type="button" data-submenu data-menu-back="חזרה" popovertarget="form-menu">
      שדות טופס
    </button>
    <div
      class="menu popup-panel"
      dir="rtl"
      lang="he"
      popover="auto"
      id="form-menu"
      aria-label="Form controls"
    >
      <a href="/components/input">
        קלט
      </a>
      <a href="/components/select">
        בחירה
      </a>
      <a href="/components/number">
        מספר
      </a>
      <button type="button" disabled>
        בקרוב
      </button>
    </div>
    <a href="/components/dialog">
      חלון
    </a>
  </div>
</div>

Installation

Download these files into the matching paths in your project, or use Create to assemble a kit. Include each dependency once. Do not also load app.css.

Add to your page
<link rel="stylesheet" href="/library/assets/base.css">
<link rel="stylesheet" href="/library/assets/popup.css">
<link rel="stylesheet" href="/library/assets/button.css">
<link rel="stylesheet" href="/library/assets/menu.css">
<script defer src="/library/assets/popup.js"></script>
<script defer src="/library/assets/menu.js"></script>

13,049 bytes CSS including base · 10,864 bytes runtime JavaScript

Usage

Actions and links

Use real links for destinations and buttons for actions. Optional leading icons must be aria-hidden. Separate action sections with hr and label them with menu-label.

Keyboard and lifecycle

Arrow keys, Home/End and typeahead navigate enabled items. Escape returns focus; Tab exits. Use layoutMenu.refresh(root) after mounting or destroy(trigger) before removal.

Submenus

Nest a menu with popover=auto inside its parent menu and target it with a button[data-submenu]. Forward and Back arrow keys follow reading direction. Escape returns one level; leaf actions close the full menu. A compact Back row appears when there is insufficient side space; localize it with data-menu-back on the trigger. Keep nesting shallow.

Shared popup

Load popup.css and popup.js before Menu. The same positioning foundation supports Select, Autocomplete, Breadcrumbs, pickers, media panels and Tooltips. Each retains its own semantics.

Building with AI? The AI Manifest has these notes and the full contract. See the AI Guide.