Fork of atp.tools as a universal profile for people on the ATmosphere
1import * as React from "react";
2import { useKeyPress } from "@/hooks/useKeyPress";
3import { cn } from "@/lib/utils";
4
5const processSpecial = (char: string) => {
6 if (char === "cmd" || char === "meta") return "⌘";
7 if (char === "shift") return "⇧";
8 if (char === "alt") return "⌥";
9 if (char === "ctrl") return "⌃";
10 return char.toUpperCase();
11};
12
13const KbdSegment = React.forwardRef<
14 HTMLSpanElement,
15 React.HTMLAttributes<HTMLSpanElement> & { char: string }
16>(({ char, className, ...props }, ref) => {
17 const isPressed = useKeyPress(char);
18 char = processSpecial(char);
19
20 return (
21 <span
22 ref={ref}
23 className={cn(
24 isPressed ? "text-primary" : "text-muted-foreground",
25 className,
26 )}
27 {...props}
28 >
29 {char!}
30 </span>
31 );
32});
33KbdSegment.displayName = "KbdSegment";
34
35const KbdKey = React.forwardRef<
36 HTMLDivElement,
37 React.HTMLAttributes<HTMLDivElement> & {
38 keys: string[];
39 plus?: boolean;
40 }
41>(({ keys, className, plus = true, ...props }, ref) => {
42 // Track all key presses
43 const keyStates = keys.map((key) => useKeyPress(key));
44 // Check if all keys are pressed
45 const allKeysPressed = keyStates.every((state) => state === true);
46
47 return (
48 <div
49 ref={ref}
50 className={cn(
51 "inline-flex items-center justify-center rounded-md border bg-muted px-2 py-1 text-xs font-mono shadow transition-colors duration-150",
52 keys ? "gap-x-[0.062rem]" : "gap-x-1",
53 allKeysPressed && "bg-green-300/50",
54 className,
55 )}
56 {...props}
57 >
58 {keys.map((key, i) => (
59 <>
60 <span
61 className={cn(
62 "transition-colors",
63 keyStates[i] ? "text-primary" : "text-muted-foreground",
64 allKeysPressed && "text-green-400",
65 )}
66 >
67 {processSpecial(key)}
68 </span>
69 {plus && i !== keys.length - 1 && <span className="mx-1">+</span>}
70 </>
71 ))}
72 </div>
73 );
74});
75KbdKey.displayName = "KbdKey";
76
77export { KbdKey };