From 6f739bfb9c0d647374a16453a1f16a183f5c6e05 Mon Sep 17 00:00:00 2001 From: Wojtek Bazant Date: Fri, 10 Jan 2025 11:43:54 +0000 Subject: [PATCH] ipad layout for header --- src/components/desktop/Header.js | 332 ++++++++++++++++++------------- 1 file changed, 199 insertions(+), 133 deletions(-) diff --git a/src/components/desktop/Header.js b/src/components/desktop/Header.js index 9e92e65b..efc23576 100644 --- a/src/components/desktop/Header.js +++ b/src/components/desktop/Header.js @@ -1,5 +1,6 @@ -import { CaretDown } from '@styled-icons/boxicons-regular' +import { CaretDown, Menu,X } from '@styled-icons/boxicons-regular' import { User } from '@styled-icons/boxicons-solid' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' import { matchPath } from 'react-router' @@ -25,9 +26,12 @@ const AuthLinksList = styled.ul` margin: 0; height: 100%; display: flex; + align-items: center; gap: 12px; ` +const TIGHT_LAYOUT_MAX_WIDTH = 940 + const StyledHeader = styled.header` height: 56px; background-color: ${({ theme }) => theme.background}; @@ -42,76 +46,106 @@ const StyledHeader = styled.header` width: auto; } + .hamburger { + display: ${({ user }) => + !user && window.innerWidth <= TIGHT_LAYOUT_MAX_WIDTH ? 'flex' : 'none'}; + margin-right: 1rem; + cursor: pointer; + color: ${({ theme }) => theme.secondaryText}; + align-self: center; + align-items: center; + } + nav { height: 100%; display: flex; - justify-content: space-between; + justify-content: flex-end; flex: 1; - ul { - list-style: none; - padding: 0; - margin: 0 0 0 0; - height: 100%; - display: flex; + .main-menu { + display: ${({ user }) => + user || window.innerWidth > TIGHT_LAYOUT_MAX_WIDTH ? 'block' : 'none'}; - li { - display: flex; - justify-content: stretch; - align-items: stretch; - min-width: 110px; - margin: 0; - color: ${({ theme }) => theme.secondaryText}; - cursor: pointer; - position: relative; - font-weight: bold; - font-size: 1rem; - - a, - .content button { - text-decoration: none; - color: ${({ theme }) => theme.secondaryText}; - text-align: center; - display: flex; - align-items: center; - justify-content: center; - flex: 1; - font-weight: inherit; - font-size: inherit; - - &.active { - background-color: ${({ theme }) => theme.navBackground}; - color: ${({ theme }) => theme.orange}; - - ::before { - content: ''; - width: 100%; - position: absolute; - background-color: ${({ theme }) => theme.orange}; - height: 3px; - bottom: 0; - left: 0; - } - } - } + &.mobile-visible { + display: block; + } + } - &.active { - color: ${({ theme }) => theme.orange}; - } + .auth-social { + display: flex; + } + + .auth-buttons { + &.mobile-hidden { + display: none; } + } + } +` + +const NavLi = styled.li` + display: flex; + justify-content: stretch; + align-items: stretch; + min-width: ${() => + window.innerWidth <= TIGHT_LAYOUT_MAX_WIDTH ? '80px' : '110px'}; + margin: 0; + color: ${({ theme }) => theme.secondaryText}; + cursor: pointer; + position: relative; + font-weight: bold; + font-size: 1rem; + + &.signin, + &.signup { + min-width: auto; + } - .signin, - .signup { - min-width: auto; + a, + .content button { + text-decoration: none; + color: ${({ theme }) => theme.secondaryText}; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + flex: 1; + font-weight: inherit; + font-size: inherit; + + &.active { + background-color: ${({ theme }) => theme.navBackground}; + color: ${({ theme }) => theme.orange}; + + ::before { + content: ''; + width: 100%; + position: absolute; + background-color: ${({ theme }) => theme.orange}; + height: 3px; + bottom: 0; + left: 0; } } } + + &.active { + color: ${({ theme }) => theme.orange}; + } +` + +const NavList = styled.ul` + list-style: none; + padding: 0; + margin: 0 0 0 0; + height: 100%; + display: flex; ` const Dropdown = ({ className, children, label, isMatch }) => (
- {label} + {label}
{children}
@@ -221,103 +255,135 @@ const StyledSocialButtons = styled(SocialButtons)` } ` -// TODO: Clean up file structure (i.e. logo_white.svg) from ./public -const Header = () => { +const UserMenu = () => { const { t } = useTranslation() const user = useSelector((state) => state.auth.user) const dispatch = useDispatch() const handleLogout = () => { dispatch(logout()) } + const isAccountPage = useRouteMatch('/users/edit') !== null + + return ( +
+ + {user ? ( + + + {user.name || user.email} + + } + isMatch={isAccountPage} + > + + {t('glossary.account')} + + + {t('glossary.logout')} + + + + ) : ( + + + + + + + + + {t('glossary.sign_up')} + + + + )} + +
+ ) +} +const MainMenu = ({ className }) => { + const { t } = useTranslation() const isAboutPage = matchPath(useLocation().pathname, { path: aboutRoutes.map((route) => route.props.path).flat(), }) !== null - const isAccountPage = useRouteMatch('/users/edit') !== null return ( - +
+ + + + {t('glossary.map')} + + + + + {t('glossary.activity')} + + + + + + {t('layouts.application.menu.the_project')} + + + {t('layouts.application.menu.the_data')} + + + {t('layouts.application.menu.sharing_the_harvest')} + + + {t('layouts.application.menu.in_the_press')} + + + + +
+ ) +} + +// TODO: Clean up file structure (i.e. logo_white.svg) from ./public +const Header = () => { + const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) + const user = useSelector((state) => state.auth.user) + + return ( + Falling Fruit logo + setIsMobileMenuOpen(!isMobileMenuOpen)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + setIsMobileMenuOpen(!isMobileMenuOpen) + } + }} + aria-label="Toggle menu" + aria-expanded={isMobileMenuOpen} + > + {isMobileMenuOpen ? : } + )