Features
PreviousNext

Keybindings

A type-safe keybindings system for React applications.

Installation

pnpm add '@kit/keybindings@workspace:*'

Quick Start

Define your keybindings config.

config/keybindings.config.ts
import { parseKeybindingsConfig } from '@kit/keybindings/config'; import { dashboardRoutes } from '@kit/shared/config'; export const keybindingsModel = parseKeybindingsConfig({ // Navigation 'navigation.home': { name: 'Go to Home', description: 'Navigate to home page', defaultShortcut: 'ctrl+h', context: 'global', url: dashboardRoutes.paths.dashboard.slug.index, }, 'navigation.settings': { name: 'Go to Settings', description: 'Navigate to settings page', defaultShortcut: 'ctrl+j', context: 'global', url: dashboardRoutes.paths.dashboard.slug.settings.index, }, // UI 'ui.toggleTheme': { name: 'Toggle Theme', description: 'Switch between light and dark theme', defaultShortcut: 'ctrl+shift+l', context: 'global', }, 'ui.toggleSidebar': { name: 'Toggle Sidebar', description: 'Show/hide sidebar', defaultShortcut: 'ctrl+b', context: 'global', }, });

Wrap your app with the KeybindingsProvider.

components/providers/app-provider.tsx
'use client'; import { LocalStorageKeybindingsStorage } from '@kit/keybindings/storage/local-storage'; import { KeybindingsProvider } from '@kit/keybindings/ui'; import { keybindingsModel } from '~/config/keybindings.config'; import { KeybindingHandlers } from '../keybinding-handlers'; const keybindingsStorage = new LocalStorageKeybindingsStorage(); export function AppProvider({ children }: { children: React.ReactNode }) { return ( <KeybindingsProvider model={keybindingsModel} storage={keybindingsStorage}> <KeybindingHandlers /> {children} </KeybindingsProvider> ); }

Implement the keybinding actions.

Now you have the implement the keybinding actions.

components/keybinding-handlers.tsx
'use client'; import { useKeybinding } from '@kit/keybindings/ui'; import { useTheme } from 'next-themes'; export function KeybindingsHandlers() { const { theme, setTheme } = useTheme(); useKeybinding('ui.toggleTheme', () => { const newTheme = theme === 'dark' ? 'light' : 'dark'; setTheme(newTheme); }); useKeybinding('ui.toggleSidebar', () => { const sidebarToggle = document.querySelector( '[data-sidebar-toggle], [data-sidebar="trigger"], .sidebar-toggle' ) as HTMLButtonElement; if (sidebarToggle) { sidebarToggle.click(); } }); return null; }

Congratulations! Now you can start using your keybindings.

Display Keybindings

Use the KeybindingDisplay component to display the keybindings.

app/somewhere.tsx
'use client'; import { KeybindingDisplay, KeybindingsProvider } from '@kit/keybindings/ui'; import { Muted } from '@kit/ui/text'; import { keybindingsModel } from '~/config/keybindings.config'; export default function YourApp() { return ( <KeybindingsProvider model={keybindingsModel}> <div className="flex flex-col gap-2 items-center"> <Muted> Press <span className="capitalize text-black dark:text-white"> <KeybindingDisplay actionSlug="ui.toggleTheme" /> </span> to toggle theme </Muted> <Muted> Press <span className="capitalize text-black dark:text-white"> <KeybindingDisplay actionSlug="ui.alert" /> </span> to alert </Muted> </div> </KeybindingsProvider> ); }

User customizations

Use the KeybindingsTable component to let users customize shortcuts.

app/somewhere.tsx
'use client';
 
import { keybindingsModel } from '~/config/keybindings.config';
import { KeybindingsProvider, KeybindingsTable } from '@kit/keybindings/ui';
 
export default function YourApp() {
    return (
        <KeybindingsProvider model={keybindingsModel}>
            {/* ... */}
            <KeybindingsTable />
            {/* ... */}
        </KeybindingsProvider>
    );
}
 

Typescript support

@kit/keybindings provides a type inference for the keybindings actions.

Keybindings typescript autocompletion

Keybindings typescript autocompletion

Follow this steps to enable the typescript support in a @app/your-app application :

Create a @types folder at the root of the package and create a keybindings.d.ts file inside it.

keybindings.d.ts
package.json
tsconfig.json

Copy paste the following code into the @types/keybindings.d.ts file.

types/keybindings.d.ts
import '@kit/keybindings/ui'; import { KeybindingDisplay as KeybindingDisplayBase, useKeybinding as useKeybindingBase, useShortcut as useShortcutBase, } from '@kit/keybindings/ui/without-context'; import { keybindingsModel } from '../config/keybindings.config'; declare module '@kit/keybindings/ui' { declare const useKeybinding = (...params: Parameters<typeof useKeybindingBase<typeof keybindingsModel>>) => useKeybindingBase<typeof keybindingsModel>(...params); declare const useShortcut = (...params: Parameters<typeof useShortcutBase<typeof keybindingsModel>>) => useShortcutBase<typeof keybindingsModel>(...params); declare const KeybindingDisplay = ( props: React.ComponentProps<typeof KeybindingDisplayBase<typeof keybindingsModel>> ) => KeybindingDisplayBase<typeof keybindingsModel>(props); }

Add the following typeRoots attribute to the tsconfig.json file.

tsconfig.json
{
    "extends": "@kit/tsconfig/base.json",
    "compilerOptions": {
        "typeRoots": ["./node_modules/@types", "./@types"],
        // ...
    },
}
 

API Reference

Components

  • KeybindingDisplay - Component to display shortcuts

KeybindingDisplayProps

PropTypeDefault
actionSlug*
keyof T & string
  • KeybindingsProvider - Context provider for keybindings

KeybindingsProviderProps

PropTypeDefault
model*
T
storage
KeybindingsStorage
children*
React.ReactNode
navigationUrlTransformers
((url: string) => string)[]
  • KeybindingsTable - Settings table for editing keybindings

KeybindingsTableProps

PropTypeDefault
filter
"global" | "contextual" |...
className
string
initialKeybindings
Record<string, string>
isLoading
boolean
false

Hooks

  • useKeybinding(actionId, callback, options?) - Register shortcut handler
  • useKeybindings() - Access keybindings context
  • useShortcut(actionId) - Get current shortcut for action

How is this guide?

Last updated on 10/17/2025