Desktop-grade keyboard interactions for modern React applications.
Overview · Installation · Quick Start · Frameworks · Documentation · Contributing
Desktop-grade keyboard ergonomics for React apps:
- Mnemonics: Native
Alt+<key>accelerators via&syntax (<button>&File</button>) with semantic underlines. - Hotkeys: Declarative element bindings (
<input hotkey="mod+k" />). - Modal Scoping: Blocks background shortcuts when dialogs, sheets, or palettes are active.
- Overlay Hints: Floating keycap badges on demand (
<KeyboundOverlay />). - Hooks API:
useMnemonicanduseHotkeyfor dynamic labels and i18n without a build step. - Tiny Footprint: ~7.9 KB gzipped runtime. React peer dependencies only. Zero runtime dependencies.
- SSR Safe: Listeners attach in client effects; Next.js, Vite, and Remix compatible.
npm install react-keyboundimport { KeyboundProvider } from 'react-keybound';
import type {} from 'react-keybound/jsx';
export function App({ children }: { children: React.ReactNode }) {
return <KeyboundProvider>{children}</KeyboundProvider>;
}With the compiler enabled:
export function Toolbar() {
return (
<nav>
{/* Alt+F triggers File, Alt+E triggers Edit */}
<button onClick={() => openMenu('file')}>&File</button>
<button onClick={() => openMenu('edit')}>&Edit</button>
{/* Mod+K (⌘K on macOS, Ctrl+K on Windows/Linux) focuses search */}
<input hotkey="mod+k" placeholder="Search (⌘K)..." />
</nav>
);
}Syntax:
&Save→ Save (Alt+S)E&xport→ Export (Alt+X)Save && &Close→ Save & Close (Alt+C,&&for literal&)
For dynamic strings or runtime translations:
import { useMnemonic, useHotkey } from 'react-keybound';
function ActionButton({ text, onAction }: { text: string; onAction: () => void }) {
const { label, triggerProps } = useMnemonic<HTMLButtonElement>(text, { onAction });
return <button {...triggerProps}>{label}</button>;
}
function GlobalSearch() {
const { triggerProps } = useHotkey<HTMLInputElement>('mod+k');
return <input {...triggerProps} placeholder="Search..." />;
}import { withKeybound } from 'react-keybound/next';
export default withKeybound(
{},
{
components: ['Button', 'Link'],
},
);import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import keybound from 'react-keybound/vite';
export default defineConfig({
plugins: [keybound(), react()],
});- Clone the repository:
git clone https://github.com/Eggwite/keybound.git cd keybound - Install dependencies:
npm ci
- Start the dev playground:
npm run dev
- Verify changes:
npm run check npm run format:check
See CONTRIBUTING.md, CODE_OF_CONDUCT.md, and AGENTS.md.