useHotkeys
useHotkeys registers keyboard shortcuts for a component and lists them in the hotkeys dialog. Global hotkeys work anywhere on the page. Local hotkeys work while focus is inside an element you choose.
Usage#
import { useHotkeys } from "@clawscale/react";const hotkeys = useMemo(() => [{ combo: "mod+s", global: true, label: "Save view", onKeyDown: saveView }], [saveView]);
const { handleKeyDown, handleKeyUp } = useHotkeys(hotkeys);The hook needs a HotkeysProvider, which ClawscaleProvider includes. Memoize the hotkeys array, or the hook binds them again on every render.
Each hotkey is either global or has a group, the heading it appears under in the dialog. Hotkeys do not fire while a text field has focus, unless they set allowInInput.
Examples#
Global hotkeys#
global: true binds the hotkey to the whole document. Press R anywhere on this page.
import { Button, Classes, KeyComboTag, useHotkeys } from "@clawscale/react";
import { useCallback, useMemo, useState } from "react";
export default function UseHotkeysGlobal() {
const [refreshedAt, setRefreshedAt] = useState<string>();
const refresh = useCallback(() => setRefreshedAt(new Date().toLocaleTimeString("en-GB")), []);
// Memoize the list, or the hook binds the hotkeys again on every render.
const hotkeys = useMemo(
() => [{ combo: "r", global: true, label: "Refresh run list", onKeyDown: refresh }],
[refresh],
);
useHotkeys(hotkeys);
return (
<>
<Button icon="refresh" text="Refresh runs" onClick={refresh} />
<KeyComboTag combo="r" />
<span className={Classes.TEXT_MUTED}>{refreshedAt ? `Refreshed at ${refreshedAt}` : "Not refreshed yet"}</span>
</>
);
}Local hotkeys#
Other hotkeys fire only for key events that reach handleKeyDown and handleKeyUp. Attach both to a focusable element.
Focus the card, then press or .
import { Card, Classes, KeyComboTag, Menu, MenuItem, useHotkeys } from "@clawscale/react";
import { useMemo, useState } from "react";
const pipelines = ["ingest-orders", "sessionize-events", "nightly-rollup", "export-finance"];
export default function UseHotkeysLocal() {
const [selected, setSelected] = useState(0);
const hotkeys = useMemo(
() => [
{
combo: "down",
group: "Pipeline list",
label: "Select next pipeline",
preventDefault: true,
onKeyDown: () => setSelected((index) => Math.min(index + 1, pipelines.length - 1)),
},
{
combo: "up",
group: "Pipeline list",
label: "Select previous pipeline",
preventDefault: true,
onKeyDown: () => setSelected((index) => Math.max(index - 1, 0)),
},
],
[],
);
const { handleKeyDown, handleKeyUp } = useHotkeys(hotkeys);
return (
<Card onKeyDown={handleKeyDown} onKeyUp={handleKeyUp} style={{ width: "100%", maxWidth: 300 }} tabIndex={0}>
<Menu>
{pipelines.map((name, index) => (
<MenuItem active={index === selected} icon="data-lineage" key={name} text={name} />
))}
</Menu>
<p className={Classes.TEXT_MUTED} style={{ margin: "8px 0 0" }}>
Focus the card, then press <KeyComboTag combo="up" minimal /> or <KeyComboTag combo="down" minimal />.
</p>
</Card>
);
}Hotkeys dialog#
Press ? to open a dialog that lists the hotkeys of this page, grouped by group. showDialogKeyCombo changes the key, and false turns it off. Hotkeys provider shows how to customize the dialog.
Key combos#
A combo is zero or more modifiers and one key, joined with +, such as shift+r or mod+k. Letters are case-insensitive. Spaces are ignored.
| Kind | Values |
|---|---|
| Modifiers | shift, alt or option, ctrl, meta or cmd, mod |
| Named keys | enter, esc, space, tab, backspace, del, home, end, pageup, pagedown, up, down, left, right, plus, minus |
mod is cmd on macOS and ctrl elsewhere.
Props interface#
interface UseHotkeysOptions@clawscale/react| Props | Description |
|---|---|
document | Document = window.documentA custom document to reference when binding global event handlers. This can be useful when using iframes in an application. |
showDialogKeyCombo | string | false = "?"The key combo which will trigger the hotkeys dialog to open. Pass false to disable the built-in trigger entirely; the dialog can still be opened programmatically via {@link HotkeysContext }. |
interface HotkeyConfig@clawscale/react| Props | Description |
|---|---|
allowInInput | boolean = falseWhether the hotkey should be triggerable when focused in a text input. |
comborequired | stringHotkey combination string (AKA "key combo"), such as "space" or "cmd+n". |
disabled | boolean = falseWhether the hotkey cannot be triggered. |
global | boolean = falseIf false, the hotkey is active only when the target is focused. If true, the hotkey can be triggered regardless of what component is focused. |
group | stringUnless the hotkey is global, you must specify a group where the hotkey will be displayed in the hotkeys dialog. This string will be displayed in a header at the start of the group of hotkeys. |
labelrequired | React.ReactNodeHuman-friendly label for the hotkey. |
onKeyDown | (e: KeyboardEvent): anykeydown event handler. |
onKeyUp | (e: KeyboardEvent): anykeyup event handler. |
preventDefault | boolean = falseWhen true, invokes event.preventDefault() before the respective onKeyDown and onKeyUp callbacks are invoked. Enabling this can simplify handler implementations. |
stopPropagation | boolean = falseWhen true, invokes event.stopPropagation() before the respective onKeyDown and onKeyUp callbacks are invoked. Enabling this can simplify handler implementations. |