diff --git a/packages/interface/src/components/layout/TopBar.tsx b/packages/interface/src/components/layout/TopBar.tsx index b5804840d..ee924040e 100644 --- a/packages/interface/src/components/layout/TopBar.tsx +++ b/packages/interface/src/components/layout/TopBar.tsx @@ -1,5 +1,5 @@ import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline'; -import { AppPropsContext, useExplorerStore, useLibraryMutation } from '@sd/client'; +import { AppPropsContext, useAppProps, useExplorerStore, useLibraryMutation } from '@sd/client'; import { Dropdown } from '@sd/ui'; import clsx from 'clsx'; import { @@ -11,7 +11,7 @@ import { SidebarSimple, SquaresFour } from 'phosphor-react'; -import React, { DetailedHTMLProps, HTMLAttributes, RefAttributes, useContext } from 'react'; +import React, { DetailedHTMLProps, HTMLAttributes, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; import { Shortcut } from '../primitive/Shortcut'; @@ -67,7 +67,7 @@ const SearchBar = React.forwardRef((props, ref) placeholder="Search" className="peer w-32 h-[30px] focus:w-52 text-sm p-3 rounded-lg outline-none focus:ring-2 placeholder-gray-400 dark:placeholder-gray-450 bg-[#F6F2F6] border border-gray-50 shadow-md dark:bg-gray-600 dark:border-gray-550 focus:ring-gray-100 dark:focus:ring-gray-550 dark:focus:bg-gray-800 transition-all" /> -
+
((props, ref) }); export const TopBar: React.FC = (props) => { + const appProps = useAppProps(); + const { layoutMode, set, locationId, showInspector } = useExplorerStore(); const { mutate: generateThumbsForLocation } = useLibraryMutation( 'jobs.generateThumbsForLocation', @@ -101,34 +103,65 @@ export const TopBar: React.FC = (props) => { const navigate = useNavigate(); - //create function to focus on search box when cmd+k is pressed - const searchRef = React.useRef(null); + const searchBarRef = React.useRef(null); + + const focusSearchBar = (bar: HTMLInputElement, e?: Event): boolean => { + bar.focus(); + + e?.preventDefault(); + return false; + }; + React.useEffect(() => { - const handler = (e: KeyboardEvent) => { - if (e.metaKey && e.key === 'l') { - if (searchRef.current) searchRef.current.focus(); + const searchBar = searchBarRef.current; + + if (searchBar === null || !searchBar) return; + + const handleKeybindAction = (e: KeybindEvent) => { + if (e.detail.action === 'open_search') { + return focusSearchBar(searchBar, e); + } + }; + + const handleWebKeydown = (e: KeyboardEvent) => { + if (e.target === searchBar && e.key === 'Escape') { + (e.target as HTMLInputElement).blur(); e.preventDefault(); return; } - if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) { - if (e.key === 'Escape') { - e.target.blur(); - e.preventDefault(); - return; - } - } else { - if (e.key === '/') { - if (searchRef.current) searchRef.current.focus(); - e.preventDefault(); - return; - } + // only do this keybind check on browser to allow for native keybind functionality + // this is particularly useful for power-user niche use cases, + // like how macOS lets you redefine keybinds for apps + + const isBrowser = appProps?.platform === 'browser'; + // use cmd on macOS and ctrl on Windows + const hasModifier = isBrowser && navigator.platform.startsWith('Mac') ? e.metaKey : e.ctrlKey; + + if ( + // allow slash on all platforms + (e.key === '/' && + !(document.activeElement instanceof HTMLInputElement) && + !(document.activeElement instanceof HTMLTextAreaElement)) || + // only check for cmd-l on browser + (isBrowser && hasModifier && e.key === 'l') + ) { + document.dispatchEvent( + new CustomEvent('exec_keybind', { detail: { action: 'open_search' } }) + ); + e.preventDefault(); + return; } }; - document.addEventListener('keydown', handler); - return () => document.removeEventListener('keydown', handler); - }, []); + document.addEventListener('keydown', handleWebKeydown); + document.addEventListener('exec_keybind', handleKeybindAction); + + return () => { + document.removeEventListener('keydown', handleWebKeydown); + document.removeEventListener('exec_keybind', handleKeybindAction); + }; + }, [appProps?.platform]); return ( <> @@ -172,7 +205,7 @@ export const TopBar: React.FC = (props) => { />
- +