Open demo

CSS code

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-chev-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12.5 4.5 4.5L19 7.5"/></symbol>
  <symbol id="i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5.5" r="2.5"/><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="18.5" r="2.5"/><path d="m8.2 10.8 7.6-4.1M8.2 13.2l7.6 4.1"/></symbol>
  <symbol id="i-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 14a4 4 0 0 0 5.7 0l3.1-3.1a4 4 0 0 0-5.7-5.7L11.5 6.8"/><path d="M14 10a4 4 0 0 0-5.7 0l-3.1 3.1a4 4 0 0 0 5.7 5.7l1.6-1.6"/></symbol>
  <symbol id="i-undo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></symbol>
  <symbol id="i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5H14"/><path d="M9.5 16.5 5 12l4.5-4.5M5 12h10"/></symbol>
  <symbol id="i-dots" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="5.5" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="18.5" cy="12" r="1.4" fill="currentColor" stroke="none"/></symbol>
  <symbol id="i-heart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20s-7.5-4.6-7.5-10.2A4.3 4.3 0 0 1 12 7.2a4.3 4.3 0 0 1 7.5 2.6C19.5 15.4 12 20 12 20z"/></symbol>
  <symbol id="i-rocket" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 14.5 7 12l1.8-4.2C11.4 3.9 15.4 2.9 20.6 3.4c.5 5.2-.5 9.2-4.4 11.8L12 17z"/><circle cx="15" cy="9" r="1.6"/><path d="M6.5 15.5c-1.8.6-2.7 2.3-3 5 2.7-.3 4.4-1.2 5-3"/></symbol>
  <symbol id="i-terminal" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4.5" width="18" height="15" rx="2"/><path d="m7 9.5 3 2.5-3 2.5M12.5 15H17"/></symbol>
  <symbol id="i-refresh" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol>
  <symbol id="i-zap" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 3 5 13.5h6.5L11 21l8-10.5h-6.5z"/></symbol>
  <symbol id="i-queue" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6.5h11M4 11.5h11M4 16.5h7M17.5 14v6M14.5 17h6"/></symbol>
  <symbol id="i-disc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><circle cx="12" cy="12" r="2.5"/></symbol>
  <symbol id="i-mic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="3.5" width="6" height="11" rx="3"/><path d="M5.5 11.5a6.5 6.5 0 0 0 13 0M12 18v3"/></symbol>
  <symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16.5V11a6 6 0 0 1 12 0v5.5l1.5 1.5h-15z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="i-smile" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><path d="M8.5 14a4.5 4.5 0 0 0 7 0M9 9.5h.01M15 9.5h.01"/></symbol>
</svg>
<div><span class="lbl">Command menu with shortcuts</span>
<div class="stage" style="--stage-h:420px">
<div class="dk-wrap">
<div class="dk">
<button class="dk-btn" id="dk-a-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-a"><svg aria-hidden="true"><use href="#i-rocket"/></svg>Deploy<svg class="dk-chev" aria-hidden="true"><use href="#i-chev-down"/></svg></button>
<div class="dk-menu" role="menu" id="dk-a" aria-labelledby="dk-a-btn" hidden>
<div role="group" aria-labelledby="dk-a-h">
<div class="dk-head" id="dk-a-h"><b>main</b> · 3f9c2e1 · 2 min ago</div>
<button type="button" class="dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+D"><svg aria-hidden="true"><use href="#i-rocket"/></svg><span>Deploy to preview</span><kbd class="dk-kbd" aria-hidden="true">⌘D</kbd></button>
<button type="button" class="dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Shift+Meta+P"><svg aria-hidden="true"><use href="#i-zap"/></svg><span>Promote to production</span><kbd class="dk-kbd" aria-hidden="true">⇧⌘P</kbd></button>
<button type="button" class="dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+R"><svg aria-hidden="true"><use href="#i-refresh"/></svg><span>Redeploy</span><kbd class="dk-kbd" aria-hidden="true">⌘R</kbd></button>
</div>
<div class="dk-sep" role="separator"></div>
<button type="button" class="dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+L"><svg aria-hidden="true"><use href="#i-terminal"/></svg><span>View build logs</span><kbd class="dk-kbd" aria-hidden="true">⌘L</kbd></button>
<button type="button" class="dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Shift+Meta+C"><svg aria-hidden="true"><use href="#i-link"/></svg><span>Copy deployment URL</span><kbd class="dk-kbd" aria-hidden="true">⇧⌘C</kbd></button>
<div class="dk-sep" role="separator"></div>
<button type="button" class="dk-item warn" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-undo"/></svg>Roll back to v2.14.0</button>
</div>
</div></div>
</div></div>
<div><span class="lbl">Status menu with radio items</span>
<div class="stage" style="--stage-h:420px">
<div class="dk-wrap">
<div class="dk">
<button class="dk-user" id="dk-b-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-b"><span class="dk-av" aria-hidden="true">RC</span><span><b>Rui Costa</b><small class="dk-st" data-choice="dk-b" data-value="on">Online</small></span><svg aria-hidden="true"><use href="#i-chev-down"/></svg></button>
<div class="dk-menu" role="menu" id="dk-b" aria-label="Status and account" hidden>
<div role="group" aria-labelledby="dk-b-h">
<div class="dk-group" id="dk-b-h">Set status</div>
<button type="button" class="dk-item" role="menuitemradio" tabindex="-1" aria-checked="true" data-choice-text="Online" data-value="on"><span class="dk-dot" aria-hidden="true"></span><span>Online</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="dk-item" role="menuitemradio" tabindex="-1" aria-checked="false" data-choice-text="Away" data-value="away"><span class="dk-dot away" aria-hidden="true"></span><span>Away</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="dk-item" role="menuitemradio" tabindex="-1" aria-checked="false" aria-labelledby="dk-b-t3" aria-describedby="dk-b-d3" data-choice-text="Do not disturb" data-value="dnd"><span class="dk-dot dnd" aria-hidden="true"></span><span id="dk-b-t3">Do not disturb</span><span class="dk-hint" id="dk-b-d3">until 17:00</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="dk-item" role="menuitemradio" tabindex="-1" aria-checked="false" data-choice-text="Invisible" data-value="off"><span class="dk-dot off" aria-hidden="true"></span><span>Invisible</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
</div>
<div class="dk-sep" role="separator"></div>
<button type="button" class="dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-smile"/></svg>Custom status…</button>
<button type="button" class="dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-bell"/></svg>Pause notifications</button>
<div class="dk-sep" role="separator"></div>
<a href="#sign-out" class="dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-logout"/></svg>Sign out</a>
</div>
</div></div>
</div></div>
<div><span class="lbl">Glass menu over artwork</span>
<div class="stage" style="--stage-h:400px">
<div class="dk-wrap dk-card"><small>Album · 2026</small><h3>Night Drive</h3><p>Saoirse Lane · 11 songs, 38 min</p>
<div class="dk">
<button class="dk-glassbtn" id="dk-c-btn" type="button" aria-label="More options for Night Drive" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-c"><svg aria-hidden="true"><use href="#i-dots"/></svg></button>
<div class="dk-menu end glass" role="menu" id="dk-c" aria-label="More options for Night Drive" hidden>
<button type="button" class="dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-queue"/></svg>Add to queue</button>
<button type="button" class="dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-disc"/></svg>Go to album</button>
<button type="button" class="dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-mic"/></svg>Go to artist</button>
<button type="button" class="dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-share"/></svg>Share</button>
<div class="dk-sep" role="separator"></div>
<button type="button" class="dk-item" role="menuitemcheckbox" tabindex="-1" aria-checked="false"><svg aria-hidden="true"><use href="#i-heart"/></svg><span>Save to your library</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
</div>
</div></div>
</div></div>
CSS
/* Dark menus: the same menu-button markup as the light sets, with a dark palette in custom properties. */
.dk{position:relative;display:inline-block}
.dk-btn{display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 12px 0 14px;border:1px solid transparent;border-radius:10px;
  background:linear-gradient(#171a24,#171a24) padding-box,linear-gradient(135deg,#818cf8,#22d3ee) border-box;color:#f3f5fa;font:inherit;font-weight:600;cursor:pointer;
  box-shadow:0 8px 24px -10px rgba(99,102,241,.65);transition:box-shadow .2s}
.dk-btn:hover,.dk-btn[aria-expanded="true"]{box-shadow:0 0 0 3px rgba(129,140,248,.22),0 8px 28px -8px rgba(34,211,238,.5)}
.dk-btn svg{width:16px;height:16px;flex:none;transition:rotate .2s}
.dk-btn>svg:first-child{color:#a5b4fc}
.dk-btn[aria-expanded="true"] .dk-chev{rotate:180deg}
.dk-user{display:flex;align-items:center;gap:10px;height:50px;padding:0 12px 0 7px;border:1px solid var(--dk-line);border-radius:12px;background:#151821;color:var(--dk-ink);
  font:inherit;cursor:pointer;transition:background-color .15s}
.dk-user:hover,.dk-user[aria-expanded="true"]{background:#1b1f2a}
.dk-user>svg{width:16px;height:16px;margin-left:6px;color:var(--dk-muted);transition:rotate .2s}
.dk-user[aria-expanded="true"]>svg{rotate:180deg}
.dk-glassbtn{display:grid;place-items:center;width:38px;height:38px;padding:0;border:1px solid rgba(255,255,255,.22);border-radius:50%;background:rgba(10,12,18,.45);color:#fff;
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);cursor:pointer;transition:background-color .15s}
.dk-glassbtn:hover,.dk-glassbtn[aria-expanded="true"]{background:rgba(10,12,18,.7)}
.dk-glassbtn svg{width:18px;height:18px}
.dk-wrap button:not([role]):focus-visible{outline:2px solid var(--dk-focus);outline-offset:3px}

.dk-menu{position:absolute;z-index:20;top:calc(100% + 8px);left:0;min-width:256px;padding:6px;background:var(--dk-bg);border:1px solid var(--dk-line);border-radius:12px;
  box-shadow:0 24px 48px -12px rgba(0,0,0,.65),inset 0 1px 0 rgba(255,255,255,.04);animation:dk-in .15s ease-out}
.dk-menu[hidden]{display:none}
@keyframes dk-in{from{opacity:0;translate:0 -4px;scale:.98}}
.dk-item{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:0;border-radius:8px;background:none;color:var(--dk-ink);font:inherit;font-weight:500;
  line-height:1.4;text-align:left;text-decoration:none;white-space:nowrap;cursor:pointer}
.dk-item>svg{width:16px;height:16px;flex:none;color:var(--dk-muted)}
.dk-item:hover,.dk-item:focus{background:var(--dk-hover);outline:none}
.dk-item:focus-visible{outline:2px solid var(--dk-focus);outline-offset:-2px}
.dk-kbd{margin-left:auto;padding:1px 6px;border:1px solid #2e3444;border-radius:5px;background:#1a1e28;color:#b4bac8;font:500 .7rem ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.dk-hint{margin-left:auto;padding-left:18px;color:var(--dk-muted);font-size:.75rem}
.dk-sep{height:1px;margin:6px -6px;background:var(--dk-line)}

.dk-wrap{--dk-ink:#e6e9f0;--dk-muted:#9aa2b3;--dk-line:#262b38;--dk-bg:#12151d;--dk-hover:#1d212c;--dk-focus:#a5b4fc;--dk-warn:#fbbf24;--dk-danger:#f87171;font-size:.875rem}
.dk-menu.end{left:auto;right:0}
.dk-menu.glass{background:rgba(16,18,26,.74);border-color:rgba(255,255,255,.14);-webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4)}
.dk-menu.glass .dk-item:hover,.dk-menu.glass .dk-item:focus{background:rgba(255,255,255,.1)}
.dk-menu.glass .dk-item>svg{color:#c9cfdb}
.dk-menu.glass .dk-sep,.dk-menu.glass .dropdown-divider{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.14)}
.dk-head{padding:6px 10px 4px;color:#8f97a8;font:500 .72rem ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.dk-head b{color:#c7ccd8;font-weight:600}
.dk-dot{flex:none;width:10px;height:10px;margin:0 3px;border-radius:50%;background:#22c55e;box-shadow:0 0 0 3px rgba(34,197,94,.18)}
.dk-dot.away{background:#f59e0b;box-shadow:0 0 0 3px rgba(245,158,11,.18)}
.dk-dot.dnd{background:#ef4444;box-shadow:0 0 0 3px rgba(239,68,68,.2)}
.dk-dot.off{background:none;border:2px solid #8f97a8;box-shadow:none}
.dk-chk{width:16px;height:16px;margin-left:auto;flex:none;color:var(--dk-focus);visibility:hidden}
.dk-item[aria-checked="true"]>.dk-chk{visibility:visible}
.dk-item.warn,.dk-item.warn>svg{color:var(--dk-warn)}
.dk-item.warn:hover,.dk-item.warn:focus{background:rgba(251,191,36,.1)}
.dk-av{flex:none;display:grid;place-items:center;width:34px;height:34px;border-radius:10px;background:linear-gradient(135deg,#0e7490,#6d28d9);color:#fff;font-size:.75rem;font-weight:700}
.dk-user b{display:block;color:var(--dk-ink);font-weight:600;line-height:1.3;text-align:left}
.dk-st{display:flex;align-items:center;gap:6px;color:var(--dk-muted);font-size:.75rem;line-height:1.4}
.dk-st::before{content:"";width:8px;height:8px;border-radius:50%;background:#22c55e}
.dk-st[data-value="away"]::before{background:#f59e0b}
.dk-st[data-value="dnd"]::before{background:#ef4444}
.dk-st[data-value="off"]::before{background:none;box-shadow:inset 0 0 0 2px #8f97a8}
.dk-card{position:relative;display:flex;flex-direction:column;justify-content:flex-end;min-height:340px;padding:22px;border-radius:16px;color:#fff;
  background:linear-gradient(180deg,transparent 35%,rgba(8,9,14,.9)),radial-gradient(circle at 18% 22%,#f472b6,transparent 45%),radial-gradient(circle at 88% 26%,#22d3ee,transparent 40%),
  radial-gradient(circle at 62% 88%,#6366f1,transparent 50%),#1e1b4b;box-shadow:0 24px 48px -20px rgba(0,0,0,.7)}
.dk-card small{color:#d4d8e2;font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase}
.dk-card h3{margin:4px 0 2px;font-size:1.35rem;font-weight:800;letter-spacing:-.02em;line-height:1.2}
.dk-card p{margin:0;color:#dfe3ea;font-size:.85rem}
.dk-card>.dk{position:absolute;top:14px;right:14px}

@media (prefers-reduced-motion:reduce){.dk-menu{animation:none}.dk-wrap *{transition:none}}
.dk-group{padding:6px 10px 4px;color:#8f97a8;font-size:.6875rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase}
JavaScript
// Menu button (WAI-ARIA APG pattern). A trigger has aria-haspopup="menu", aria-expanded and aria-controls="<menu id>".
// Click, Enter, Space or ArrowDown opens the menu (ArrowUp opens it on the last item). Inside: ArrowUp/ArrowDown move,
// Home/End jump, typing a letter jumps to the next item that starts with it, Esc closes and returns focus to the trigger,
// Tab or a click outside closes. Choosing an item closes the menu; checkbox items stay open so you can tick several.
(() => {
  const OPEN = '[aria-haspopup="menu"][aria-expanded="true"]';
  const menuOf = t => document.getElementById(t.getAttribute('aria-controls'));
  const ownerOf = m => m && document.querySelector(`[aria-controls="${m.id}"][aria-expanded="true"]`);
  const itemsOf = m => [...m.querySelectorAll('[role^="menuitem"]')]
    .filter(i => i.closest('[role="menu"]') === m && i.getAttribute('aria-disabled') !== 'true');

  function close(t, focus) {
    const m = menuOf(t);
    m.querySelectorAll(OPEN).forEach(s => close(s));
    t.setAttribute('aria-expanded', 'false');
    m.hidden = true;
    if (focus) t.focus();
  }
  function open(t, at) {
    const level = t.closest('[role="menu"]');
    document.querySelectorAll(OPEN).forEach(o => { if (o !== t && o.closest('[role="menu"]') === level) close(o); });
    t.setAttribute('aria-expanded', 'true');
    menuOf(t).hidden = false;
    if (at !== undefined) itemsOf(menuOf(t)).at(at)?.focus();
  }
  const closeAll = target => document.querySelectorAll(OPEN).forEach(t => {
    if (!t.closest('[role="menu"]') && !t.contains(target) && !menuOf(t).contains(target)) close(t);
  });

  document.addEventListener('click', e => {
    const t = e.target.closest('[aria-haspopup="menu"][aria-controls]:not([data-context])');
    if (t) {
      if (!t.closest('[role="menu"]') && t.getAttribute('aria-expanded') === 'true') close(t);
      else open(t, e.detail === 0 ? 0 : undefined); // keyboard clicks (Enter/Space) move focus into the menu
      return;
    }
    const item = e.target.closest('[role^="menuitem"]');
    if (item && item.getAttribute('aria-disabled') !== 'true') {
      const role = item.getAttribute('role');
      if (role === 'menuitemcheckbox') { item.setAttribute('aria-checked', item.getAttribute('aria-checked') !== 'true'); return; }
      if (role === 'menuitemradio') {
        const set = item.closest('[role="group"]') || item.closest('[role="menu"]');
        set.querySelectorAll('[role="menuitemradio"]').forEach(r => r.setAttribute('aria-checked', r === item));
        // Copy the choice onto the element that shows it, e.g. the split button's label.
        document.querySelectorAll(`[data-choice="${set.closest('[role="menu"]').id}"]`).forEach(el => {
          el.textContent = item.dataset.choiceText;
          if (item.dataset.value) el.dataset.value = item.dataset.value;
        });
      }
      let t = ownerOf(item.closest('[role="menu"]'));
      while (t && t.closest('[role="menu"]')) t = ownerOf(t.closest('[role="menu"]'));
      if (t) close(t, true);
      return;
    }
    closeAll(e.target);
  });

  document.addEventListener('keydown', e => {
    const t = e.target.closest('[aria-haspopup="menu"][aria-controls]:not([data-context])');
    if (t && !t.closest('[role="menu"]')) {
      if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { e.preventDefault(); open(t, e.key === 'ArrowDown' ? 0 : -1); }
      else if (e.key === 'Escape' && t.getAttribute('aria-expanded') === 'true') close(t);
      return;
    }
    const m = e.target.closest('[role="menu"]');
    if (!m) return;
    const items = itemsOf(m), i = items.indexOf(e.target), owner = ownerOf(m);
    let next;
    switch (e.key) {
      case 'ArrowDown': next = items[(i + 1) % items.length]; break;
      case 'ArrowUp': next = items.at(i <= 0 ? -1 : i - 1); break;
      case 'Home': next = items[0]; break;
      case 'End': next = items.at(-1); break;
      case 'Escape': if (owner) { e.preventDefault(); close(owner, true); } return;
      case 'Tab': closeAll(null); return;
      case ' ': if (e.target.tagName === 'A') { e.preventDefault(); e.target.click(); } return;
      default:
        if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;
        next = [...items.slice(i + 1), ...items.slice(0, i + 1)]
          .find(x => x.textContent.trim().toLowerCase().startsWith(e.key.toLowerCase()));
    }
    e.preventDefault();
    next?.focus();
  });
})();

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS, Bootstrap 5.3.8 JS bundle

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-chev-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12.5 4.5 4.5L19 7.5"/></symbol>
  <symbol id="i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5.5" r="2.5"/><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="18.5" r="2.5"/><path d="m8.2 10.8 7.6-4.1M8.2 13.2l7.6 4.1"/></symbol>
  <symbol id="i-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 14a4 4 0 0 0 5.7 0l3.1-3.1a4 4 0 0 0-5.7-5.7L11.5 6.8"/><path d="M14 10a4 4 0 0 0-5.7 0l-3.1 3.1a4 4 0 0 0 5.7 5.7l1.6-1.6"/></symbol>
  <symbol id="i-undo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></symbol>
  <symbol id="i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5H14"/><path d="M9.5 16.5 5 12l4.5-4.5M5 12h10"/></symbol>
  <symbol id="i-dots" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="5.5" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="18.5" cy="12" r="1.4" fill="currentColor" stroke="none"/></symbol>
  <symbol id="i-heart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20s-7.5-4.6-7.5-10.2A4.3 4.3 0 0 1 12 7.2a4.3 4.3 0 0 1 7.5 2.6C19.5 15.4 12 20 12 20z"/></symbol>
  <symbol id="i-rocket" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 14.5 7 12l1.8-4.2C11.4 3.9 15.4 2.9 20.6 3.4c.5 5.2-.5 9.2-4.4 11.8L12 17z"/><circle cx="15" cy="9" r="1.6"/><path d="M6.5 15.5c-1.8.6-2.7 2.3-3 5 2.7-.3 4.4-1.2 5-3"/></symbol>
  <symbol id="i-terminal" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4.5" width="18" height="15" rx="2"/><path d="m7 9.5 3 2.5-3 2.5M12.5 15H17"/></symbol>
  <symbol id="i-refresh" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol>
  <symbol id="i-zap" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 3 5 13.5h6.5L11 21l8-10.5h-6.5z"/></symbol>
  <symbol id="i-queue" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6.5h11M4 11.5h11M4 16.5h7M17.5 14v6M14.5 17h6"/></symbol>
  <symbol id="i-disc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><circle cx="12" cy="12" r="2.5"/></symbol>
  <symbol id="i-mic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="3.5" width="6" height="11" rx="3"/><path d="M5.5 11.5a6.5 6.5 0 0 0 13 0M12 18v3"/></symbol>
  <symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16.5V11a6 6 0 0 1 12 0v5.5l1.5 1.5h-15z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="i-smile" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><path d="M8.5 14a4.5 4.5 0 0 0 7 0M9 9.5h.01M15 9.5h.01"/></symbol>
</svg>
<div><span class="lbl">Command menu with shortcuts</span>
<div class="stage" style="--stage-h:420px">
<div class="dk-wrap">
<div class="dropdown dk" data-bs-theme="dark">
<button class="btn dk-btn" id="dk-a-btn" type="button" data-bs-toggle="dropdown" data-bs-offset="0,8" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-a"><svg aria-hidden="true"><use href="#i-rocket"/></svg>Deploy<svg class="dk-chev" aria-hidden="true"><use href="#i-chev-down"/></svg></button>
<div class="dropdown-menu dk-menu" role="menu" id="dk-a" aria-labelledby="dk-a-btn">
<div role="group" aria-labelledby="dk-a-h">
<div class="dropdown-header dk-head" id="dk-a-h"><b>main</b> · 3f9c2e1 · 2 min ago</div>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+D"><svg aria-hidden="true"><use href="#i-rocket"/></svg><span>Deploy to preview</span><kbd class="dk-kbd" aria-hidden="true">⌘D</kbd></button>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Shift+Meta+P"><svg aria-hidden="true"><use href="#i-zap"/></svg><span>Promote to production</span><kbd class="dk-kbd" aria-hidden="true">⇧⌘P</kbd></button>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+R"><svg aria-hidden="true"><use href="#i-refresh"/></svg><span>Redeploy</span><kbd class="dk-kbd" aria-hidden="true">⌘R</kbd></button>
</div>
<hr class="dropdown-divider">
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+L"><svg aria-hidden="true"><use href="#i-terminal"/></svg><span>View build logs</span><kbd class="dk-kbd" aria-hidden="true">⌘L</kbd></button>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1" aria-keyshortcuts="Shift+Meta+C"><svg aria-hidden="true"><use href="#i-link"/></svg><span>Copy deployment URL</span><kbd class="dk-kbd" aria-hidden="true">⇧⌘C</kbd></button>
<hr class="dropdown-divider">
<button type="button" class="dropdown-item dk-item warn" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-undo"/></svg>Roll back to v2.14.0</button>
</div>
</div></div>
</div></div>
<div><span class="lbl">Status menu with radio items</span>
<div class="stage" style="--stage-h:420px">
<div class="dk-wrap">
<div class="dropdown dk" data-bs-theme="dark">
<button class="btn dk-user" id="dk-b-btn" type="button" data-bs-toggle="dropdown" data-bs-offset="0,8" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-b"><span class="dk-av" aria-hidden="true">RC</span><span><b>Rui Costa</b><small class="dk-st" data-choice="dk-b" data-value="on">Online</small></span><svg aria-hidden="true"><use href="#i-chev-down"/></svg></button>
<div class="dropdown-menu dk-menu" role="menu" id="dk-b" aria-label="Status and account">
<div role="group" aria-labelledby="dk-b-h">
<div class="dropdown-header dk-group" id="dk-b-h">Set status</div>
<button type="button" class="dropdown-item dk-item" role="menuitemradio" tabindex="-1" aria-checked="true" data-choice-text="Online" data-value="on"><span class="dk-dot" aria-hidden="true"></span><span>Online</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="dropdown-item dk-item" role="menuitemradio" tabindex="-1" aria-checked="false" data-choice-text="Away" data-value="away"><span class="dk-dot away" aria-hidden="true"></span><span>Away</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="dropdown-item dk-item" role="menuitemradio" tabindex="-1" aria-checked="false" aria-labelledby="dk-b-t3" aria-describedby="dk-b-d3" data-choice-text="Do not disturb" data-value="dnd"><span class="dk-dot dnd" aria-hidden="true"></span><span id="dk-b-t3">Do not disturb</span><span class="dk-hint" id="dk-b-d3">until 17:00</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="dropdown-item dk-item" role="menuitemradio" tabindex="-1" aria-checked="false" data-choice-text="Invisible" data-value="off"><span class="dk-dot off" aria-hidden="true"></span><span>Invisible</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
</div>
<hr class="dropdown-divider">
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-smile"/></svg>Custom status…</button>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-bell"/></svg>Pause notifications</button>
<hr class="dropdown-divider">
<a href="#sign-out" class="dropdown-item dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-logout"/></svg>Sign out</a>
</div>
</div></div>
</div></div>
<div><span class="lbl">Glass menu over artwork</span>
<div class="stage" style="--stage-h:400px">
<div class="dk-wrap dk-card"><small>Album · 2026</small><h3>Night Drive</h3><p>Saoirse Lane · 11 songs, 38 min</p>
<div class="dropdown dk" data-bs-theme="dark">
<button class="btn dk-glassbtn" id="dk-c-btn" type="button" data-bs-toggle="dropdown" data-bs-offset="0,8" aria-label="More options for Night Drive" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-c"><svg aria-hidden="true"><use href="#i-dots"/></svg></button>
<div class="dropdown-menu dk-menu dropdown-menu-end glass" role="menu" id="dk-c" aria-label="More options for Night Drive">
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-queue"/></svg>Add to queue</button>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-disc"/></svg>Go to album</button>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-mic"/></svg>Go to artist</button>
<button type="button" class="dropdown-item dk-item" role="menuitem" tabindex="-1"><svg aria-hidden="true"><use href="#i-share"/></svg>Share</button>
<hr class="dropdown-divider">
<button type="button" class="dropdown-item dk-item" role="menuitemcheckbox" tabindex="-1" aria-checked="false"><svg aria-hidden="true"><use href="#i-heart"/></svg><span>Save to your library</span><svg class="dk-chk" aria-hidden="true"><use href="#i-check"/></svg></button>
</div>
</div></div>
</div></div>
CSS
/* Bootstrap dropdowns with data-bs-theme="dark", tuned through --bs-dropdown-* variables. */
.dk-btn{--bs-btn-padding-x:14px;--bs-btn-padding-y:0;--bs-btn-font-size:.875rem;--bs-btn-font-weight:600;--bs-btn-color:#f3f5fa;--bs-btn-hover-color:#f3f5fa;
  --bs-btn-active-color:#f3f5fa;--bs-btn-border-width:1px;--bs-btn-border-color:transparent;--bs-btn-hover-border-color:transparent;--bs-btn-active-border-color:transparent;
  --bs-btn-border-radius:10px;display:inline-flex;align-items:center;gap:8px;height:40px;padding-right:12px;
  background:linear-gradient(#171a24,#171a24) padding-box,linear-gradient(135deg,#818cf8,#22d3ee) border-box!important;box-shadow:0 8px 24px -10px rgba(99,102,241,.65);transition:box-shadow .2s}
.dk-btn:hover,.dk-btn.show{box-shadow:0 0 0 3px rgba(129,140,248,.22),0 8px 28px -8px rgba(34,211,238,.5)}
.dk-btn svg{width:16px;height:16px;flex:none;transition:rotate .2s}
.dk-btn>svg:first-child{color:#a5b4fc}
.dk-btn.show .dk-chev{rotate:180deg}
.dk-user{--bs-btn-padding-x:7px;--bs-btn-padding-y:0;--bs-btn-font-size:.875rem;--bs-btn-color:var(--dk-ink);--bs-btn-bg:#151821;--bs-btn-border-color:var(--dk-line);
  --bs-btn-border-radius:12px;--bs-btn-hover-color:var(--dk-ink);--bs-btn-hover-bg:#1b1f2a;--bs-btn-hover-border-color:var(--dk-line);--bs-btn-active-color:var(--dk-ink);
  --bs-btn-active-bg:#1b1f2a;--bs-btn-active-border-color:var(--dk-line);display:flex;align-items:center;gap:10px;height:50px;padding-right:12px}
.dk-user>svg{width:16px;height:16px;margin-left:6px;color:var(--dk-muted);transition:rotate .2s}
.dk-user.show>svg{rotate:180deg}
.dk-glassbtn{--bs-btn-padding-x:0;--bs-btn-padding-y:0;--bs-btn-color:#fff;--bs-btn-hover-color:#fff;--bs-btn-active-color:#fff;--bs-btn-bg:rgba(10,12,18,.45);
  --bs-btn-hover-bg:rgba(10,12,18,.7);--bs-btn-active-bg:rgba(10,12,18,.7);--bs-btn-border-color:rgba(255,255,255,.22);--bs-btn-hover-border-color:rgba(255,255,255,.22);
  --bs-btn-active-border-color:rgba(255,255,255,.22);--bs-btn-border-radius:50%;display:grid;place-items:center;width:38px;height:38px;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
.dk-glassbtn svg{width:18px;height:18px}
.dk-wrap .btn:focus-visible{outline:2px solid var(--dk-focus);outline-offset:3px;box-shadow:none}

.dk-menu{--bs-dropdown-min-width:256px;--bs-dropdown-padding-x:6px;--bs-dropdown-padding-y:6px;--bs-dropdown-font-size:.875rem;--bs-dropdown-bg:var(--dk-bg);
  --bs-dropdown-color:var(--dk-ink);--bs-dropdown-border-color:var(--dk-line);--bs-dropdown-border-radius:12px;--bs-dropdown-divider-bg:var(--dk-line);
  --bs-dropdown-divider-margin-y:6px;--bs-dropdown-link-color:var(--dk-ink);--bs-dropdown-link-hover-color:var(--dk-ink);--bs-dropdown-link-hover-bg:var(--dk-hover);
  --bs-dropdown-link-active-color:var(--dk-ink);--bs-dropdown-link-active-bg:var(--dk-hover);--bs-dropdown-item-padding-x:10px;--bs-dropdown-item-padding-y:8px;
  --bs-dropdown-item-border-radius:8px;box-shadow:0 24px 48px -12px rgba(0,0,0,.65),inset 0 1px 0 rgba(255,255,255,.04)}
.dk-menu.show{animation:dk-in .15s ease-out}
@keyframes dk-in{from{opacity:0;translate:0 -4px;scale:.98}}
.dk-menu .dropdown-divider{margin-inline:-6px;opacity:1}
.dk-item{display:flex;align-items:center;gap:10px;font-weight:500;line-height:1.4}
.dk-item>svg{width:16px;height:16px;flex:none;color:var(--dk-muted)}
.dk-item:focus{outline:none}
.dk-item:focus-visible{outline:2px solid var(--dk-focus);outline-offset:-2px}
.dk-kbd{margin-left:auto;padding:1px 6px;border:1px solid #2e3444;border-radius:5px;background:#1a1e28;color:#b4bac8;font:500 .7rem ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.dk-hint{margin-left:auto;padding-left:18px;color:var(--dk-muted);font-size:.75rem}
.dk-menu .dk-head{white-space:normal}

.dk-wrap{--dk-ink:#e6e9f0;--dk-muted:#9aa2b3;--dk-line:#262b38;--dk-bg:#12151d;--dk-hover:#1d212c;--dk-focus:#a5b4fc;--dk-warn:#fbbf24;--dk-danger:#f87171;font-size:.875rem}
.dk-menu.end{left:auto;right:0}
.dk-menu.glass{background:rgba(16,18,26,.74);border-color:rgba(255,255,255,.14);-webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4)}
.dk-menu.glass .dk-item:hover,.dk-menu.glass .dk-item:focus{background:rgba(255,255,255,.1)}
.dk-menu.glass .dk-item>svg{color:#c9cfdb}
.dk-menu.glass .dk-sep,.dk-menu.glass .dropdown-divider{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.14)}
.dk-head{padding:6px 10px 4px;color:#8f97a8;font:500 .72rem ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.dk-head b{color:#c7ccd8;font-weight:600}
.dk-dot{flex:none;width:10px;height:10px;margin:0 3px;border-radius:50%;background:#22c55e;box-shadow:0 0 0 3px rgba(34,197,94,.18)}
.dk-dot.away{background:#f59e0b;box-shadow:0 0 0 3px rgba(245,158,11,.18)}
.dk-dot.dnd{background:#ef4444;box-shadow:0 0 0 3px rgba(239,68,68,.2)}
.dk-dot.off{background:none;border:2px solid #8f97a8;box-shadow:none}
.dk-chk{width:16px;height:16px;margin-left:auto;flex:none;color:var(--dk-focus);visibility:hidden}
.dk-item[aria-checked="true"]>.dk-chk{visibility:visible}
.dk-item.warn,.dk-item.warn>svg{color:var(--dk-warn)}
.dk-item.warn:hover,.dk-item.warn:focus{background:rgba(251,191,36,.1)}
.dk-av{flex:none;display:grid;place-items:center;width:34px;height:34px;border-radius:10px;background:linear-gradient(135deg,#0e7490,#6d28d9);color:#fff;font-size:.75rem;font-weight:700}
.dk-user b{display:block;color:var(--dk-ink);font-weight:600;line-height:1.3;text-align:left}
.dk-st{display:flex;align-items:center;gap:6px;color:var(--dk-muted);font-size:.75rem;line-height:1.4}
.dk-st::before{content:"";width:8px;height:8px;border-radius:50%;background:#22c55e}
.dk-st[data-value="away"]::before{background:#f59e0b}
.dk-st[data-value="dnd"]::before{background:#ef4444}
.dk-st[data-value="off"]::before{background:none;box-shadow:inset 0 0 0 2px #8f97a8}
.dk-card{position:relative;display:flex;flex-direction:column;justify-content:flex-end;min-height:340px;padding:22px;border-radius:16px;color:#fff;
  background:linear-gradient(180deg,transparent 35%,rgba(8,9,14,.9)),radial-gradient(circle at 18% 22%,#f472b6,transparent 45%),radial-gradient(circle at 88% 26%,#22d3ee,transparent 40%),
  radial-gradient(circle at 62% 88%,#6366f1,transparent 50%),#1e1b4b;box-shadow:0 24px 48px -20px rgba(0,0,0,.7)}
.dk-card small{color:#d4d8e2;font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase}
.dk-card h3{margin:4px 0 2px;font-size:1.35rem;font-weight:800;letter-spacing:-.02em;line-height:1.2}
.dk-card p{margin:0;color:#dfe3ea;font-size:.85rem}
.dk-card>.dk{position:absolute;top:14px;right:14px}

@media (prefers-reduced-motion:reduce){.dk-menu.show{animation:none}.dk-wrap *{transition:none}}
.dk-group{padding:6px 10px 4px;color:#8f97a8;font-size:.6875rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase}
JavaScript
// Radio items in a Bootstrap dropdown: Bootstrap closes the menu on click; this keeps aria-checked in step
// and copies the choice onto the element that shows it (data-choice="<menu id>").
document.addEventListener('click', e => {
  const item = e.target.closest('.dropdown-menu [role="menuitemradio"]');
  if (!item) return;
  const menu = item.closest('.dropdown-menu');
  menu.querySelectorAll('[role="menuitemradio"]').forEach(r => r.setAttribute('aria-checked', r === item));
  document.querySelectorAll(`[data-choice="${menu.id}"]`).forEach(el => {
    el.textContent = item.dataset.choiceText;
    if (item.dataset.value) el.dataset.value = item.dataset.value;
  });
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-chev-down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
  <symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12.5 4.5 4.5L19 7.5"/></symbol>
  <symbol id="i-share" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5.5" r="2.5"/><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="18.5" r="2.5"/><path d="m8.2 10.8 7.6-4.1M8.2 13.2l7.6 4.1"/></symbol>
  <symbol id="i-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 14a4 4 0 0 0 5.7 0l3.1-3.1a4 4 0 0 0-5.7-5.7L11.5 6.8"/><path d="M14 10a4 4 0 0 0-5.7 0l-3.1 3.1a4 4 0 0 0 5.7 5.7l1.6-1.6"/></symbol>
  <symbol id="i-undo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 0 11H11"/></symbol>
  <symbol id="i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5H14"/><path d="M9.5 16.5 5 12l4.5-4.5M5 12h10"/></symbol>
  <symbol id="i-dots" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="5.5" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="18.5" cy="12" r="1.4" fill="currentColor" stroke="none"/></symbol>
  <symbol id="i-heart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20s-7.5-4.6-7.5-10.2A4.3 4.3 0 0 1 12 7.2a4.3 4.3 0 0 1 7.5 2.6C19.5 15.4 12 20 12 20z"/></symbol>
  <symbol id="i-rocket" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 14.5 7 12l1.8-4.2C11.4 3.9 15.4 2.9 20.6 3.4c.5 5.2-.5 9.2-4.4 11.8L12 17z"/><circle cx="15" cy="9" r="1.6"/><path d="M6.5 15.5c-1.8.6-2.7 2.3-3 5 2.7-.3 4.4-1.2 5-3"/></symbol>
  <symbol id="i-terminal" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4.5" width="18" height="15" rx="2"/><path d="m7 9.5 3 2.5-3 2.5M12.5 15H17"/></symbol>
  <symbol id="i-refresh" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3"/><path d="M19.5 4.5v4h-4"/></symbol>
  <symbol id="i-zap" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 3 5 13.5h6.5L11 21l8-10.5h-6.5z"/></symbol>
  <symbol id="i-queue" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6.5h11M4 11.5h11M4 16.5h7M17.5 14v6M14.5 17h6"/></symbol>
  <symbol id="i-disc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><circle cx="12" cy="12" r="2.5"/></symbol>
  <symbol id="i-mic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="3.5" width="6" height="11" rx="3"/><path d="M5.5 11.5a6.5 6.5 0 0 0 13 0M12 18v3"/></symbol>
  <symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16.5V11a6 6 0 0 1 12 0v5.5l1.5 1.5h-15z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="i-smile" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><path d="M8.5 14a4.5 4.5 0 0 0 7 0M9 9.5h.01M15 9.5h.01"/></symbol>
</svg>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#9aa3b5] uppercase">Command menu with shortcuts</span>
<div class="relative min-h-[420px] rounded-[18px] border border-[#1e232e] bg-[#0f1218] bg-[radial-gradient(#1c212b_1px,transparent_1px)] bg-size-[18px_18px] p-7 max-[600px]:p-5">
<div class="relative inline-block text-[.875rem]">
<button class="group inline-flex h-10 cursor-pointer items-center gap-2 rounded-[10px] border border-transparent pr-3 pl-3.5 font-semibold text-[#f3f5fa] [background:linear-gradient(#171a24,#171a24)_padding-box,linear-gradient(135deg,#818cf8,#22d3ee)_border-box] shadow-[0_8px_24px_-10px_rgba(99,102,241,.65)] transition-shadow duration-200 hover:shadow-[0_0_0_3px_rgba(129,140,248,.22),0_8px_28px_-8px_rgba(34,211,238,.5)] aria-expanded:shadow-[0_0_0_3px_rgba(129,140,248,.22),0_8px_28px_-8px_rgba(34,211,238,.5)] focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-[#a5b4fc] motion-reduce:transition-none" id="dk-a-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-a"><svg class="size-4 flex-none text-[#a5b4fc]" aria-hidden="true"><use href="#i-rocket"/></svg>Deploy<svg class="size-4 flex-none transition-[rotate] duration-200 group-aria-expanded:rotate-180 motion-reduce:transition-none" aria-hidden="true"><use href="#i-chev-down"/></svg></button>
<div class="absolute top-[calc(100%+8px)] left-0 z-20 min-w-[256px] rounded-xl border p-1.5 shadow-[0_24px_48px_-12px_rgba(0,0,0,.65),inset_0_1px_0_rgba(255,255,255,.04)] animate-menu-in motion-reduce:animate-none border-[#262b38] bg-[#12151d]" role="menu" id="dk-a" aria-labelledby="dk-a-btn" hidden>
<div role="group" aria-labelledby="dk-a-h">
<div class="px-2.5 pt-1.5 pb-1 font-mono text-[.72rem] leading-[normal] font-medium text-[#8f97a8]" id="dk-a-h"><b class="font-semibold text-[#c7ccd8]">main</b> · 3f9c2e1 · 2 min ago</div>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+D"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-rocket"/></svg><span>Deploy to preview</span><kbd class="ml-auto rounded-[5px] border border-[#2e3444] bg-[#1a1e28] px-1.5 py-px font-mono text-[.7rem] leading-[normal] font-medium text-[#b4bac8]" aria-hidden="true">⌘D</kbd></button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1" aria-keyshortcuts="Shift+Meta+P"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-zap"/></svg><span>Promote to production</span><kbd class="ml-auto rounded-[5px] border border-[#2e3444] bg-[#1a1e28] px-1.5 py-px font-mono text-[.7rem] leading-[normal] font-medium text-[#b4bac8]" aria-hidden="true">⇧⌘P</kbd></button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+R"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-refresh"/></svg><span>Redeploy</span><kbd class="ml-auto rounded-[5px] border border-[#2e3444] bg-[#1a1e28] px-1.5 py-px font-mono text-[.7rem] leading-[normal] font-medium text-[#b4bac8]" aria-hidden="true">⌘R</kbd></button>
</div>
<div class="-mx-1.5 my-1.5 h-px bg-[#262b38]" role="separator"></div>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1" aria-keyshortcuts="Meta+L"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-terminal"/></svg><span>View build logs</span><kbd class="ml-auto rounded-[5px] border border-[#2e3444] bg-[#1a1e28] px-1.5 py-px font-mono text-[.7rem] leading-[normal] font-medium text-[#b4bac8]" aria-hidden="true">⌘L</kbd></button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1" aria-keyshortcuts="Shift+Meta+C"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-link"/></svg><span>Copy deployment URL</span><kbd class="ml-auto rounded-[5px] border border-[#2e3444] bg-[#1a1e28] px-1.5 py-px font-mono text-[.7rem] leading-[normal] font-medium text-[#b4bac8]" aria-hidden="true">⇧⌘C</kbd></button>
<div class="-mx-1.5 my-1.5 h-px bg-[#262b38]" role="separator"></div>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#fbbf24] hover:bg-[#fbbf24]/10 focus:bg-[#fbbf24]/10" role="menuitem" tabindex="-1"><svg class="size-4 flex-none" aria-hidden="true"><use href="#i-undo"/></svg>Roll back to v2.14.0</button>
</div>
</div>
</div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#9aa3b5] uppercase">Status menu with radio items</span>
<div class="relative min-h-[420px] rounded-[18px] border border-[#1e232e] bg-[#0f1218] bg-[radial-gradient(#1c212b_1px,transparent_1px)] bg-size-[18px_18px] p-7 max-[600px]:p-5">
<div class="relative inline-block text-[.875rem]">
<button class="group flex h-[50px] cursor-pointer items-center gap-2.5 rounded-xl border border-[#262b38] bg-[#151821] pr-3 pl-[7px] text-[#e6e9f0] transition-colors duration-150 hover:bg-[#1b1f2a] aria-expanded:bg-[#1b1f2a] focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-[#a5b4fc] motion-reduce:transition-none" id="dk-b-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-b"><span class="grid size-[34px] flex-none place-items-center rounded-[10px] bg-[linear-gradient(135deg,#0e7490,#6d28d9)] text-[.75rem] font-bold text-white" aria-hidden="true">RC</span><span><b class="block text-left leading-[1.3] font-semibold">Rui Costa</b><small class="flex items-center gap-1.5 text-[.75rem] leading-[1.4] text-[#9aa2b3] before:size-2 before:rounded-full before:bg-[#22c55e] before:content-[''] data-[value=away]:before:bg-[#f59e0b] data-[value=dnd]:before:bg-[#ef4444] data-[value=off]:before:bg-transparent data-[value=off]:before:shadow-[inset_0_0_0_2px_#8f97a8]" data-choice="dk-b" data-value="on">Online</small></span><svg class="ml-1.5 size-4 text-[#9aa2b3] transition-[rotate] duration-200 group-aria-expanded:rotate-180 motion-reduce:transition-none" aria-hidden="true"><use href="#i-chev-down"/></svg></button>
<div class="absolute top-[calc(100%+8px)] left-0 z-20 min-w-[256px] rounded-xl border p-1.5 shadow-[0_24px_48px_-12px_rgba(0,0,0,.65),inset_0_1px_0_rgba(255,255,255,.04)] animate-menu-in motion-reduce:animate-none border-[#262b38] bg-[#12151d]" role="menu" id="dk-b" aria-label="Status and account" hidden>
<div role="group" aria-labelledby="dk-b-h">
<div class="px-2.5 pt-1.5 pb-1 font-mono text-[.72rem] leading-[normal] font-medium text-[#8f97a8]" id="dk-b-h">Set status</div>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitemradio" tabindex="-1" aria-checked="true" data-choice-text="Online" data-value="on"><span class="mx-[3px] size-2.5 flex-none rounded-full bg-[#22c55e] shadow-[0_0_0_3px_rgba(34,197,94,.18)]" aria-hidden="true"></span><span>Online</span><svg class="invisible ml-auto size-4 flex-none text-[#a5b4fc] group-aria-checked:visible" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitemradio" tabindex="-1" aria-checked="false" data-choice-text="Away" data-value="away"><span class="mx-[3px] size-2.5 flex-none rounded-full bg-[#f59e0b] shadow-[0_0_0_3px_rgba(245,158,11,.18)]" aria-hidden="true"></span><span>Away</span><svg class="invisible ml-auto size-4 flex-none text-[#a5b4fc] group-aria-checked:visible" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitemradio" tabindex="-1" aria-checked="false" aria-labelledby="dk-b-t3" aria-describedby="dk-b-d3" data-choice-text="Do not disturb" data-value="dnd"><span class="mx-[3px] size-2.5 flex-none rounded-full bg-[#ef4444] shadow-[0_0_0_3px_rgba(239,68,68,.2)]" aria-hidden="true"></span><span id="dk-b-t3">Do not disturb</span><span class="ml-auto pl-[18px] text-[.75rem] text-[#9aa2b3]" id="dk-b-d3">until 17:00</span><svg class="invisible ml-auto size-4 flex-none text-[#a5b4fc] group-aria-checked:visible" aria-hidden="true"><use href="#i-check"/></svg></button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitemradio" tabindex="-1" aria-checked="false" data-choice-text="Invisible" data-value="off"><span class="mx-[3px] size-2.5 flex-none rounded-full border-2 border-[#8f97a8]" aria-hidden="true"></span><span>Invisible</span><svg class="invisible ml-auto size-4 flex-none text-[#a5b4fc] group-aria-checked:visible" aria-hidden="true"><use href="#i-check"/></svg></button>
</div>
<div class="-mx-1.5 my-1.5 h-px bg-[#262b38]" role="separator"></div>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-smile"/></svg>Custom status…</button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-bell"/></svg>Pause notifications</button>
<div class="-mx-1.5 my-1.5 h-px bg-[#262b38]" role="separator"></div>
<a href="#sign-out" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-[#1d212c] focus:bg-[#1d212c]" role="menuitem" tabindex="-1"><svg class="size-4 flex-none text-[#9aa2b3]" aria-hidden="true"><use href="#i-logout"/></svg>Sign out</a>
</div>
</div>
</div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#9aa3b5] uppercase">Glass menu over artwork</span>
<div class="relative min-h-[400px] rounded-[18px] border border-[#1e232e] bg-[#0f1218] bg-[radial-gradient(#1c212b_1px,transparent_1px)] bg-size-[18px_18px] p-7 max-[600px]:p-5">
<div class="relative flex min-h-[340px] flex-col justify-end rounded-2xl p-[22px] text-[.875rem] text-white shadow-[0_24px_48px_-20px_rgba(0,0,0,.7)] bg-[linear-gradient(180deg,transparent_35%,rgba(8,9,14,.9)),radial-gradient(circle_at_18%_22%,#f472b6,transparent_45%),radial-gradient(circle_at_88%_26%,#22d3ee,transparent_40%),radial-gradient(circle_at_62%_88%,#6366f1,transparent_50%),linear-gradient(#1e1b4b,#1e1b4b)]"><small class="text-[.72rem] font-bold tracking-[.1em] text-[#d4d8e2] uppercase">Album · 2026</small><h3 class="mt-1 mb-0.5 text-[1.35rem] leading-[1.2] font-extrabold tracking-[-.02em]">Night Drive</h3><p class="m-0 text-[.85rem] text-[#dfe3ea]">Saoirse Lane · 11 songs, 38 min</p><div class="absolute top-3.5 right-3.5 inline-block">
<button class="grid size-[38px] cursor-pointer place-items-center rounded-full border border-white/20 bg-[rgba(10,12,18,.45)] p-0 text-white backdrop-blur-[8px] transition-colors duration-150 hover:bg-[rgba(10,12,18,.7)] aria-expanded:bg-[rgba(10,12,18,.7)] focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-[#a5b4fc] motion-reduce:transition-none" id="dk-c-btn" type="button" aria-label="More options for Night Drive" aria-haspopup="menu" aria-expanded="false" aria-controls="dk-c"><svg class="size-[18px]" aria-hidden="true"><use href="#i-dots"/></svg></button>
<div class="absolute top-[calc(100%+8px)] left-0 z-20 min-w-[256px] rounded-xl border p-1.5 shadow-[0_24px_48px_-12px_rgba(0,0,0,.65),inset_0_1px_0_rgba(255,255,255,.04)] animate-menu-in motion-reduce:animate-none right-0 left-auto border-white/15 bg-[rgba(16,18,26,.74)] backdrop-blur-[18px] backdrop-saturate-[1.4]" role="menu" id="dk-c" aria-label="More options for Night Drive" hidden>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-white/10 focus:bg-white/10" role="menuitem" tabindex="-1"><svg class="size-4 flex-none text-[#c9cfdb]" aria-hidden="true"><use href="#i-queue"/></svg>Add to queue</button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-white/10 focus:bg-white/10" role="menuitem" tabindex="-1"><svg class="size-4 flex-none text-[#c9cfdb]" aria-hidden="true"><use href="#i-disc"/></svg>Go to album</button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-white/10 focus:bg-white/10" role="menuitem" tabindex="-1"><svg class="size-4 flex-none text-[#c9cfdb]" aria-hidden="true"><use href="#i-mic"/></svg>Go to artist</button>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-white/10 focus:bg-white/10" role="menuitem" tabindex="-1"><svg class="size-4 flex-none text-[#c9cfdb]" aria-hidden="true"><use href="#i-share"/></svg>Share</button>
<div class="-mx-1.5 my-1.5 h-px bg-white/15" role="separator"></div>
<button type="button" class="group flex w-full cursor-pointer items-center gap-2.5 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left leading-[1.4] font-medium whitespace-nowrap no-underline focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#a5b4fc] text-[#e6e9f0] hover:bg-white/10 focus:bg-white/10" role="menuitemcheckbox" tabindex="-1" aria-checked="false"><svg class="size-4 flex-none text-[#c9cfdb]" aria-hidden="true"><use href="#i-heart"/></svg><span>Save to your library</span><svg class="invisible ml-auto size-4 flex-none text-[#a5b4fc] group-aria-checked:visible" aria-hidden="true"><use href="#i-check"/></svg></button>
</div>
</div></div>
</div></div>
CSS
@theme {
  --animate-menu-in: menu-in .15s ease-out;
  @keyframes menu-in { from { opacity: 0; translate: 0 -4px; scale: .98; } }
}
JavaScript
// Menu button (WAI-ARIA APG pattern). A trigger has aria-haspopup="menu", aria-expanded and aria-controls="<menu id>".
// Click, Enter, Space or ArrowDown opens the menu (ArrowUp opens it on the last item). Inside: ArrowUp/ArrowDown move,
// Home/End jump, typing a letter jumps to the next item that starts with it, Esc closes and returns focus to the trigger,
// Tab or a click outside closes. Choosing an item closes the menu; checkbox items stay open so you can tick several.
(() => {
  const OPEN = '[aria-haspopup="menu"][aria-expanded="true"]';
  const menuOf = t => document.getElementById(t.getAttribute('aria-controls'));
  const ownerOf = m => m && document.querySelector(`[aria-controls="${m.id}"][aria-expanded="true"]`);
  const itemsOf = m => [...m.querySelectorAll('[role^="menuitem"]')]
    .filter(i => i.closest('[role="menu"]') === m && i.getAttribute('aria-disabled') !== 'true');

  function close(t, focus) {
    const m = menuOf(t);
    m.querySelectorAll(OPEN).forEach(s => close(s));
    t.setAttribute('aria-expanded', 'false');
    m.hidden = true;
    if (focus) t.focus();
  }
  function open(t, at) {
    const level = t.closest('[role="menu"]');
    document.querySelectorAll(OPEN).forEach(o => { if (o !== t && o.closest('[role="menu"]') === level) close(o); });
    t.setAttribute('aria-expanded', 'true');
    menuOf(t).hidden = false;
    if (at !== undefined) itemsOf(menuOf(t)).at(at)?.focus();
  }
  const closeAll = target => document.querySelectorAll(OPEN).forEach(t => {
    if (!t.closest('[role="menu"]') && !t.contains(target) && !menuOf(t).contains(target)) close(t);
  });

  document.addEventListener('click', e => {
    const t = e.target.closest('[aria-haspopup="menu"][aria-controls]:not([data-context])');
    if (t) {
      if (!t.closest('[role="menu"]') && t.getAttribute('aria-expanded') === 'true') close(t);
      else open(t, e.detail === 0 ? 0 : undefined); // keyboard clicks (Enter/Space) move focus into the menu
      return;
    }
    const item = e.target.closest('[role^="menuitem"]');
    if (item && item.getAttribute('aria-disabled') !== 'true') {
      const role = item.getAttribute('role');
      if (role === 'menuitemcheckbox') { item.setAttribute('aria-checked', item.getAttribute('aria-checked') !== 'true'); return; }
      if (role === 'menuitemradio') {
        const set = item.closest('[role="group"]') || item.closest('[role="menu"]');
        set.querySelectorAll('[role="menuitemradio"]').forEach(r => r.setAttribute('aria-checked', r === item));
        // Copy the choice onto the element that shows it, e.g. the split button's label.
        document.querySelectorAll(`[data-choice="${set.closest('[role="menu"]').id}"]`).forEach(el => {
          el.textContent = item.dataset.choiceText;
          if (item.dataset.value) el.dataset.value = item.dataset.value;
        });
      }
      let t = ownerOf(item.closest('[role="menu"]'));
      while (t && t.closest('[role="menu"]')) t = ownerOf(t.closest('[role="menu"]'));
      if (t) close(t, true);
      return;
    }
    closeAll(e.target);
  });

  document.addEventListener('keydown', e => {
    const t = e.target.closest('[aria-haspopup="menu"][aria-controls]:not([data-context])');
    if (t && !t.closest('[role="menu"]')) {
      if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { e.preventDefault(); open(t, e.key === 'ArrowDown' ? 0 : -1); }
      else if (e.key === 'Escape' && t.getAttribute('aria-expanded') === 'true') close(t);
      return;
    }
    const m = e.target.closest('[role="menu"]');
    if (!m) return;
    const items = itemsOf(m), i = items.indexOf(e.target), owner = ownerOf(m);
    let next;
    switch (e.key) {
      case 'ArrowDown': next = items[(i + 1) % items.length]; break;
      case 'ArrowUp': next = items.at(i <= 0 ? -1 : i - 1); break;
      case 'Home': next = items[0]; break;
      case 'End': next = items.at(-1); break;
      case 'Escape': if (owner) { e.preventDefault(); close(owner, true); } return;
      case 'Tab': closeAll(null); return;
      case ' ': if (e.target.tagName === 'A') { e.preventDefault(); e.target.click(); } return;
      default:
        if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;
        next = [...items.slice(i + 1), ...items.slice(0, i + 1)]
          .find(x => x.textContent.trim().toLowerCase().startsWith(e.key.toLowerCase()));
    }
    e.preventDefault();
    next?.focus();
  });
})();

About this set

Three dropdowns for dark interfaces. Command menu with shortcuts is a Deploy button with a gradient border and glow, whose menu starts with the branch and commit, then Deploy to preview, Promote to production and Redeploy with shortcut keys, build log and URL actions, and an amber Roll back item. Status menu with radio items is a chat profile button showing the current status; its Set status group offers Online, Away, Do not disturb until 17:00 and Invisible, and the choice updates the button’s label and dot. Glass menu over artwork is a more menu on an album card with a translucent, blurred menu for queue, album, artist, share and save. Muted text and shortcut keys are tuned to reach 4.5:1 on near-black, and the focus outline uses a light indigo that stays visible on dark and glass surfaces. Status choices are menuitemradio items whose colour dots are backed by their text. The Bootstrap version sets data-bs-theme=”dark” on each dropdown and tunes Bootstrap’s dropdown variables.

What’s included

  • Gradient-border trigger and shortcut keys as keycaps
  • Radio status items that update the trigger label and dot
  • Translucent glass menu with backdrop blur over artwork
  • Muted text at 4.5:1 or better on near-black
  • Bootstrap data-bs-theme="dark" dropdowns

Accessibility

Triggers carry aria-haspopup, aria-expanded and aria-controls, and the icon-only album button is named. Status options are menuitemradio items with aria-checked, and the status dots are decorative next to the written status. Shortcuts use aria-keyshortcuts. Focus outlines are light indigo for contrast on dark backgrounds, keyboard handling follows the WAI-ARIA menu button pattern, and animations stop under prefers-reduced-motion.

Customise it

The dark palette is the --dk-* custom properties on .dk-wrap (ink, muted, line, background, hover, focus, warning). Change the glass strength on .dk-menu.glass. In Bootstrap the same properties feed --bs-dropdown-*; in Tailwind edit the hex values in the classes.