GitHub repository

ShortcutsHelp

Registry-backed "?" keyboard-shortcuts overlay.

The GitHub/Slack/Linear-style shortcuts dialog, always in sync with the live shortcut registry: a section per group, `<Kbd>` key caps per binding, remaps shown as their effective combo, and disabled shortcuts struck through with a visible "(off)". Composes `Modal`, so the native `<dialog>` provides the focus trap, Esc-to-close, backdrop, and focus return. Its own hotkey (default `?, mod+/`) is registered through the registry under `ss:shortcuts-help` — it lists itself and can be disabled or remapped like any other shortcut.

Demo

live · storybook Open in Storybook

Demo loads from https://dssoca-storybook.vercel.app/. Run pnpm storybook for it to render locally.

Usage

svelte
<script>
  import { ShortcutsHelp, Kbd, shortcuts } from 'dssoca';

  let open = $state(false);

  shortcuts.add({
    id: 'app:save',
    label: 'Save draft',
    keys: 'mod+s',
    group: 'Editing',
    onPress: save,
  });
</script>

<!-- discovery must not be shortcut-only: give it a visible trigger -->
<button onclick={() => (open = true)}>
  Keyboard shortcuts <Kbd keys="?" />
</button>

<ShortcutsHelp bind:open />

ShortcutsHelp renders whatever the registry holds at that moment — register shortcuts with `shortcuts.add()` / the `shortcut()` attachment and the overlay needs no configuration. Because it composes Modal, the dialog semantics are native: focus trap, Esc-close, backdrop click, and focus return all come from `<dialog>`/`showModal()`. Disabled shortcuts stay visible (struck through, "(off)") so users can see what `setEnabled` turned off — WCAG 2.1.4 state must be discoverable, not silent. The default `?, mod+/` hotkey pairs GitHub's `?` with Slack's `mod+/` so discovery survives both the `characterKeys` kill switch and screen-reader browse mode; still, always provide a visible trigger (a button wired to `open`) — discovery must never be shortcut-only. An empty registry renders an EmptyState instead of a blank dialog. With `editable`, the overlay doubles as the user-facing remap/disable surface — mounting `<ShortcutsHelp editable />` is the whole WCAG 2.1.4 compliance story; pair it with the localStorage recipe from the keyboard guide (`getOverrides()` on change, `applyOverrides()` at startup) so settings survive the visit. This site mounts this component in editable mode — press `?` anywhere in the docs to see it listing the site's real bindings, remap one, and find it persisted on reload.

Guide: Making your site keyboard-friendly.

HTML

CSS only — static markup The exact markup the component renders, generated at build time. Use it with dssoca/vanilla.css — see Plain HTML & CSS.

html
<dialog class="ss-modal" aria-labelledby="shortcuts-help-s1-title">
  <div class="panel">
    <header class="head">
      <h2 class="title" id="shortcuts-help-s1-title">Keyboard shortcuts</h2>
      <button type="button" class="close" aria-label="Close">×</button>
    </header>
    <div class="body">
      <div class="ss-shortcuts-help">
        <div class="ss-empty empty compact" role="status" aria-atomic="true">
          <div class="ic glyph" aria-hidden="true">⌨</div>
          <p class="title" role="heading" aria-level="3">No shortcuts registered</p>
          <p class="msg">Shortcuts added through the dssoca registry will show up here.</p>
        </div>
      </div>
    </div>
  </div>
</dialog>

Lists the live shortcut registry — Svelte only. Shown for styling reference.

Props

PropTypeDefaultDescription
openbooleanfalseWhether the overlay is shown. Bindable — control it yourself, or let the self-registered hotkey manage it.
titlestring'Keyboard shortcuts'Dialog title; wires the dialog's accessible name via Modal's `aria-labelledby`.
hotkeystring | null'?, mod+/'Combo(s) that open the overlay, self-registered through the registry (id `ss:shortcuts-help`, group "General") — it appears in its own list and is itself disable-able/remappable. `null` registers nothing (wire your own trigger).
groupOrderstring[]—Explicit section order by group name. Unlisted groups follow in registration order; by default "General" (also the bucket for ungrouped shortcuts) comes last.
editablebooleanfalseBuilt-in WCAG 2.1.4 settings UI: every row gains an enable Switch (`setEnabled`), a Change button that records the next keydown as the new binding (`remap` — Escape cancels, reserved browser combos rejected with feedback), and a Reset once remapped (`remap(id, null)`); a footer adds the global single-key kill switch (`characterKeys`) and a Restore defaults button (`resetOverrides`). Recording suppresses all other shortcuts and every change is announced through a live region.
childrenSnippet—Extra content rendered below the shortcut list (e.g. a note about where remaps persist).
↑↓ navigate · ↵ open · esc close

Keyboard shortcuts

No shortcuts registered

Shortcuts added through the dssoca registry will show up here.

Single-key shortcuts