Keyboard Shortcut Overlay

Reference sheet of shortcuts, often opened with ?.

html

<div class="kso-stage">
  <button type="button" class="kso-trigger" style="--accent:#D9C8F0">Press <kbd>?</kbd> for shortcuts</button>
  
  <div class="kso-backdrop">
    <div class="kso-panel" data-columns="two" style="--accent:#D9C8F0" role="dialog" aria-label="Keyboard shortcuts">
      <div class="kso-panel__head">
        <h3>Keyboard shortcuts</h3>
        <button type="button" class="kso-panel__close" aria-label="Close shortcuts">&times;</button>
      </div>
      <dl class="kso-panel__list">
        <div><dt>Command palette</dt><dd><kbd>Ctrl</kbd>+<kbd>K</kbd></dd></div>
        <div><dt>Search</dt><dd><kbd>/</kbd></dd></div>
        <div><dt>New item</dt><dd><kbd>N</kbd></dd></div>
        <div><dt>Save</dt><dd><kbd>Ctrl</kbd>+<kbd>S</kbd></dd></div>
        <div><dt>Toggle sidebar</dt><dd><kbd>[</kbd></dd></div>
        <div><dt>This panel</dt><dd><kbd>?</kbd></dd></div>
      </dl>
      <p class="kso-panel__hint">Press Esc or ? to close</p>
    </div>
  </div>
  
</div>
<style>
.kso-stage { position: relative; min-height: 220px; font: 16px/1.5 system-ui, sans-serif; background: #FAF7F2; border-radius: 12px; display: flex; align-items: center; justify-content: center; }
.kso-trigger { background: #fff; border: 1.5px solid #24143030; border-radius: 8px; padding: 9px 14px; font: 13.5px system-ui, sans-serif; color: #241430; cursor: pointer; }
.kso-trigger kbd { background: var(--accent); border-radius: 4px; padding: 1px 6px; font-family: inherit; }
.kso-backdrop { position: absolute; inset: 0; background: #24143066; border-radius: 12px; display: flex; align-items: center; justify-content: center; }
.kso-panel { width: 300px; max-width: 88%; background: #FAF7F2; border-radius: 12px; padding: 18px; box-shadow: 0 20px 40px rgba(36,20,48,.3); }
.kso-panel__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.kso-panel__head h3 { margin: 0; font-size: 16px; font-weight: 600; color: #241430; }
.kso-panel__close { background: transparent; border: none; font-size: 16px; line-height: 1; cursor: pointer; color: #241430; }
.kso-panel__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.kso-panel__list { margin: 0; display: grid; grid-template-columns: 1fr; gap: 8px 16px; }
.kso-panel[data-columns="two"] .kso-panel__list { grid-template-columns: 1fr 1fr; }
.kso-panel__list > div { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.kso-panel__list dt { margin: 0; font-size: 12.5px; color: #241430cc; }
.kso-panel__list dd { margin: 0; }
.kso-panel__list kbd { background: var(--accent); border-radius: 4px; padding: 1px 6px; font: 11.5px system-ui, sans-serif; }
.kso-panel__hint { margin: 14px 0 0; font-size: 11.5px; color: #24143099; text-align: center; }
</style>

tailwind

<div class="relative min-h-[220px] font-sans bg-[#FAF7F2] rounded-xl flex items-center justify-center">
  <button type="button" class="bg-white border-[1.5px] border-[#24143030] rounded-lg px-3.5 py-2 text-[13.5px] text-[#241430] cursor-pointer">
    Press <kbd class="rounded px-1.5" style="background:#D9C8F0">?</kbd> for shortcuts
  </button>
  
  <div class="absolute inset-0 bg-[#24143066] rounded-xl flex items-center justify-center">
    <div class="kso-panel-tw w-[300px] max-w-[88%] bg-[#FAF7F2] rounded-xl p-4.5 shadow-[0_20px_40px_rgba(36,20,48,.3)]" data-columns="two">
      <div class="flex items-center justify-between mb-3">
        <h3 class="m-0 text-base font-semibold text-[#241430]">Keyboard shortcuts</h3>
        <button type="button" class="bg-transparent border-0 text-base leading-none cursor-pointer text-[#241430]" aria-label="Close shortcuts">&times;</button>
      </div>
      <dl class="m-0 grid grid-cols-1 gap-x-4 gap-y-2">
        <div class="flex items-center justify-between gap-2"><dt class="m-0 text-[12.5px] text-[#241430]/80">Command palette</dt><dd class="m-0"><kbd class="rounded px-1.5 text-[11.5px]" style="background:#D9C8F0">Ctrl</kbd>+<kbd class="rounded px-1.5 text-[11.5px]" style="background:#D9C8F0">K</kbd></dd></div>
        <div class="flex items-center justify-between gap-2"><dt class="m-0 text-[12.5px] text-[#241430]/80">Search</dt><dd class="m-0"><kbd class="rounded px-1.5 text-[11.5px]" style="background:#D9C8F0">/</kbd></dd></div>
        <div class="flex items-center justify-between gap-2"><dt class="m-0 text-[12.5px] text-[#241430]/80">New item</dt><dd class="m-0"><kbd class="rounded px-1.5 text-[11.5px]" style="background:#D9C8F0">N</kbd></dd></div>
        <div class="flex items-center justify-between gap-2"><dt class="m-0 text-[12.5px] text-[#241430]/80">Toggle sidebar</dt><dd class="m-0"><kbd class="rounded px-1.5 text-[11.5px]" style="background:#D9C8F0">[</kbd></dd></div>
      </dl>
      <p class="mt-3.5 mb-0 text-[11.5px] text-[#241430]/60 text-center">Press Esc or ? to close</p>
    </div>
  </div>
  
</div>
<style>
.kso-panel-tw[data-columns="two"] dl { grid-template-columns: 1fr 1fr; }
</style>

react

import { useState } from "react";

export function KeyboardShortcutOverlay({
  title = "Keyboard shortcuts",
  hint = "Press Esc or ? to close",
  columns = "two",
  accent = "#D9C8F0",
  open: initialOpen = true,
}) {
  const [open, setOpen] = useState(initialOpen);
  const shortcuts = [
    ["Command palette", "Ctrl+K"],
    ["Search", "/"],
    ["New item", "N"],
    ["Save", "Ctrl+S"],
    ["Toggle sidebar", "["],
    ["This panel", "?"],
  ];
  return (
    <div style={{ position: "relative", minHeight: 220, fontFamily: "system-ui, sans-serif", background: "#FAF7F2", borderRadius: 12, display: "flex", alignItems: "center", justifyContent: "center" }}>
      <button type="button" onClick={() => setOpen(true)} style={{ background: "#fff", border: "1.5px solid #24143030", borderRadius: 8, padding: "9px 14px", fontSize: 13.5, color: "#241430", cursor: "pointer" }}>
        Press <kbd style={{ background: accent, borderRadius: 4, padding: "1px 6px" }}>?</kbd> for shortcuts
      </button>
      {open && (
        <div style={{ position: "absolute", inset: 0, background: "#24143066", borderRadius: 12, display: "flex", alignItems: "center", justifyContent: "center" }}>
          <div role="dialog" aria-label={title} style={{ width: 300, maxWidth: "88%", background: "#FAF7F2", borderRadius: 12, padding: 18, boxShadow: "0 20px 40px rgba(36,20,48,.3)" }}>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }}>
              <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600, color: "#241430" }}>{title}</h3>
              <button type="button" aria-label="Close shortcuts" onClick={() => setOpen(false)} style={{ background: "transparent", border: "none", fontSize: 16, lineHeight: 1, cursor: "pointer", color: "#241430" }}>&times;</button>
            </div>
            <dl style={{ margin: 0, display: "grid", gridTemplateColumns: columns === "two" ? "1fr 1fr" : "1fr", gap: "8px 16px" }}>
              {shortcuts.map(([name, key]) => (
                <div key={name} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
                  <dt style={{ margin: 0, fontSize: 12.5, color: "#241430cc" }}>{name}</dt>
                  <dd style={{ margin: 0 }}><kbd style={{ background: accent, borderRadius: 4, padding: "1px 6px", fontSize: 11.5 }}>{key}</kbd></dd>
                </div>
              ))}
            </dl>
            <p style={{ margin: "14px 0 0", fontSize: 11.5, color: "#24143099", textAlign: "center" }}>{hint}</p>
          </div>
        </div>
      )}
    </div>
  );
}