-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathShortcutKey.tsx
More file actions
105 lines (92 loc) · 3.78 KB
/
ShortcutKey.tsx
File metadata and controls
105 lines (92 loc) · 3.78 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
101
102
103
104
105
import { KeyboardDownIcon } from "~/assets/icons/KeyboardDownIcon";
import { KeyboardLeftIcon } from "~/assets/icons/KeyboardLeftIcon";
import { KeyboardRightIcon } from "~/assets/icons/KeyboardRightIcon";
import { KeyboardUpIcon } from "~/assets/icons/KeyboardUpIcon";
import { KeyboardWindowsIcon } from "~/assets/icons/KeyboardWindowsIcon";
import { type Modifier, type Shortcut } from "~/hooks/useShortcutKeys";
import { cn } from "~/utils/cn";
import { useOperatingSystem } from "./OperatingSystemProvider";
import { KeyboardEnterIcon } from "~/assets/icons/KeyboardEnterIcon";
const medium =
"justify-center min-w-[1.25rem] min-h-[1.25rem] text-[0.65rem] font-mono font-medium rounded-[2px] tabular-nums px-1 ml-1 -mr-0.5 flex items-center gap-x-1.5 border border-dimmed/40 text-text-dimmed group-hover:text-text-bright/80 group-hover:border-dimmed/60 transition uppercase";
export const variants = {
small:
"justify-center text-[0.6rem] font-mono font-medium min-w-[1rem] min-h-[1rem] rounded-[2px] tabular-nums px-1 ml-1 -mr-0.5 flex items-center gap-x-1 border border-text-dimmed/40 text-text-dimmed group-hover:text-text-bright/80 group-hover:border-text-dimmed/60 transition uppercase",
medium: cn(medium, "group-hover:border-charcoal-550"),
"medium/bright": cn(medium, "bg-charcoal-750 text-text-bright border-charcoal-650"),
};
export type ShortcutKeyVariant = keyof typeof variants;
type ShortcutKey = Partial<Shortcut>;
type ShortcutKeyDefinition =
| {
windows: ShortcutKey;
mac: ShortcutKey;
}
| ShortcutKey;
type ShortcutKeyProps = {
shortcut: ShortcutKeyDefinition;
variant: ShortcutKeyVariant;
className?: string;
};
export function ShortcutKey({ shortcut, variant, className }: ShortcutKeyProps) {
const { platform } = useOperatingSystem();
const isMac = platform === "mac";
let relevantShortcut = "mac" in shortcut ? (isMac ? shortcut.mac : shortcut.windows) : shortcut;
const modifiers = relevantShortcut.modifiers ?? [];
const character = relevantShortcut.key ? keyString(relevantShortcut.key, isMac, variant) : null;
return (
<span className={cn(variants[variant], className)}>
{modifiers.map((k) => (
<span key={k}>
<span>{modifierString(k, isMac, variant)}</span>
</span>
))}
{character && <span>{character}</span>}
</span>
);
}
function keyString(key: string, isMac: boolean, variant: "small" | "medium" | "medium/bright") {
key = key.toLowerCase();
const className = variant === "small" ? "w-2.5 h-4" : "w-2.5 h-4.5";
switch (key) {
case "enter":
return isMac ? (
<KeyboardEnterIcon className={className} />
) : (
<span className="capitalize">Enter</span>
);
case "esc":
return <span className="capitalize">Esc</span>;
case "del":
return <span className="capitalize">Del</span>;
case "arrowdown":
return <KeyboardDownIcon className={className} />;
case "arrowup":
return <KeyboardUpIcon className={className} />;
case "arrowleft":
return <KeyboardLeftIcon className={className} />;
case "arrowright":
return <KeyboardRightIcon className={className} />;
default:
return key;
}
}
function modifierString(
modifier: Modifier,
isMac: boolean,
variant: "small" | "medium" | "medium/bright"
): string | JSX.Element {
const className = variant === "small" ? "w-2.5 h-4" : "w-3.5 h-5";
switch (modifier) {
case "alt":
return isMac ? "⌥" : <span className="capitalize">Alt</span>;
case "ctrl":
return isMac ? "⌃" : <span className="capitalize">Ctrl</span>;
case "meta":
return isMac ? "⌘" : <KeyboardWindowsIcon className={className} />;
case "shift":
return "⇧";
case "mod":
return isMac ? "⌘" : <span className="capitalize">Ctrl</span>;
}
}