From 90f45935259d0d8ad100a0c199e155e73c835d0d Mon Sep 17 00:00:00 2001 From: marcoskolodny Date: Tue, 5 Nov 2024 11:17:29 +0100 Subject: [PATCH] fix focus logic and right content height --- src/navigation-bar.css.ts | 142 +++++++++++++++++++++++--------------- src/navigation-bar.tsx | 28 ++++---- 2 files changed, 102 insertions(+), 68 deletions(-) diff --git a/src/navigation-bar.css.ts b/src/navigation-bar.css.ts index c02e7fd87..2e829da01 100644 --- a/src/navigation-bar.css.ts +++ b/src/navigation-bar.css.ts @@ -143,26 +143,35 @@ export const desktopMenuSectionContainer = style([ }, ]); -export const desktopMenuSectionWithArrowWrapper = style({ +export const desktopMenuSectionWithArrowWrapper = sprinkles({ position: 'relative', }); -export const desktopMenuSectionArrowContainer = style({ - position: 'absolute', - zIndex: -1, - right: -8, - top: 0, - bottom: 0, - display: 'flex', - alignItems: 'center', -}); +export const desktopMenuSectionArrowContainer = style([ + sprinkles({ + position: 'absolute', + top: 0, + bottom: 0, + display: 'flex', + alignItems: 'center', + }), + { + // Avoid element from affecting hover status of the section + zIndex: -1, + right: -8, + }, +]); -export const desktopMenuSectionArrow = style({ - border: 'none', - background: 'transparent', - padding: 0, - transition: `opacity 0.1s`, -}); +export const desktopMenuSectionArrow = style([ + sprinkles({ + border: 'none', + background: 'transparent', + padding: 0, + }), + { + transition: `opacity 0.1s`, + }, +]); export const section = style([ sprinkles({ @@ -209,22 +218,26 @@ export const textWrapperVariants = styleVariants({ }, }); -export const navigationBarContent = style({ - alignItems: 'center', - width: '100%', - display: 'flex', - height: NAVBAR_HEIGHT_DESKTOP, - '@media': { - [mq.tabletOrSmaller]: { - height: NAVBAR_HEIGHT_MOBILE - borderWidth, - }, - [mq.desktopOrBigger]: { - ':last-child': { - height: NAVBAR_HEIGHT_DESKTOP - borderWidth, +export const navigationBarContent = style([ + sprinkles({ + alignItems: 'center', + width: '100%', + display: 'flex', + }), + { + height: NAVBAR_HEIGHT_DESKTOP, + '@media': { + [mq.tabletOrSmaller]: { + height: NAVBAR_HEIGHT_MOBILE - borderWidth, + }, + [mq.desktopOrBigger]: { + ':last-child': { + height: NAVBAR_HEIGHT_DESKTOP - borderWidth, + }, }, }, }, -}); +]); export const navigationBarAction = sprinkles({ border: 'none', @@ -240,18 +253,29 @@ export const desktopOnly = style({ }, }); -export const navigationBarContentRight = style({ - display: 'flex', - flex: 1, - alignItems: 'center', - justifyContent: 'flex-end', - paddingLeft: 136, - '@media': { - [mq.tabletOrSmaller]: { - paddingLeft: 24, +export const navigationBarContentRight = style([ + sprinkles({ + display: 'flex', + flex: 1, + alignItems: 'center', + justifyContent: 'flex-end', + }), + { + paddingLeft: 136, + height: NAVBAR_HEIGHT_DESKTOP, + '@media': { + [mq.tabletOrSmaller]: { + paddingLeft: 24, + height: NAVBAR_HEIGHT_MOBILE - borderWidth, + }, + [mq.desktopOrBigger]: { + ':last-child': { + height: NAVBAR_HEIGHT_DESKTOP - borderWidth, + }, + }, }, }, -}); +]); const spacerMobile = style({ '@media': { @@ -280,7 +304,7 @@ export const burgerMenuTransition = { transform: 'translate(-100vw)', }), enterActive: style({ - transform: 'translate(0vw)', + transform: 'translate(0)', transition: `transform ${BURGER_MENU_ANIMATION_DURATION_MS}ms ease-out`, '@media': { ['(prefers-reduced-motion)']: { @@ -289,7 +313,7 @@ export const burgerMenuTransition = { }, }), exit: style({ - transform: 'translate(0vw)', + transform: 'translate(0)', }), exitActive: style({ transform: 'translate(-100vw)', @@ -302,7 +326,7 @@ export const burgerMenuTransition = { }), }; -export const mainNavbarContent = style({ +export const mainNavbarContent = sprinkles({ display: 'flex', alignItems: 'center', }); @@ -344,19 +368,25 @@ export const burgerMenu = style([ }, ]); -export const burgerMainMenuContainer = style({ - height: `calc(100vh - ${NAVBAR_HEIGHT_MOBILE}px)`, - overflowY: 'auto', -}); +export const burgerMainMenuContainer = style([ + sprinkles({overflowY: 'auto'}), + { + height: `calc(100vh - ${NAVBAR_HEIGHT_MOBILE}px)`, + }, +]); -export const burgerSubMenuContainer = style({ - height: `calc(100vh - ${NAVBAR_HEIGHT_MOBILE}px)`, - overflowY: 'auto', - width: '100%', - position: 'absolute', - left: '100vw', - top: 0, -}); +export const burgerSubMenuContainer = style([ + sprinkles({ + overflowY: 'auto', + width: '100%', + position: 'absolute', + top: 0, + }), + { + height: `calc(100vh - ${NAVBAR_HEIGHT_MOBILE}px)`, + left: '100vw', + }, +]); export const iconButtonVariants = styleVariants({ default: [ @@ -444,12 +474,12 @@ export const desktopSmallMenuContainer = style([ position: 'fixed', paddingY: 40, paddingX: 24, + overflowY: 'auto', }), { zIndex: NAVBAR_ZINDEX, borderRadius: `0 0 ${vars.borderRadii.popup} ${vars.borderRadii.popup}`, width: DESKTOP_SMALL_MENU_WIDTH, - overflowY: 'auto', boxShadow: '0px 2px 4px rgba(0,0,0,0.2)', }, ]); @@ -471,7 +501,7 @@ export const desktopMenu = style([ ]); export const desktopMenuContentFadeIn = style({ - transform: 'translateY(0px)', + transform: 'translateY(0)', opacity: 1, transition: `opacity ${DESKTOP_MENU_CONTENT_ANIMATION_DURATION_MS}ms cubic-bezier(0.33, 1, 0.68, 1), transform ${DESKTOP_MENU_CONTENT_ANIMATION_DURATION_MS}ms cubic-bezier(0.33, 1, 0.68, 1)`, '@media': { diff --git a/src/navigation-bar.tsx b/src/navigation-bar.tsx index e33afbd3a..c2a51a50e 100644 --- a/src/navigation-bar.tsx +++ b/src/navigation-bar.tsx @@ -371,7 +371,7 @@ const MainNavigationBarDesktopMenuContextProvider = ({ let id: NodeJS.Timeout; - // If menu started opening/closing + // menu starts opening or closing if (!isMenuOpen) { dispatch('close'); id = setTimeout(() => dispatch('finishClose'), menuAnimationDuration); @@ -947,7 +947,7 @@ const MainNavigationBarDesktopSection = ({ const {title, menu, ...touchableProps} = section; const sectionRef = React.useRef(null); const [smallMenuLeftPosition, setSmallMenuLeftPosition] = React.useState(0); - const [isArrowFocused, setIsArrowFocused] = React.useState(false); + const [isMenuControlFocused, setIsMenuControlFocused] = React.useState(false); const {isMenuOpen, openedSection, setSectionAsActive, setSectionAsInactive} = useMainNavigationBarDesktopMenuState(); @@ -976,12 +976,10 @@ const MainNavigationBarDesktopSection = ({ React.useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { - const shouldReactOnArrowKeyPress = isArrowFocused || (menu && !hasCustomInteraction); - switch (e.key) { // If arrow is focused and DOWN key is pressed, open the menu if it was closed case DOWN: - if (shouldReactOnArrowKeyPress) { + if (isMenuControlFocused) { cancelEvent(e); openSectionMenu(); } @@ -989,7 +987,7 @@ const MainNavigationBarDesktopSection = ({ // If arrow is focused and UP key is pressed, close the menu if it was opened case UP: - if (shouldReactOnArrowKeyPress) { + if (isMenuControlFocused) { cancelEvent(e); setSectionAsInactive(index, true); } @@ -1004,7 +1002,7 @@ const MainNavigationBarDesktopSection = ({ return () => { document.removeEventListener('keydown', handleKeyDown, false); }; - }, [index, isArrowFocused, openSectionMenu, setSectionAsInactive, menu, hasCustomInteraction]); + }, [index, isMenuControlFocused, openSectionMenu, setSectionAsInactive, menu, hasCustomInteraction]); const isSectionMenuOpen = isMenuOpen && openedSection === index; @@ -1041,6 +1039,12 @@ const MainNavigationBarDesktopSection = ({ // TODO: debounce this! onMouseEnter={openSectionMenu} onMouseLeave={() => setSectionAsInactive(index)} + onFocus={() => { + if (menu && !hasCustomInteraction) setIsMenuControlFocused(true); + }} + onBlur={() => { + if (menu && !hasCustomInteraction) setIsMenuControlFocused(false); + }} > setIsArrowFocused(true)} - onBlur={() => setIsArrowFocused(false)} + onFocus={() => setIsMenuControlFocused(true)} + onBlur={() => setIsMenuControlFocused(false)} > { - if (isArrowFocused) { + if (isMenuControlFocused) { menuButtonOnPress(); } }} style={{ - pointerEvents: isArrowFocused ? 'auto' : 'none', - opacity: isArrowFocused ? 1 : 0, + pointerEvents: isMenuControlFocused ? 'auto' : 'none', + opacity: isMenuControlFocused ? 1 : 0, }} >