Skip to content

Commit

Permalink
feat-505: improve navbar layout when resizing the screen
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Füting committed Feb 25, 2025
1 parent e2675b6 commit fb34877
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 104 deletions.
25 changes: 25 additions & 0 deletions web/src/components/Common/NomenclatureSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useRecoilState } from 'recoil'
import React from 'react'
import { styled } from 'styled-components'
import { enablePangolinAtom } from 'src/state/Nomenclature'
import { ToggleTwoLabels } from 'src/components/Common/ToggleTwoLabels'

export function NomenclatureSwitch({ className }: { className?: string }) {
const [enablePangolin, setEnablePangolin] = useRecoilState(enablePangolinAtom)

return (
<NomenclatureToggle
className={className}
identifier="nomenclature-switch"
title="Switch nomenclature"
checked={enablePangolin}
onCheckedChanged={setEnablePangolin}
labelLeft="Pangolin"
labelRight="Nextstrain"
/>
)
}

const NomenclatureToggle = styled(ToggleTwoLabels)`
transform: scale(0.9);
`
4 changes: 2 additions & 2 deletions web/src/components/Layout/LanguageSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { getLocaleWithKey, Locale, localesArray } from 'src/i18n/i18n'

export type LanguageSwitcherProps = DropdownProps

export function LanguageSwitcher({ ...restProps }: LanguageSwitcherProps) {
export function LanguageSwitcher({ className, ...restProps }: LanguageSwitcherProps) {
const [currentLocale, setCurrentLocale] = useRecoilState(localeAtom)
const [dropdownOpen, setDropdownOpen] = useState(false)
const toggle = useCallback(() => setDropdownOpen((prevState) => !prevState), [])
const setLocaleLocal = useCallback((locale: Locale) => () => setCurrentLocale(locale.key), [setCurrentLocale])

return (
<Dropdown className="language-switcher" isOpen={dropdownOpen} toggle={toggle} {...restProps}>
<Dropdown className={`language-switcher ${className}`} isOpen={dropdownOpen} toggle={toggle} {...restProps}>
<DropdownToggle nav caret>
<LanguageSwitcherItem locale={currentLocale} />
</DropdownToggle>
Expand Down
62 changes: 2 additions & 60 deletions web/src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import React, { PropsWithChildren, Suspense } from 'react'
import React, { PropsWithChildren } from 'react'
import { styled } from 'styled-components'
import { Container as ContainerBase, Row, Col } from 'reactstrap'
import Image from 'next/image'
import { ErrorBoundary } from 'react-error-boundary'
import { useRecoilState } from 'recoil'
import { LastUpdated } from '../Common/LastUpdated'
import { NavigationBar } from './NavigationBar'
import { FooterContent } from './Footer'
import GisaidLogoPNG from 'src/assets/images/GISAID_logo.png'
import { ChristmasLightRope, Santa, Snowfall } from 'src/components/Common/Christmas'
import { ChangelogButton } from 'src/components/Common/ChangelogButton'
import { useTranslationSafe } from 'src/helpers/useTranslationSafe'
import { LinkExternal } from 'src/components/Link/LinkExternal'
import { FetchError } from 'src/components/Error/FetchError'
import { ToggleTwoLabels } from 'src/components/Common/ToggleTwoLabels'
import { enablePangolinAtom } from 'src/state/Nomenclature'

export function Layout({ children }: PropsWithChildren<LayoutProps>) {
const { t } = useTranslationSafe()

return (
<Container fluid>
<HeaderRow className={'gx-0'}>
Expand All @@ -28,29 +15,8 @@ export function Layout({ children }: PropsWithChildren<LayoutProps>) {
</HeaderCol>
</HeaderRow>

<Row className="ms-3 mt-2 d-none d-md-block gx-0">
<Col className="d-flex">
<GisaidText className="me-auto d-flex align-items-center gap-1">
{t('Enabled by data from {{ gisaid }}', { gisaid: '' })}
<LinkExternal href="https://www.gisaid.org/" icon={null}>
<Image src={GisaidLogoPNG} alt="GISAID" height={27} width={73} />
</LinkExternal>
</GisaidText>

<NomenclatureSwitch />

<ChangelogButton>
<ErrorBoundary FallbackComponent={FetchError}>
<Suspense>
<LastUpdated />
</Suspense>
</ErrorBoundary>
</ChangelogButton>
</Col>
</Row>

<MainContainer fluid>
<MainRow className={'gx-0 mt-2'}>
<MainRow className={'gx-0 mt-4 mt-md-2'}>
<MainCol>{children}</MainCol>
</MainRow>
</MainContainer>
Expand All @@ -67,22 +33,6 @@ export function Layout({ children }: PropsWithChildren<LayoutProps>) {
)
}

function NomenclatureSwitch({ className }: { className?: string }) {
const [enablePangolin, setEnablePangolin] = useRecoilState(enablePangolinAtom)

return (
<NomenclatureToggle
className={className}
identifier="nomenclature-switch"
title="Switch nomenclature"
checked={enablePangolin}
onCheckedChanged={setEnablePangolin}
labelLeft="Pangolin"
labelRight="Nextstrain"
/>
)
}

const Container = styled(ContainerBase)`
min-height: 100%;
width: 100%;
Expand Down Expand Up @@ -127,14 +77,6 @@ const FooterCol = styled(Col)`
padding: 0;
`

const GisaidText = styled.small`
font-size: 0.9rem;
`

export interface LayoutProps {
wide?: boolean
}

const NomenclatureToggle = styled(ToggleTwoLabels)`
transform: scale(0.9);
`
124 changes: 82 additions & 42 deletions web/src/components/Layout/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useRouter } from 'next/router'
import React, { useCallback, useMemo, useState } from 'react'
import React, { Suspense, useCallback, useMemo, useState } from 'react'

import { styled } from 'styled-components'
import {
Expand All @@ -15,6 +15,9 @@ import {
import classNames from 'classnames'
import { FaGithub, FaTwitter } from 'react-icons/fa'

import Image from 'next/image'
import { ErrorBoundary } from 'react-error-boundary'
import { NomenclatureSwitch } from '../Common/NomenclatureSwitch'
import BrandLogoBase from 'src/assets/images/logo.svg'
import BrandLogoLargeBase from 'src/assets/images/logo_text_right.svg'

Expand All @@ -24,6 +27,10 @@ import { LinkExternal } from 'src/components/Link/LinkExternal'
import { TWITTER_USERNAME_RAW, URL_GITHUB } from 'src/constants'
import { ChristmasToggle } from 'src/components/Common/Christmas'
import { LanguageSwitcher } from 'src/components/Layout/LanguageSwitcher'
import GisaidLogoPNG from 'src/assets/images/GISAID_logo.png'
import { ChangelogButton } from 'src/components/Common/ChangelogButton'
import { FetchError } from 'src/components/Error/FetchError'
import { LastUpdated } from 'src/components/Common/LastUpdated'

export function matchingUrl(url: string, pathname: string): boolean {
if (pathname.startsWith('/variants')) {
Expand Down Expand Up @@ -164,48 +171,81 @@ export function NavigationBar() {
}, [t])

return (
<Navbar expand="md" color="light" light role="navigation">
<Link href="/">
<BrandLogoLarge className="d-none d-lg-block" />
<BrandLogo className="d-block d-lg-none" />
</Link>

<NavbarToggler onClick={toggle} />

<Collapse isOpen={isOpen} navbar>
<NavWrappable navbar>
{Object.entries(navLinksLeft).map(([url, text]) => {
return (
<NavItem key={url} className={classNames(matchingUrl(url, pathname) && 'active')}>
<NavLink tag={Link} href={url}>
{text}
<>
<Navbar expand="md" color="light" light role="navigation">
<Link href="/">
<BrandLogoLarge className="d-none d-lg-block" />
<BrandLogo className="d-block d-lg-none" />
</Link>

<NavbarToggler onClick={toggle} />

<Collapse isOpen={isOpen} navbar>
<NavWrappable navbar>
{Object.entries(navLinksLeft).map(([url, text]) => {
return (
<NavItem key={url} className={classNames(matchingUrl(url, pathname) && 'active')}>
<NavLink tag={Link} href={url}>
{text}
</NavLink>
</NavItem>
)
})}
</NavWrappable>

<Nav className="ms-auto" navbar>
<NavItem>
<Row className={'gx-0'}>
<Col className="mt-2 mx-3">
<ChristmasToggle />
</Col>
</Row>
</NavItem>
{navLinksRight.map(({ text, title, url, alt, icon }) => (
<NavItem key={title}>
<NavLink tag={LinkRight} title={title} href={url} alt={alt} icon={null}>
<span>
<span className="me-2">{icon}</span>
<span className="d-inline d-sm-none">{text}</span>
</span>
</NavLink>
</NavItem>
)
})}
</NavWrappable>

<Nav className="ms-auto" navbar>
<NavItem>
<Row className={'gx-0'}>
<Col className="mt-2 mx-3">
<ChristmasToggle />
</Col>
</Row>
</NavItem>
{navLinksRight.map(({ text, title, url, alt, icon }) => (
<NavItem key={title}>
<NavLink tag={LinkRight} title={title} href={url} alt={alt} icon={null}>
<span>
<span className="me-2">{icon}</span>
<span className="d-inline d-sm-none">{text}</span>
</span>
</NavLink>
</NavItem>
))}
<LanguageSwitcher />
</Nav>
</Collapse>
</Navbar>
))}
<LanguageSwitcher className="mx-auto mx-md-0" />
</Nav>
</Collapse>
</Navbar>

{!isOpen && <SubNavigationBar className="d-none d-md-flex mt-2 gx-0 px-3" />}
{isOpen && <SubNavigationBar className="d-flex mt-2 gx-0 px-3" />}
</>
)
}

function SubNavigationBar({ className }: { className?: string }) {
const { t } = useTranslationSafe()
return (
<div className={className}>
<GisaidText className="d-none d-md-flex align-items-center gap-1">
{t('Enabled by data from {{ gisaid }}', { gisaid: '' })}
<LinkExternal href="https://www.gisaid.org/" icon={null}>
<Image src={GisaidLogoPNG} alt="GISAID" height={27} width={73} />
</LinkExternal>
</GisaidText>

<NomenclatureSwitch className="mx-auto mx-md-0 ms-md-auto" />

<ChangelogButton className="d-none d-md-flex">
<ErrorBoundary FallbackComponent={FetchError}>
<Suspense>
<LastUpdated />
</Suspense>
</ErrorBoundary>
</ChangelogButton>
</div>
)
}

const GisaidText = styled.small`
font-size: 0.9rem;
`

0 comments on commit fb34877

Please sign in to comment.