01layout-aware
Correct on every keyboard
Matches on event.key and event.code — never the deprecated keyCode. ⌘Z lands on the Z key even on a German layout. ? matches the glyph, not a position.
kb.add({
id: 'undo',
keys: 'mod+z', // the Z key, any layout
handler: undo,
});
02context
when-expressions, not flags
Gate any rule with a boolean expression over context keys. The same keystroke does different things in different contexts. Scopes are just sugar over this.
kb.add({
keys: 'mod+b',
when: "scope == 'editor' && !readOnly",
handler: toggleBold,
});
03collisions
Conflicts, caught early
Two rules fighting for one keystroke is first-class. Detect them up front; resolve them by priority and registration order, the way VS Code does.
kb.getCollisions();
// [{ keys: 'mod+k',
// rules: ['a', 'b'] }]
04core / adapter
One engine, any framework
The core talks to a KeyEventSource interface, not the DOM. Fully unit-tested in Node, reusable by React today — Vue and Svelte next.
import { createKeybindingEngine }
from '@tactile-js/core';
const kb = createKeybindingEngine();