From 4247696402213e749f1ce63eac230b732d6acfe2 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Wed, 22 Nov 2023 15:56:36 +0000 Subject: [PATCH] DockedMegaMenu: Keep undock button (#78461) * dock undock smoothly * handle keyboard focus * use ref instead of state * run i18n:extract * undo this change * make dock/undock first button to focus * only focus when going to docked, add comment * minor tweaks --- .../core/components/AppChrome/AppChrome.tsx | 2 +- .../components/AppChrome/AppChromeMenu.tsx | 13 +++++++-- .../AppChrome/DockedMegaMenu/MegaMenu.tsx | 28 +++++++++++++------ .../AppChrome/NavToolbar/NavToolbar.tsx | 20 +++++++++++-- public/locales/de-DE/grafana.json | 3 +- public/locales/en-US/grafana.json | 3 +- public/locales/es-ES/grafana.json | 3 +- public/locales/fr-FR/grafana.json | 3 +- public/locales/pseudo-LOCALE/grafana.json | 3 +- public/locales/zh-Hans/grafana.json | 3 +- 10 files changed, 59 insertions(+), 22 deletions(-) diff --git a/public/app/core/components/AppChrome/AppChrome.tsx b/public/app/core/components/AppChrome/AppChrome.tsx index a23b75fa50e..5f7bc35fe96 100644 --- a/public/app/core/components/AppChrome/AppChrome.tsx +++ b/public/app/core/components/AppChrome/AppChrome.tsx @@ -93,7 +93,7 @@ export function AppChrome({ children }: Props) { {!state.chromeless && ( <> - {config.featureToggles.dockedMegaMenu ? ( + {config.featureToggles.dockedMegaMenu && state.megaMenu !== 'docked' ? ( ) : ( chrome.setMegaMenu('closed')} /> diff --git a/public/app/core/components/AppChrome/AppChromeMenu.tsx b/public/app/core/components/AppChrome/AppChromeMenu.tsx index a204e7fc9b3..d5718520bce 100644 --- a/public/app/core/components/AppChrome/AppChromeMenu.tsx +++ b/public/app/core/components/AppChrome/AppChromeMenu.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import { useDialog } from '@react-aria/dialog'; import { FocusScope } from '@react-aria/focus'; import { OverlayContainer, useOverlay } from '@react-aria/overlays'; -import React, { useRef } from 'react'; +import React, { useEffect, useRef } from 'react'; import CSSTransition from 'react-transition-group/CSSTransition'; import { GrafanaTheme2 } from '@grafana/data'; @@ -20,11 +20,18 @@ export function AppChromeMenu({}: Props) { const theme = useTheme2(); const { chrome } = useGrafana(); const state = chrome.useState(); + const prevMegaMenuState = useRef(state.megaMenu); const searchBarHidden = state.searchBarHidden || state.kioskMode === KioskMode.TV; + useEffect(() => { + prevMegaMenuState.current = state.megaMenu; + }, [state.megaMenu]); + const ref = useRef(null); const backdropRef = useRef(null); - const animationSpeed = theme.transitions.duration.shortest; + // we don't want to show the opening animation when transitioning between docked + open + const animationSpeed = + prevMegaMenuState.current === 'docked' && state.megaMenu === 'open' ? 0 : theme.transitions.duration.shortest; const animationStyles = useStyles2(getAnimStyles, animationSpeed); const isOpen = state.megaMenu === 'open'; @@ -57,7 +64,7 @@ export function AppChromeMenu({}: Props) { classNames={animationStyles.overlay} timeout={{ enter: animationSpeed, exit: 0 }} > - + diff --git a/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx b/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx index 1a15b5c01c5..61fc62ca533 100644 --- a/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx +++ b/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx @@ -35,7 +35,12 @@ export const MegaMenu = React.memo( const activeItem = getActiveItem(navItems, location.pathname); const handleDockedMenu = () => { - chrome.setMegaMenu(state.megaMenu === 'docked' ? 'closed' : 'docked'); + chrome.setMegaMenu(state.megaMenu === 'docked' ? 'open' : 'docked'); + + // refocus on dock/undock button when changing state + setTimeout(() => { + document.getElementById('dock-menu-button')?.focus(); + }); }; return ( @@ -54,21 +59,26 @@ export const MegaMenu = React.memo(
    {navItems.map((link, index) => ( - - - {index === 0 && Boolean(state.megaMenu === 'open') && ( + + {index === 0 && ( )} + ))}
diff --git a/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx b/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx index 059d961b9a6..5d388544308 100644 --- a/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx +++ b/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx @@ -1,10 +1,11 @@ import { css } from '@emotion/css'; -import React from 'react'; +import React, { useState } from 'react'; import { GrafanaTheme2, NavModelItem } from '@grafana/data'; import { Components } from '@grafana/e2e-selectors'; -import { Icon, IconButton, ToolbarButton, useStyles2 } from '@grafana/ui'; +import { Icon, IconButton, ToolbarButton, useStyles2, useTheme2 } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; +import { useMediaQueryChange } from 'app/core/hooks/useMediaQueryChange'; import { t } from 'app/core/internationalization'; import { HOME_NAV_ID } from 'app/core/reducers/navModel'; import { useSelector } from 'app/types'; @@ -39,9 +40,22 @@ export function NavToolbar({ const { chrome } = useGrafana(); const state = chrome.useState(); const homeNav = useSelector((state) => state.navIndex)[HOME_NAV_ID]; + const theme = useTheme2(); const styles = useStyles2(getStyles); const breadcrumbs = buildBreadcrumbs(sectionNav, pageNav, homeNav); + const dockMenuBreakpoint = theme.breakpoints.values.xl; + const [isTooSmallForDockedMenu, setIsTooSmallForDockedMenu] = useState( + !window.matchMedia(`(min-width: ${dockMenuBreakpoint}px)`).matches + ); + + useMediaQueryChange({ + breakpoint: dockMenuBreakpoint, + onChange: (e) => { + setIsTooSmallForDockedMenu(!e.matches); + }, + }); + return (
@@ -49,7 +63,7 @@ export function NavToolbar({ id={TOGGLE_BUTTON_ID} name="bars" tooltip={ - state.megaMenu === 'closed' + state.megaMenu === 'closed' || (state.megaMenu === 'docked' && isTooSmallForDockedMenu) ? t('navigation.toolbar.open-menu', 'Open menu') : t('navigation.toolbar.close-menu', 'Close menu') } diff --git a/public/locales/de-DE/grafana.json b/public/locales/de-DE/grafana.json index 4b9e4b2fa0d..dcee13939eb 100644 --- a/public/locales/de-DE/grafana.json +++ b/public/locales/de-DE/grafana.json @@ -935,7 +935,8 @@ }, "megamenu": { "close": "Menü schließen", - "dock": "Menü andocken" + "dock": "Menü andocken", + "undock": "" }, "toolbar": { "close-menu": "Menü schließen", diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 33ef5f29eaf..79923a71a71 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -935,7 +935,8 @@ }, "megamenu": { "close": "Close menu", - "dock": "Dock menu" + "dock": "Dock menu", + "undock": "Undock menu" }, "toolbar": { "close-menu": "Close menu", diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index c79d6c2442e..2ec04f36b0c 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -941,7 +941,8 @@ }, "megamenu": { "close": "Cerrar menú", - "dock": "Menú base" + "dock": "Menú base", + "undock": "" }, "toolbar": { "close-menu": "Cerrar menú", diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index bd64c9a5295..fd75a0e3af4 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -941,7 +941,8 @@ }, "megamenu": { "close": "Fermer le menu", - "dock": "Ancrer le menu" + "dock": "Ancrer le menu", + "undock": "" }, "toolbar": { "close-menu": "Fermer le menu", diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 77be386cb16..24d16fe8c07 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -935,7 +935,8 @@ }, "megamenu": { "close": "Cľőşę męʼnū", - "dock": "Đőčĸ męʼnū" + "dock": "Đőčĸ męʼnū", + "undock": "Ůʼnđőčĸ męʼnū" }, "toolbar": { "close-menu": "Cľőşę męʼnū", diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json index a6594545607..f88e92d9fb1 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -929,7 +929,8 @@ }, "megamenu": { "close": "关闭菜单", - "dock": "停靠菜单" + "dock": "停靠菜单", + "undock": "" }, "toolbar": { "close-menu": "关闭菜单",