From 9d9707e6f43fabde8ca459c44990682b4b054a12 Mon Sep 17 00:00:00 2001 From: Peter Zimon Date: Wed, 13 Mar 2024 08:46:22 +0100 Subject: [PATCH] Settings keyboard shortcuts (#19836) ref DES-166 Accessing settings via a keyboard shortcut is a great productivity booster for advanced users and it is missing from Ghost today. --- .../src/global/form/Select.tsx | 3 ++ .../src/global/modal/Modal.tsx | 3 ++ apps/admin-x-settings/src/MainContent.tsx | 27 +++++++++++--- .../src/components/ExitSettingsButton.tsx | 2 +- .../src/components/Settings.tsx | 2 +- .../src/components/Sidebar.tsx | 24 +++++++++++-- apps/admin-x-settings/src/styles/index.css | 36 +++++++++++++++++-- .../app/components/gh-nav-menu/footer.hbs | 2 +- .../admin/app/components/gh-nav-menu/main.js | 6 ++++ 9 files changed, 93 insertions(+), 12 deletions(-) diff --git a/apps/admin-x-design-system/src/global/form/Select.tsx b/apps/admin-x-design-system/src/global/form/Select.tsx index bd6624c1da..2fec485998 100644 --- a/apps/admin-x-design-system/src/global/form/Select.tsx +++ b/apps/admin-x-design-system/src/global/form/Select.tsx @@ -127,6 +127,9 @@ const Select: React.FC = ({ document.activeElement.blur(); } setFocusState(false); + + // Prevent the event from bubbling up to the window level + event.stopPropagation(); } }; diff --git a/apps/admin-x-design-system/src/global/modal/Modal.tsx b/apps/admin-x-design-system/src/global/modal/Modal.tsx index af352f423f..2377c3de3f 100644 --- a/apps/admin-x-design-system/src/global/modal/Modal.tsx +++ b/apps/admin-x-design-system/src/global/modal/Modal.tsx @@ -107,6 +107,9 @@ const Modal: React.FC = ({ }); } }); + + // Prevent the event from bubbling up to the window level + event.stopPropagation(); } }; diff --git a/apps/admin-x-settings/src/MainContent.tsx b/apps/admin-x-settings/src/MainContent.tsx index 94bcb0cf12..45bafb385a 100644 --- a/apps/admin-x-settings/src/MainContent.tsx +++ b/apps/admin-x-settings/src/MainContent.tsx @@ -2,7 +2,7 @@ import ExitSettingsButton from './components/ExitSettingsButton'; import Settings from './components/Settings'; import Sidebar from './components/Sidebar'; import Users from './components/settings/general/Users'; -import {Heading, topLevelBackdropClasses} from '@tryghost/admin-x-design-system'; +import {Heading, confirmIfDirty, topLevelBackdropClasses, useGlobalDirtyState} from '@tryghost/admin-x-design-system'; import {ReactNode, useEffect} from 'react'; import {canAccessSettings, isEditorUser} from '@tryghost/admin-x-framework/api/users'; import {toast} from 'react-hot-toast'; @@ -11,7 +11,7 @@ import {useRouting} from '@tryghost/admin-x-framework/routing'; const Page: React.FC<{children: ReactNode}> = ({children}) => { return <> -
+
@@ -23,6 +23,25 @@ const Page: React.FC<{children: ReactNode}> = ({children}) => { const MainContent: React.FC = () => { const {currentUser} = useGlobalData(); const {route, updateRoute, loadingModal} = useRouting(); + const {isDirty} = useGlobalDirtyState(); + + const navigateAway = () => { + window.location.hash = '/dashboard'; + }; + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + confirmIfDirty(isDirty, navigateAway); + } + }; + + window.addEventListener('keydown', handleKeyDown); + + return () => { + window.removeEventListener('keydown', handleKeyDown); + }; + }, []); useEffect(() => { // resets any toasts that may have been left open on initial load @@ -53,12 +72,12 @@ const MainContent: React.FC = () => { return ( {loadingModal &&
} -
+
-
+
diff --git a/apps/admin-x-settings/src/components/ExitSettingsButton.tsx b/apps/admin-x-settings/src/components/ExitSettingsButton.tsx index eefa5ade04..742682f2f2 100644 --- a/apps/admin-x-settings/src/components/ExitSettingsButton.tsx +++ b/apps/admin-x-settings/src/components/ExitSettingsButton.tsx @@ -9,7 +9,7 @@ const ExitSettingsButton: React.FC = () => { }; return ( -