Keyboard shortcuts
A modal listing every shortcut.
Built with
- Button
- Modal
- Table
- TableBody
- TableCell
- TableHeader
- TableHeaderCell
- TableRow
Approvals
6 leave requests and 2 expense claims waiting
Tip: press ? on any Northwind page to open this list.
keyboard-shortcuts.tsx
"use client";
import { LuKeyboard } from "react-icons/lu";
import {
Button,
Modal,
Table,
TableBody,
TableCell,
TableHeader,
TableHeaderCell,
TableRow,
} from "@nexera-ui/react";
const GROUPS = [
{
id: "general",
title: "General",
rows: [
{ keys: ["Ctrl", "K"], together: true, action: "Search people, teams and requests" },
{ keys: ["?"], action: "Show keyboard shortcuts" },
{ keys: ["G", "P"], action: "Go to People" },
{ keys: ["G", "A"], action: "Go to Approvals" },
],
},
{
id: "lists",
title: "Lists and tables",
rows: [
{ keys: ["J"], action: "Next row" },
{ keys: ["K"], action: "Previous row" },
{ keys: ["X"], action: "Select or clear the row" },
{ keys: ["Enter"], action: "Open the row" },
],
},
{
id: "approvals",
title: "Approvals",
rows: [
{ keys: ["A"], action: "Approve the open request" },
{ keys: ["D"], action: "Decline the open request" },
{ keys: ["C"], action: "Comment on the request" },
],
},
];
const Keys = ({ keys, together = false }: { keys: string[]; together?: boolean }) => (
<span className="flex flex-wrap items-center gap-1">
{keys.map((key, i) => (
<span key={key} className="flex items-center gap-1">
{i > 0 ? (
<span className="text-body-small text-muted">{together ? "+" : "then"}</span>
) : null}
<kbd className="rounded-sm border border-default bg-sunken px-1.5 py-0.5 font-mono text-body-small text-primary">
{key}
</kbd>
</span>
))}
</span>
);
/** Keyboard shortcuts: a modal, opened from the page header, that lists every shortcut in a real table per area. */
export default function KeyboardShortcuts() {
return (
<div className="@container bg-page px-4 py-8 @3xl:px-8">
<div className="mx-auto grid max-w-3xl gap-4">
<header className="flex flex-wrap items-end justify-between gap-3">
<div className="grid gap-1">
<h2 className="text-heading-h2 text-primary">Approvals</h2>
<p className="text-body-default text-secondary">
6 leave requests and 2 expense claims waiting
</p>
</div>
<Modal
trigger={
<Button variant="secondary" leadingIcon={<LuKeyboard />}>
Keyboard shortcuts
</Button>
}
title="Keyboard shortcuts"
subtitle="Shortcuts work anywhere except while you type in a field."
size="md"
isDismissable
primaryAction={
<Button size="md" slot="close">
Done
</Button>
}
>
<div className="grid gap-6">
{GROUPS.map((group) => (
<section key={group.id} aria-labelledby={`kbd-${group.id}`} className="grid gap-2">
<h3 id={`kbd-${group.id}`} className="text-heading-h4 text-primary">
{group.title}
</h3>
<Table
aria-labelledby={`kbd-${group.id}`}
className="rounded-md border border-default"
>
<TableHeader>
<TableHeaderCell id="action" isRowHeader label="Action" />
<TableHeaderCell id="keys" label="Keys" />
</TableHeader>
<TableBody items={group.rows.map((row) => ({ ...row, id: row.action }))}>
{(row) => (
<TableRow id={row.id}>
<TableCell>{row.action}</TableCell>
<TableCell>
<Keys keys={row.keys} together={"together" in row && row.together} />
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</section>
))}
</div>
</Modal>
</header>
<p className="rounded-lg border border-default bg-surface p-4 text-body-default text-secondary">
Tip: press{" "}
<kbd className="rounded-sm border border-default bg-sunken px-1.5 font-mono text-body-small text-primary">
?
</kbd>{" "}
on any Northwind page to open this list.
</p>
</div>
</div>
);
}
More lists, tables and records blocks
- Data tableSearch, sort, select rows and page through results.
- Bulk actionsA floating bar that acts on the selected rows.
- Filter barActive filters as removable chips above results.
- Filters drawerDetailed filters in a side panel.
- People directorySearchable list of people with presence.
- Record details drawerOpen a row to see details without leaving the list.
- Activity feedNewest first, with a 'new items' pill and paging.
- File browserFolders and files in a tree.