Skip to content
tactile

Tactile: a JavaScript keyboard shortcut library

Tactile is a keyboard-shortcut engine that takes context and keyboard layouts seriously.

Most shortcut libraries are built on the deprecated KeyboardEvent.keyCode, treat scopes as an afterthought, and leave you to discover binding conflicts at runtime. Tactile starts from a different place: a small framework-agnostic core modeled on VS Code’s keybinding system structured rules, a when-expression context system, and explicit collision resolution with thin adapters on top.

  • Layout-aware matching. Bindings match against event.key and event.code depending on what the key is — never the deprecated keyCode. ⌘Z lands on the physical Z key across layouts; ? matches the character you’d expect. See Match modes and International keyboards.
  • when expressions, not flags. Gate any rule with a boolean expression over context keys (scope == 'editor' && !readOnly). Named scopes are just sugar over context keys — one concept to learn, not two.
  • Collisions are first-class. getCollisions() tells you when two rules fight over the same keystroke; at runtime, ties resolve by priority then registration order, the same model VS Code uses.
  • Introspection built in. getKeymap() returns every binding with platform-formatted labels — help dialogs that can’t drift from what’s registered.
  • A real core/adapter split. The engine talks to a KeyEventSource interface, not the DOM directly — fully unit-tested in Node and reusable by any framework adapter.
Package What it is
@tactile-js/core The framework-agnostic engine. API reference.
@tactile-js/react React hooks — overview.
I want to… Start here
Install and write my first shortcut InstallationQuick start
Understand code vs key / Dvorak Match modesInternational keyboards
Gate shortcuts by UI state When expressions
Build a command palette or help dialog Recipes
See every API option Core APIEngine options
Try it in the browser Playground

How do I add keyboard shortcuts to a JavaScript app?

Section titled “How do I add keyboard shortcuts to a JavaScript app?”

Install @tactile-js/core, create an engine with createKeybindingEngine(), and register rules with kb.add({ id, keys, handler }). React apps can use the useShortcut hook from @tactile-js/react instead. See the Quick start.

How do I support ⌘ on Mac and Ctrl on Windows with one binding?

Section titled “How do I support ⌘ on Mac and Ctrl on Windows with one binding?”

Use the mod alias: keys: 'mod+k' resolves to ⌘K on macOS and Ctrl+K on Windows and Linux — one binding string for every platform. See Key syntax.

Why do keyboard shortcuts break on international keyboard layouts?

Section titled “Why do keyboard shortcuts break on international keyboard layouts?”

Most libraries rely on the deprecated keyCode, which maps inconsistently across layouts like QWERTZ, AZERTY, and Dvorak. Tactile matches on event.key and event.code with a hybrid strategy — ⌘Z stays on the physical Z key while symbols like ? match the character. See Match modes.

How do I stop shortcuts from firing while the user types in an input?

Section titled “How do I stop shortcuts from firing while the user types in an input?”

By default Tactile ignores key events from input, textarea, select, and contenteditable elements. To let a specific shortcut through anyway — a command palette’s mod+k, say — set enableInFormFields: true on that one rule, or replace the engine-wide ignore predicate for broader policies.

What happens when two shortcuts use the same key combination?

Section titled “What happens when two shortcuts use the same key combination?”

Tactile detects collisions at registration time via getCollisions() and resolves them at runtime by priority, then registration order — the same precedence model VS Code uses. See Collision detection.


Ready? Head to Installation.