"use client";
import * as React from "react";
import { ShortcutsDialog, useShortcuts, type ShortcutGroup } from "@/components/ui/keyboard-shortcuts";
const GROUPS: ShortcutGroup[] = [
{
heading: "General",
items: [
{ keys: "mod+k", label: "Open command menu" },
{ keys: "?", label: "Show keyboard shortcuts" },
{ keys: "mod+/", label: "Toggle comment" },
{ keys: "mod+,", label: "Open settings" },
],
},
{
heading: "Navigation",
items: [
{ keys: ["g h", "g d"], label: "Go home / dashboard" },
{ keys: "g i", label: "Go to inbox" },
{ keys: "mod+p", label: "Jump to file" },
{ keys: ["up", "down"], label: "Move between items" },
],
},
{
heading: "Editing",
items: [
{ keys: "mod+s", label: "Save" },
{ keys: "mod+z", label: "Undo" },
{ keys: "mod+shift+z", label: "Redo" },
{ keys: "mod+enter", label: "Submit" },
{ keys: "mod+backspace", label: "Delete line" },
],
},
];
export default function KeyboardShortcutsDemo() {
const [dark, setDark] = React.useState(false);
const shortcuts = useShortcuts("?");
React.useEffect(() => {
const t = window.setTimeout(() => shortcuts.setOpen(true), 550);
return () => window.clearTimeout(t);
}, [shortcuts.setOpen]);
return (
<div className={dark ? "dark" : ""}>
<div className="min-h-screen overflow-x-hidden bg-zinc-100 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100">
<div className="mx-auto flex min-h-screen max-w-3xl flex-col p-4 sm:p-8">
<header className="flex items-center justify-between">
<div className="flex items-center gap-2.5">
<div className="grid h-8 w-8 place-items-center rounded-[9px] border border-zinc-200/90 bg-gradient-to-b from-white to-zinc-100 text-[13px] font-semibold text-zinc-700 shadow-[0_1px_2px_rgba(0,0,0,0.05),inset_0_-1px_0_rgba(0,0,0,0.04)] dark:border-zinc-700 dark:from-zinc-800 dark:to-zinc-900 dark:text-zinc-200">
⌘
</div>
<div className="flex flex-col leading-tight">
<span className="text-[13px] font-semibold tracking-tight">Keyflow</span>
<span className="text-[11px] text-zinc-400">Untitled draft</span>
</div>
</div>
<div className="flex items-center gap-2">
<button
onClick={shortcuts.toggle}
className="group inline-flex items-center gap-2 rounded-xl border border-zinc-200 bg-white py-1.5 pl-3 pr-2 text-[12.5px] font-medium text-zinc-600 transition-colors hover:bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-300 dark:hover:bg-zinc-800/60"
>
Shortcuts
<kbd className="grid h-[18px] min-w-[18px] place-items-center rounded-[5px] border border-zinc-200/90 bg-gradient-to-b from-white to-zinc-50 px-1 text-[11px] font-medium leading-none text-zinc-500 shadow-[0_1px_0_rgba(0,0,0,0.04)] dark:border-zinc-700 dark:from-zinc-800 dark:to-zinc-800/70 dark:text-zinc-300">
?
</kbd>
</button>
<button
onClick={() => setDark((d) => !d)}
aria-label="Toggle theme"
className="h-9 w-9 shrink-0 rounded-full border border-zinc-200 text-zinc-500 transition-colors hover:bg-white dark:border-zinc-800 dark:hover:bg-zinc-900"
>
{dark ? "☀" : "☽"}
</button>
</div>
</header>
<div className="mt-6 flex-1 rounded-2xl border border-zinc-200 bg-white p-6 dark:border-zinc-800 dark:bg-zinc-900 sm:p-8">
<h1 className="text-[20px] font-semibold tracking-tight">Untitled document</h1>
<p className="mt-3 max-w-prose text-[13.5px] leading-relaxed text-zinc-500 dark:text-zinc-400">
Every fast app has a keyboard layer. Press{" "}
<kbd className="rounded border border-zinc-200 px-1.5 py-0.5 text-[11.5px] text-zinc-500 dark:border-zinc-700 dark:text-zinc-300">
?
</kbd>{" "}
to see the full map - search it, learn one, close it. This overlay is the
whole thing: bring your groups, it renders the chips and handles the rest.
</p>
<div className="mt-6 space-y-2">
{[92, 78, 85, 60].map((w, i) => (
<div
key={i}
className="h-2.5 rounded-full bg-zinc-100 dark:bg-zinc-800"
style={{ width: `${w}%` }}
/>
))}
</div>
</div>
</div>
</div>
<ShortcutsDialog
groups={GROUPS}
open={shortcuts.open}
onOpenChange={shortcuts.setOpen}
/>
</div>
);
}