diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts index bcf3cee9c..8d4e15eb9 100644 --- a/frontend/src/hooks/index.ts +++ b/frontend/src/hooks/index.ts @@ -4,42 +4,63 @@ export function useOutsideAlerter( ref: RefObject, handler: () => void, additionalDeps: unknown[], + handleEscapeKey?: boolean, ) { useEffect(() => { - function handleClickOutside(this: Document, event: MouseEvent) { + function handleClickOutside(event: MouseEvent) { if (ref.current && !ref.current.contains(event.target as Node)) { handler(); } } + + function handleEscape(event: KeyboardEvent) { + if (event.key === 'Escape') { + handler(); + } + } + document.addEventListener('mousedown', handleClickOutside); + if (handleEscapeKey) { + document.addEventListener('keydown', handleEscape); + } + return () => { document.removeEventListener('mousedown', handleClickOutside); + if (handleEscapeKey) { + document.removeEventListener('keydown', handleEscape); + } }; }, [ref, ...additionalDeps]); } -// Use isMobile for checking if the width is in the expected mobile range (less than 768px) -// use IsDesktop for effects you explicitly only want when width is wider than 960px. export function useMediaQuery() { const mobileQuery = '(max-width: 768px)'; + const darkModeQuery = '(prefers-color-scheme: dark)'; // Detect dark mode const desktopQuery = '(min-width: 960px)'; const [isMobile, setIsMobile] = useState(false); const [isDesktop, setIsDesktop] = useState(false); + const [isDarkMode, setIsDarkMode] = useState(false); useEffect(() => { const mobileMedia = window.matchMedia(mobileQuery); const desktopMedia = window.matchMedia(desktopQuery); + const darkModeMedia = window.matchMedia(darkModeQuery); + const updateMediaQueries = () => { setIsMobile(mobileMedia.matches); setIsDesktop(desktopMedia.matches); + setIsDarkMode(darkModeMedia.matches); }; + updateMediaQueries(); + const listener = () => updateMediaQueries(); window.addEventListener('resize', listener); + return () => { window.removeEventListener('resize', listener); }; - }, [mobileQuery, desktopQuery]); + }, [mobileQuery, desktopQuery, darkModeQuery]); - return { isMobile, isDesktop }; + return { isMobile, isDesktop, isDarkMode }; }