Skip to content

feat(hotkeys): end-user keymap customization#48

Merged
thorwhalen merged 1 commit into
mainfrom
feat/hotkeys-keymap
Jul 6, 2026
Merged

feat(hotkeys): end-user keymap customization#48
thorwhalen merged 1 commit into
mainfrom
feat/hotkeys-keymap

Conversation

@thorwhalen

Copy link
Copy Markdown
Member

What & why

The second v1.14-deferred accelerator. Lets a user (not just the developer) remap shortcuts and have the choice persist (research-10) — pure composition over the record defaults, no change to the closed CommandRecord. The zero-dependency reproducible equivalent already shipped as docs/hand-written-keymap-override.md (v1.14); this is the tested acture-hotkeys package layer.

Almost no SaaS ships user-remapping (Figma/Linear/Slack don't) — and no JS hotkey library ships a persisted rebindable keymap with conflict detection — so this is a genuine differentiator, not a reinvention.

Changes

  • bindHotkeys(registry, { keymap }) — an optional UserKeymap (sparse commandId → { replace | add | remove }) layered over each record's default keybinding at bind time. Default empty → existing callers unaffected. useHotkeys (React) forwards it and re-binds on keymap identity change, so a live remap UI takes effect.
  • Pure keymap.ts: resolveKeys (override resolution); collectBindings gained a keymap param and orders user-touched bindings first on a shared key (VS Code's "user override wins, scope respected"); detectConflicts(registry, keymap?) (definite/possible clashes).
  • Capture / display primitives: tokenFromEvent (press-to-record), isReservedCombo / RESERVED_COMBOS, formatKeybinding (⌘/Ctrl), layoutLabel (getLayoutMap, with fallback).
  • Two-layer discipline: keymap.ts is tinykeys-free; bind.ts composes it.
  • +14 tests (23 in the package; the 9 pre-existing bind tests still pass → backward-compatible). minor changeset (acture-hotkeys 1.0.1 → 1.1.0).

Left to the app (the primitives cover it)

The full remap-UI React component, preset packs, cloud sync, and the WCAG 2.1.4 "disable character-key shortcuts" toggle — documented, YAGNI-gated.

https://claude.ai/code/session_016teVFousRsWNhiiPNpG1p9

The second v1.14-deferred accelerator. Lets a USER (not just the developer)
remap shortcuts and have the choice persist (research-10) — pure composition
over the record defaults, NO change to the closed CommandRecord. The
reproducible zero-dependency equivalent already shipped as
docs/hand-written-keymap-override.md (v1.14); this is the tested package layer.

- bindHotkeys(registry, { keymap }) — an optional UserKeymap (sparse
  commandId → { replace | add | remove }) layered over each record's default
  keybinding at bind time. Default empty → existing callers unaffected.
  useHotkeys (React) forwards it and re-binds on keymap identity change (live
  remap UI).
- Pure keymap.ts: resolveKeys (override resolution); collectBindings gained a
  keymap param and orders user-touched bindings first on a shared key; and
  detectConflicts (definite/possible same-key clashes).
- Capture/display primitives: tokenFromEvent (press-to-record), isReservedCombo
  / RESERVED_COMBOS, formatKeybinding, layoutLabel (getLayoutMap w/ fallback).
- keymap.ts is tinykeys-free; bind.ts composes it (two-layer discipline).
- +14 tests (23 in the package; the 9 pre-existing bind tests still pass →
  backward-compatible). minor changeset (1.0.1 → 1.1.0).

Left to the app (primitives cover it): the full remap-UI React component,
preset packs, cloud sync, the WCAG "disable character-key shortcuts" toggle.

Claude-Session: https://claude.ai/code/session_016teVFousRsWNhiiPNpG1p9
@thorwhalen thorwhalen merged commit cfe98d3 into main Jul 6, 2026
1 check passed
@thorwhalen thorwhalen deleted the feat/hotkeys-keymap branch July 6, 2026 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant