Skip to content

KeyboardShortcutsHelp

MD, under 1950B gzipped

A shortcut reference dialog inheriting the focus trap every overlay gets.

Category
Navigation
Budget
md, several states or a live subscription
Runtime deps
None

Preview

Preview language

This is the exact fixture the conformance suite renders in CI. Switch the language to see the component mirror and reformat.

Install

npx shadcn@latest add https://kata-ui-rho.vercel.app/r/keyboard-shortcuts-help.json

Copies the source into your project. Pulls in 8 primitives: dialog, use-focus-trap, cn, use-locale, locale, portal, use-hydrated, kbd.

Source

import { Dialog } from "./dialog";
import { Kbd } from "./kbd";

export interface Shortcut {
  keys: string[];
  description: string;
}

export interface KeyboardShortcutsHelpProps {
  open: boolean;
  onClose: () => void;
  shortcuts: Shortcut[];
  title?: string;
}

/**
 * A shortcut reference, built on `Dialog` so it inherits the focus trap and
 * Escape-to-close every other overlay in the library has — a "just show a
 * list of shortcuts" dialog is exactly the kind of secondary UI that skips
 * this in most apps and traps keyboard users when it does.
 */
export function KeyboardShortcutsHelp({ open, onClose, shortcuts, title = "Keyboard shortcuts" }: KeyboardShortcutsHelpProps) {
  return (
    <Dialog open={open} onClose={onClose} title={title}>
      <ul className="flex flex-col gap-2">
        {shortcuts.map((shortcut) => (
          <li key={shortcut.description} className="flex items-center justify-between gap-4 text-sm">
            <span>{shortcut.description}</span>
            <span className="flex gap-1">
              {shortcut.keys.map((key) => (
                <Kbd key={key}>{key}</Kbd>
              ))}
            </span>
          </li>
        ))}
      </ul>
    </Dialog>
  );
}

What CI checks

← All components