Fork of atp.tools as a universal profile for people on the ATmosphere
at main 77 lines 2.1 kB view raw
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 };