Nasaq
Components

HotkeyRecorder

A control that records a keyboard shortcut from the keys the user presses, reads the physical key so it works on an Arabic layout, refuses shortcuts the browser or OS keeps, warns about clashes, and a settings list of bindings with reset.

PreviewOpen ↗

Code

import { HotkeyRecorder } from "@fadymondy/nasaq/web";import { useState } from "react";export function Example() {  const [value, setValue] = useState<string | null>("Mod+K");  return <HotkeyRecorder value={value} onValueChange={setValue} requireModifier resetTo="Mod+K" label="Command palette" />;}

Keyboard & Commands · stable

Live examples and controls: HotkeyRecorder in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/hotkey-recorder.json

Click the control, press the keys, done. The result is a string such as "Mod+Shift+K" (or a sequence "G I") that you store and bind. Keys are read from event.code, so a person on an Arabic layout who presses the K key gets "K", not the Arabic letter. Shortcuts the browser (Ctrl+W) or the OS (Alt+F4, Cmd+Q) keep are refused, and clashes with other bindings are shown as you record. Escape cancels, Backspace clears.

When to use

  • A "Keyboard shortcuts" page in settings: HotkeyBindings.
  • One customisable shortcut: HotkeyRecorder.

When not to use

Import

import { HotkeyRecorder, HotkeyBindings, hotkeyMatches, hotkeyParse } from "@fadymondy/nasaq/web";

Quick start

import { HotkeyRecorder } from "@fadymondy/nasaq/web";
import { useState } from "react";

export function Example() {
  const [value, setValue] = useState<string | null>("Mod+K");
  return <HotkeyRecorder value={value} onValueChange={setValue} requireModifier resetTo="Mod+K" label="Command palette" />;
}

To run a stored shortcut, use the pure helpers: hotkeyMatches(hotkeyParse("Mod+K")![0], event, apple).

Anatomy

HotkeyRecorder      data-slot="hotkey-recorder"  (data-recording)
├─ button           shows ShortcutKeys, or the prompt while recording
├─ clear / reset    icon buttons
├─ ul               error and clash messages (role="alert" for errors)
└─ span role="status"  polite announcements
HotkeyBindings      data-slot="hotkey-bindings": groups of rows, one recorder each, Reset all

API

HotkeyRecorder

PropTypeDefaultDescription
value / defaultValuestring | nullnullThe shortcut string.
onValueChange(value: string | null) => voidnoneNew shortcut, or null when cleared.
sequencebooleanfalseAllow "G I" sequences, confirmed with Enter.
requireModifierbooleanfalseRefuse a bare key that would fire while typing.
bindings / bindingId{ id, label, shortcut }[] / stringnoneOthers, to warn about duplicates and shadowing.
allowReservedbooleanfalseAccept browser and OS shortcuts.
resetTostring | nullnoneShows Reset when the value differs.
platform"auto" | "mac" | "windows""auto"
labelstringnoneAccessible name: what the shortcut does.
labels / localeen and ar strings, overridable.

HotkeyBindings

PropTypeDefaultDescription
bindingsHotkeyBindingItem[]requiredid, label, labelAr, group, shortcut, defaultShortcut, locked.
onChange(id, shortcut) => void | { error? } | Promise<...>requiredStore the change. Return { error } to show a failure.
sequence, requireModifier, platform, title, locale, labelsrequireModifier true

Logic (no React)

hotkeyParse, hotkeyFormat, hotkeyFromEvent, hotkeyMatches, hotkeyRecordKey, hotkeyValidate, hotkeyConflicts, hotkeyReservedBy, hotkeyKeys, hotkeyLabel, hotkeyTextMatches, HOTKEY_RESERVED.

Accessibility

KeyAction
Enter, Space (idle)Starts recording.
Any chord (recording)Records it. Tab and shortcuts do not leave the control.
EscapeCancels.
BackspaceClears (or removes the last step of a sequence).
  • Blur stops recording. Results and errors are announced through a polite status region.
  • Errors use aria-invalid and aria-describedby.

RTL & i18n

Key caps are always left to right. Messages are en and ar. Recording uses the physical key, so layouts do not matter.

Styling & tokens

Border, focus and danger tokens of the form controls. Extend with className.

Do / Don't

  • Do set requireModifier for app-wide shortcuts.
  • Do store the string, not the caps.
  • Do not allow reserved shortcuts unless the app runs as a desktop app.

Lab

https://docs.nasaqui.com/?path=/docs/components-keyboard-commands-hotkey-recorder--docs

On this page