diff --git a/app/layout.tsx b/app/layout.tsx
index 2a423ce1..be93992a 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -24,7 +24,6 @@ import AdminUploadPanel from '@/admin/upload/AdminUploadPanel';
import { revalidatePath } from 'next/cache';
import RecipeModal from '@/recipe/RecipeModal';
import ThemeColors from '@/app/ThemeColors';
-import AppKeyListener from '@/app/AppKeyListener';
import '../tailwind.css';
@@ -115,7 +114,6 @@ export default function RootLayout({
-
diff --git a/src/app/AppKeyListener.tsx b/src/app/AppKeyListener.tsx
deleted file mode 100644
index 178dac73..00000000
--- a/src/app/AppKeyListener.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-'use client';
-
-import useKeydownHandler from '@/utility/useKeydownHandler';
-import { PATH_FEED_INFERRED, PATH_GRID_INFERRED } from './paths';
-import { useCallback } from 'react';
-import { useRouter, usePathname } from 'next/navigation';
-
-const PATH_MAPS = {
- G: PATH_GRID_INFERRED,
- F: PATH_FEED_INFERRED,
-};
-
-export default function AppKeyListener() {
- const pathname = usePathname();
-
- const router = useRouter();
-
- const onKeyDown = useCallback((e: KeyboardEvent) => {
- const path = PATH_MAPS[e.key.toLocaleUpperCase() as keyof typeof PATH_MAPS];
- if (path && pathname !== path) {
- router.push(path);
- }
- }, [router, pathname]);
-
- useKeydownHandler({ onKeyDown });
-
- return null;
-}
diff --git a/src/app/AppViewSwitcher.tsx b/src/app/AppViewSwitcher.tsx
index 58972cdb..5e3c5018 100644
--- a/src/app/AppViewSwitcher.tsx
+++ b/src/app/AppViewSwitcher.tsx
@@ -12,7 +12,9 @@ import { GRID_HOMEPAGE_ENABLED } from './config';
import AdminAppMenu from '@/admin/AdminAppMenu';
import Spinner from '@/components/Spinner';
import clsx from 'clsx/lite';
-import { useState, useRef, useEffect } from 'react';
+import { useCallback, useRef, useState } from 'react';
+import useKeydownHandler from '@/utility/useKeydownHandler';
+import { usePathname } from 'next/navigation';
export type SwitcherSelection = 'feed' | 'grid' | 'admin';
@@ -23,32 +25,39 @@ export default function AppViewSwitcher({
currentSelection?: SwitcherSelection
className?: string
}) {
+ const pathname = usePathname();
+
const {
isUserSignedIn,
isUserSignedInEager,
setIsCommandKOpen,
} = useAppState();
- const hasAdminMenuOpenedOnce = useRef(false);
- const [isAdminMenuOpen, setIsAdminMenuOpen] = useState(false);
+ const refHrefFeed = useRef(null);
+ const refHrefGrid = useRef(null);
- useEffect(() => {
- if (isAdminMenuOpen) {
- hasAdminMenuOpenedOnce.current = true;
- } else if (hasAdminMenuOpenedOnce.current) {
- // Blur admin menu button to avoid tooltip on dismiss
- setTimeout(() => {
- if (document.activeElement instanceof HTMLElement) {
- document.activeElement.blur();
- }
- }, 50);
+ const onKeyDown = useCallback((e: KeyboardEvent) => {
+ switch (e.key.toLocaleUpperCase()) {
+ case 'F':
+ if (pathname !== PATH_FEED_INFERRED) { refHrefFeed.current?.click(); }
+ break;
+ case 'G':
+ if (pathname !== PATH_GRID_INFERRED) { refHrefGrid.current?.click(); }
+ break;
+ case 'A':
+ if (isUserSignedIn) { setIsAdminMenuOpen(true); }
+ break;
}
- }, [isAdminMenuOpen]);
+ }, [pathname, isUserSignedIn]);
+ useKeydownHandler({ onKeyDown });
+
+ const [isAdminMenuOpen, setIsAdminMenuOpen] = useState(false);
const renderItemFeed =
}
href={PATH_FEED_INFERRED}
+ hrefRef={refHrefFeed}
active={currentSelection === 'feed'}
tooltip={{
content: 'Feed',
@@ -61,6 +70,7 @@ export default function AppViewSwitcher({
}
href={PATH_GRID_INFERRED}
+ hrefRef={refHrefGrid}
active={currentSelection === 'grid'}
tooltip={{
content: 'Grid',
@@ -93,7 +103,10 @@ export default function AppViewSwitcher({
isOpen={isAdminMenuOpen}
setIsOpen={setIsAdminMenuOpen}
/>}
- tooltip={{ content: !isAdminMenuOpen ? 'Admin Menu' : undefined }}
+ tooltip={{
+ content: !isAdminMenuOpen ? 'Admin Menu' : undefined,
+ keyCommand: !isAdminMenuOpen ? 'A' : undefined,
+ }}
noPadding
/>}
diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx
index a93e82e8..190e33cd 100644
--- a/src/components/Modal.tsx
+++ b/src/components/Modal.tsx
@@ -61,7 +61,10 @@ export default function Modal({
},
});
- useEscapeHandler(onClose, true);
+ useEscapeHandler({
+ onKeyDown: onClose,
+ ignoreShouldRespondToKeyboardCommands: true,
+ });
return (
className?: string
onClick?: () => void
active?: boolean
@@ -57,6 +59,7 @@ export default function SwitcherItem({
const content = href
?
{content}
diff --git a/src/components/more/MoreMenu.tsx b/src/components/more/MoreMenu.tsx
index 4cb4c4f9..17e56e05 100644
--- a/src/components/more/MoreMenu.tsx
+++ b/src/components/more/MoreMenu.tsx
@@ -75,6 +75,7 @@ export default function MoreMenu({
e.preventDefault()}
align={align}
sideOffset={sideOffset}
className={clsx(
diff --git a/src/photo/PhotoEscapeHandler.tsx b/src/photo/PhotoEscapeHandler.tsx
index c52223af..89047a76 100644
--- a/src/photo/PhotoEscapeHandler.tsx
+++ b/src/photo/PhotoEscapeHandler.tsx
@@ -12,11 +12,11 @@ export default function PhotoEscapeHandler() {
const escapePath = getEscapePath(pathname);
- const escapeHandler = useCallback(() => {
+ const onKeyDown = useCallback(() => {
if (escapePath) { router.push(escapePath, { scroll: false }); }
}, [escapePath, router]);
- useEscapeHandler(escapeHandler);
+ useEscapeHandler({ onKeyDown });
return null;
}
diff --git a/src/utility/useEscapeHandler.ts b/src/utility/useEscapeHandler.ts
index 8eaf9ea3..fd37d3f3 100644
--- a/src/utility/useEscapeHandler.ts
+++ b/src/utility/useEscapeHandler.ts
@@ -1,12 +1,10 @@
import useKeydownHandler from '@/utility/useKeydownHandler';
export default function useEscapeHandler(
- onKeyDown?: (e: KeyboardEvent) => void,
- ignoreShouldRespondToKeyboardCommands?: boolean,
+ args: Omit[0], 'keys'>,
) {
useKeydownHandler({
- onKeyDown,
+ ...args,
keys: ['ESCAPE'],
- ignoreShouldRespondToKeyboardCommands,
});
}