forked from Prompt-Hash-Stellar/prompt-hash
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKeyboardShortcutsModal.tsx
More file actions
100 lines (91 loc) · 3.14 KB
/
Copy pathKeyboardShortcutsModal.tsx
File metadata and controls
100 lines (91 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { useEffect, useRef } from "react";
import { X } from "lucide-react";
interface KeyboardShortcutsModalProps {
open: boolean;
onClose: () => void;
}
const shortcuts = [
{ keys: ["/"], description: "Focus the search bar" },
{ keys: ["?"], description: "Show this shortcuts reference" },
{ keys: ["Esc"], description: "Close modal / blur active element" },
{ keys: ["Ctrl", "S"], description: "Save current prompt draft" },
];
export function KeyboardShortcutsModal({
open,
onClose,
}: KeyboardShortcutsModalProps) {
const dialogRef = useRef<HTMLDivElement>(null);
// Close on Escape
useEffect(() => {
function handleClose() {
onClose();
}
document.addEventListener("close-modal", handleClose);
return () => document.removeEventListener("close-modal", handleClose);
}, [onClose]);
// Click-outside
function handleBackdropClick(e: React.MouseEvent<HTMLDivElement>) {
if (e.target === e.currentTarget) onClose();
}
if (!open) return null;
return (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"
onClick={handleBackdropClick}
role="dialog"
aria-modal="true"
aria-label="Keyboard shortcuts"
>
<div
ref={dialogRef}
className="relative w-full max-w-md rounded-2xl border border-white/10 bg-slate-900 p-6 shadow-2xl"
>
<div className="mb-5 flex items-center justify-between">
<h2 className="text-lg font-semibold text-white">
Keyboard Shortcuts
</h2>
<button
onClick={onClose}
className="rounded-full p-1.5 text-slate-400 transition-colors hover:bg-white/10 hover:text-white"
aria-label="Close"
>
<X className="h-5 w-5" />
</button>
</div>
<table className="w-full text-sm">
<thead>
<tr className="border-b border-white/10 text-left text-xs uppercase tracking-widest text-slate-500">
<th className="pb-3 pr-4">Shortcut</th>
<th className="pb-3">Action</th>
</tr>
</thead>
<tbody>
{shortcuts.map((s, i) => (
<tr
key={i}
className="border-b border-white/5 last:border-0"
>
<td className="py-3 pr-4">
<span className="flex gap-1">
{s.keys.map((k) => (
<kbd
key={k}
className="inline-flex items-center rounded border border-white/20 bg-white/10 px-2 py-0.5 font-mono text-xs text-slate-200"
>
{k}
</kbd>
))}
</span>
</td>
<td className="py-3 text-slate-300">{s.description}</td>
</tr>
))}
</tbody>
</table>
<p className="mt-4 text-xs text-slate-500">
Press <kbd className="rounded border border-white/20 bg-white/10 px-1 font-mono text-xs">Esc</kbd> or click outside to close.
</p>
</div>
</div>
);
}