Key table
StableKeyboard shortcuts as a two-column table: key caps on the left, what they do on the right.
Each row draws its keys with KeyCombo, so “mod+k” becomes ⌘ K on a Mac and Ctrl K elsewhere, and a then step shows two-key sequences. The kit pages use it to list every tool’s shortcuts.
Updated View source
Shortcuts
import { KeyTable } from '@rchursin/product/shell/layout'
/** A few of the Tasks tool's real shortcuts. "mod" shows as ⌘ on Apple keyboards and Ctrl elsewhere. */const rows = [ { keys: 'j', action: 'Next task' }, { keys: 'k', action: 'Previous task' }, { keys: 'enter', action: 'Open the task' }, { keys: '/', action: 'Search' }, { keys: 'c', action: 'Create a task' }, { keys: 'mod+b', action: 'Switch between list and board' }, { keys: 'mod+z', action: 'Undo the last change' },]
export default function KeyTableShortcuts() { return <KeyTable caption="In the task list" rows={rows} className="w-full max-w-lg" />}Usage
import { KeyTable } from '@rchursin/product/shell/layout'<KeyTable caption="In the task list" rows={[{ keys: 'c', action: 'Create a task' }]} />Examples
A two-step key
then adds a second step: Enter, then Down.
import { KeyTable } from '@rchursin/product/shell/layout'
/** `then` adds a second step: press Enter, then Down. These are the Reminders list's keys. */const rows = [ { keys: 'enter', action: 'Save the reminder with the date it understood' }, { keys: 'esc', action: 'Clear the field' }, { keys: 'space', action: 'Check off (on its checkbox)' }, { keys: 'enter', then: 'down', action: 'Snooze menu: open, then pick a time' },]
export default function KeyTableSequence() { return <KeyTable caption="In Reminders" rows={rows} className="w-full max-w-lg" />}API
KeyTable props
| Prop | Type | Default | Description |
|---|---|---|---|
rowsrequired | { keys: string; then?: string; action: string }[] | – | One row per shortcut. keys uses KeyCombo’s syntax (mod, shift, alt, enter, esc, arrows, letters joined with “+”); then is an optional second step. |
caption | string | – | A short title shown above the rows; it is the table’s <caption>. |
className | string | – | Extra classes on the card around the table. |
Accessibility
- It is a real <table> with a <caption>, and the keys cell is a row header (<th scope="row">), so each action is read with its keys.
- Keys render as <kbd> elements. Pages render “Ctrl” first and switch to ⌘ after loading on Apple devices, so prerendered HTML never mismatches.
Guidelines
Do
- Say where the keys work in the caption (“In the task list”).
- Start each action with a verb or a noun people know from the screen.
Don’t
- Don’t list keys the tool doesn’t actually bind.
- Don’t put two rows with the same keys and action; they share a React key.
In use
Related
- Key capsKeyboard keys cut from the same metal as the buttons, and shortcuts written as key caps.
- useHotkeysSingle-key and modifier shortcuts, Linear style, that wait while you type and can be scoped to one part of the page.
- Rules listA numbered grid of short principles (01, 02, 03), each a title and one or two lines.
Source
The component’s own files, exactly as they run on this site.
/** * Layout pieces for the kit pages: an intro, numbered sections, specimens (one component on a * card with a caption), a keyboard table and a short list of rules. * They share the site's finishing layer: arrivals (lux-reveal), hairlines, grain, the halo. */import type { ReactNode } from "react"import { cx } from "../../components/cx"import { useLuxe } from "../../components/motion"import { delay } from "../../home/ui"import { KeyCombo } from "../ui/button"
export function KitPage({ children, className }: { children: ReactNode; className?: string }) { const root = useLuxe<HTMLDivElement>() return ( <div ref={root} className={cx("bg-surface text-fg antialiased", className)}> {children} </div> )}