- TanStack Router with type-safe file-based routes - Sidebar: collapsible, workspace switcher, 12 nav links, user menu - Topbar: search, quick-add, notifications, user avatar - cmdk command palette: nav + create + search + @mentions - Keyboard shortcuts: Cmd+K palette, g+t/h/p/n/c/g/s navigation, ? help - Theme: dark default, accent picker (slate/blue/green/purple/orange), persisted to localStorage - Auth: login -> /, logout -> /login, 401 redirect - Placeholder pages for all 13 nav routes (real in T6/T7) - Typed API client with useApiQuery/useApiMutation hooks
87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogDescription,
|
|
} from "@/components/ui/dialog";
|
|
|
|
const shortcutGroups = [
|
|
{
|
|
heading: "Navigation",
|
|
shortcuts: [
|
|
{ keys: "g then d", description: "Go to Dashboard" },
|
|
{ keys: "g then t", description: "Go to Tasks" },
|
|
{ keys: "g then h", description: "Go to Habits" },
|
|
{ keys: "g then p", description: "Go to Projects" },
|
|
{ keys: "g then n", description: "Go to Notes" },
|
|
{ keys: "g then c", description: "Go to Calendar" },
|
|
{ keys: "g then g", description: "Go to Graph" },
|
|
{ keys: "g then s", description: "Go to Settings" },
|
|
],
|
|
},
|
|
{
|
|
heading: "General",
|
|
shortcuts: [
|
|
{ keys: "⌘K / Ctrl+K", description: "Open command palette" },
|
|
{ keys: "/", description: "Focus search" },
|
|
{ keys: "?", description: "Show this help" },
|
|
{ keys: "Esc", description: "Close dialogs / panels" },
|
|
],
|
|
},
|
|
{
|
|
heading: "Command Palette",
|
|
shortcuts: [
|
|
{ keys: "↑↓", description: "Navigate items" },
|
|
{ keys: "Enter", description: "Select item" },
|
|
{ keys: "Esc", description: "Close palette" },
|
|
],
|
|
},
|
|
];
|
|
|
|
export function ShortcutsHelp() {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const handler = () => setOpen(true);
|
|
document.addEventListener("open-shortcuts-help", handler);
|
|
return () => document.removeEventListener("open-shortcuts-help", handler);
|
|
}, []);
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
<DialogContent className="max-w-md">
|
|
<DialogHeader>
|
|
<DialogTitle>Keyboard Shortcuts</DialogTitle>
|
|
<DialogDescription>
|
|
Use these shortcuts to navigate quickly.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="space-y-4">
|
|
{shortcutGroups.map((group) => (
|
|
<div key={group.heading}>
|
|
<h4 className="mb-2 text-sm font-semibold text-muted-foreground">
|
|
{group.heading}
|
|
</h4>
|
|
<div className="space-y-2">
|
|
{group.shortcuts.map((s) => (
|
|
<div
|
|
key={s.keys}
|
|
className="flex items-center justify-between text-sm"
|
|
>
|
|
<span className="text-muted-foreground">{s.description}</span>
|
|
<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground">
|
|
{s.keys}
|
|
</kbd>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|