@@ -7,6 +7,61 @@ import styles from "./Root.module.css"; // Import the CSS module
77import { useLocation } from "@docusaurus/router" ;
88import useDocusaurusContext from "@docusaurus/useDocusaurusContext" ;
99
10+ function isEditableEventTarget ( target : EventTarget | null ) : boolean {
11+ if ( ! ( target instanceof Element ) ) {
12+ return false ;
13+ }
14+
15+ if ( target . isContentEditable ) {
16+ return true ;
17+ }
18+
19+ const tagName = target . tagName . toLowerCase ( ) ;
20+ if ( tagName === "textarea" || tagName === "select" ) {
21+ return true ;
22+ }
23+
24+ if ( target instanceof HTMLInputElement ) {
25+ const editableTypes = new Set ( [
26+ "text" ,
27+ "search" ,
28+ "url" ,
29+ "tel" ,
30+ "email" ,
31+ "password" ,
32+ "number" ,
33+ "date" ,
34+ "datetime-local" ,
35+ "month" ,
36+ "time" ,
37+ "week" ,
38+ ] ) ;
39+ return ! target . readOnly && ! target . disabled && editableTypes . has ( target . type ) ;
40+ }
41+
42+ return target . matches (
43+ "[contenteditable='true'], [contenteditable=''], [contenteditable='plaintext-only']" ,
44+ ) ;
45+ }
46+
47+ function focusSearchInput ( ) : boolean {
48+ const navbarSearch = document . querySelector < HTMLInputElement > (
49+ "#algolia-sitesearch-navbar input" ,
50+ ) ;
51+ if ( navbarSearch ) {
52+ navbarSearch . focus ( { preventScroll : true } ) ;
53+ return true ;
54+ }
55+
56+ const blogSearch = document . querySelector < HTMLInputElement > ( ".blog-search-input" ) ;
57+ if ( blogSearch ) {
58+ blogSearch . focus ( { preventScroll : true } ) ;
59+ return true ;
60+ }
61+
62+ return false ;
63+ }
64+
1065// A simple Trophy SVG icon component
1166function TrophyIcon ( ) {
1267 return (
@@ -144,6 +199,33 @@ export default function Root({ children }: { children: React.ReactNode }) {
144199 } ;
145200 } , [ ] ) ;
146201
202+ useEffect ( ( ) => {
203+ function handleGlobalSearchShortcut ( event : KeyboardEvent ) {
204+ if (
205+ event . key !== "/" ||
206+ event . defaultPrevented ||
207+ event . metaKey ||
208+ event . altKey ||
209+ event . ctrlKey
210+ ) {
211+ return ;
212+ }
213+
214+ if ( isEditableEventTarget ( event . target ) ) {
215+ return ;
216+ }
217+
218+ if ( focusSearchInput ( ) ) {
219+ event . preventDefault ( ) ;
220+ }
221+ }
222+
223+ document . addEventListener ( "keydown" , handleGlobalSearchShortcut ) ;
224+ return ( ) => {
225+ document . removeEventListener ( "keydown" , handleGlobalSearchShortcut ) ;
226+ } ;
227+ } , [ ] ) ;
228+
147229 // Show toast on initial load for all pages
148230 useEffect ( ( ) => {
149231 setShowToast ( true ) ;
0 commit comments