@@ -2,6 +2,8 @@ import { useSearchParams } from "react-router";
22
33import { Input } from "@/ui/input" ;
44import { searchParamKey } from "@/data/searchParams" ;
5+ import { useEffect , useRef , useState , type ChangeEvent } from "react" ;
6+ import { CommandIcon } from "lucide-react" ;
57
68interface iSearchProps {
79 className ?: string ;
@@ -11,8 +13,23 @@ interface iSearchProps {
1113const Search = ( props : iSearchProps ) => {
1214 const [ searchParams , setSearchParams ] = useSearchParams ( ) ;
1315 const search = searchParams . get ( searchParamKey ) ?? "" ;
16+ const [ isFocused , setIsFocused ] = useState < boolean > ( false ) ;
17+ const inputRef = useRef < HTMLInputElement > ( null ) ;
1418
15- const handleChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
19+ useEffect ( ( ) => {
20+ const down = ( e : KeyboardEvent ) => {
21+ if ( e . key === "k" && ( e . metaKey || e . ctrlKey ) ) {
22+ e . preventDefault ( ) ;
23+ if ( inputRef . current ) {
24+ inputRef . current . focus ( ) ;
25+ }
26+ }
27+ } ;
28+ document . addEventListener ( "keydown" , down ) ;
29+ return ( ) => document . removeEventListener ( "keydown" , down ) ;
30+ } , [ ] ) ;
31+
32+ const handleChange = ( e : ChangeEvent < HTMLInputElement > ) => {
1633 const newSearchParams = new URLSearchParams ( searchParams ) ;
1734 if ( ! e . target . value ) {
1835 newSearchParams . delete ( searchParamKey ) ;
@@ -23,15 +40,26 @@ const Search = (props: iSearchProps) => {
2340 } ;
2441
2542 return (
26- < Input
27- className = { props . className }
28- type = "search"
29- name = { searchParamKey }
30- placeholder = { props . placeholder }
31- defaultValue = { search }
32- autoComplete = "off"
33- onChange = { ( e ) => handleChange ( e ) }
34- />
43+ < div className = "relative" >
44+ < Input
45+ ref = { inputRef }
46+ className = { props . className }
47+ type = "search"
48+ name = { searchParamKey }
49+ placeholder = { props . placeholder }
50+ defaultValue = { search }
51+ autoComplete = "off"
52+ onChange = { ( e ) => handleChange ( e ) }
53+ onFocus = { ( ) => setIsFocused ( true ) }
54+ onBlur = { ( ) => setIsFocused ( false ) }
55+ />
56+ { ! isFocused && ! search && (
57+ < kbd className = "pointer-events-none absolute right-2 top-1/2 flex -translate-y-1/2 items-center gap-1 rounded bg-zinc-200 p-1 font-mono text-xs text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400" >
58+ < CommandIcon size = { 14 } />
59+ < span > K</ span >
60+ </ kbd >
61+ ) }
62+ </ div >
3563 ) ;
3664} ;
3765
0 commit comments