Keyboard Shortcuts¶
Implementing global and contextual keyboard shortcuts.
Problem¶
You want to add keyboard shortcuts for common actions like save, undo, or navigation.
Solution¶
Use app.keys() for global shortcuts and app.modes() for modal (contextual) keymaps.
Complete Example¶
import { ui } from "@rezi-ui/core";
import { createNodeApp } from "@rezi-ui/node";
type State = {
content: string;
saved: boolean;
mode: "insert" | "normal";
helpOpen: boolean;
};
const app = createNodeApp<State>({
initialState: { content: "", saved: true, mode: "insert", helpOpen: false },
});
app.view((state) =>
ui.column({ flex: 1, gap: 1, p: 1 }, [
ui.row({ gap: 1, justify: "between" }, [
ui.text(state.saved ? "Saved" : "Modified"),
ui.text(`Mode: ${state.mode}`, { style: { dim: true } }),
ui.text(app.pendingChord ? `Waiting: ${app.pendingChord}` : "Ready", { style: { dim: true } }),
]),
ui.input({
id: "editor",
value: state.content,
onInput: (value) => app.update((s) => ({ ...s, content: value, saved: false })),
}),
ui.row({ gap: 2 }, [
ui.row({ gap: 1 }, [ui.kbd(["Ctrl", "S"]), ui.text("Save")]),
ui.row({ gap: 1 }, [ui.kbd("Esc"), ui.text("Normal mode")]),
ui.row({ gap: 1 }, [ui.kbd("i"), ui.text("Insert mode")]),
ui.row({ gap: 1 }, [ui.kbd("?"), ui.text("Help")]),
ui.row({ gap: 1 }, [ui.kbd("q"), ui.text("Quit")]),
]),
state.helpOpen
? ui.modal({
id: "help",
title: "Shortcuts",
content: ui.keybindingHelp(app.getBindings()),
actions: [ui.button({ id: "help-close", label: "Close", onPress: () => app.update((s) => ({ ...s, helpOpen: false })) })],
onClose: () => app.update((s) => ({ ...s, helpOpen: false })),
})
: null,
])
);
// Global shortcuts
app.keys({
"ctrl+s": {
handler: (ctx) => ctx.update((s) => ({ ...s, saved: true })),
description: "Save",
},
"?": {
handler: (ctx) => ctx.update((s) => ({ ...s, helpOpen: true })),
description: "Show shortcuts",
},
"ctrl+q": {
handler: () => app.stop(),
description: "Force quit",
},
q: {
handler: (ctx) => {
if (ctx.state.mode === "normal") app.stop();
},
description: "Quit (normal mode)",
},
});
// Modal (contextual) keymaps
app.modes({
insert: {
escape: {
handler: (ctx) => ctx.update((s) => ({ ...s, mode: "normal" })),
description: "Enter normal mode",
},
},
normal: {
i: {
handler: (ctx) => ctx.update((s) => ({ ...s, mode: "insert" })),
description: "Enter insert mode",
},
},
});
app.setMode("insert");
await app.start();
Explanation¶
app.keys()registers global bindings (available in all modes).app.modes()registers per-mode bindings (Vim-style “normal/insert”).descriptionmetadata enables auto-generated help views viaapp.getBindings().app.pendingChordexposes in-progress chord prefixes for status feedback.- Use
ui.kbd(...)to display shortcuts directly in your UI.
Overlay item shortcuts¶
shortcut on dropdown and command-palette items is currently a display/filter hint.
- In dropdowns,
routeDropdownKey(...)handles navigation keys (Up,Down,Enter,Space,Escape) but does not execute arbitrary shortcut combos. - In command palette, shortcut text is displayed and participates in search matching, but shortcut combos are not auto-bound.
- Register actual key combos with
app.keys()(orapp.modes()) and call the same action handlers your overlay uses.
Related¶
- Kbd - Displaying keyboard shortcuts