Skip to content

Commit

Permalink
Merge pull request #1337 from nextstrain/feat/web-ui-tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-aksamentov authored Dec 13, 2023
2 parents b153442 + 0e7ed19 commit 2a2fa48
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function CitationButton() {
return (
<>
<ButtonCitationBase type="button" color="link" onClick={open} title={text}>
<span className="d-none d-xl-inline">{text}</span>
{text}
</ButtonCitationBase>

<Modal centered isOpen={showCitation} toggle={toggleOpen} fade={false} size="lg">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ export const FilePickerHeader = styled.div`
`

export const FilePickerBody = styled.div<{ $compact?: boolean }>`
flex: 1 0;
display: flex;
flex-direction: column;
width: 100%;
min-height: ${(props) => !props.$compact && props.theme.filePicker.minHeight};
`

export const FilePickerTitle = styled.h4`
flex: 1;
flex: 1 0;
padding-top: 0.75rem;
margin: auto 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export function LanguageSwitcher({ ...restProps }: LanguageSwitcherProps) {
}, [searchTerm])

return (
<Dropdown isOpen={dropdownOpen} toggle={toggle} {...restProps}>
<DropdownToggle nav caret>
<Dropdown inNavbar nav direction="left" isOpen={dropdownOpen} toggle={toggle} {...restProps}>
<DropdownToggle nav>
<LabelShort locale={currentLocale} />
</DropdownToggle>
<DropdownMenu>
Expand Down Expand Up @@ -95,6 +95,7 @@ const LabelShortText = styled.span`
`

const Dropdown = styled(DropdownBase)`
display: block !important;
margin: 0 !important;
`

Expand All @@ -105,12 +106,16 @@ const DropdownToggle = styled(DropdownToggleBase)`
`

const DropdownMenu = styled(DropdownMenuBase)`
position: absolute !important;
right: 0 !important;
top: 20px !important;
background-color: ${(props) => props.theme.bodyBg};
box-shadow: 1px 1px 20px 0 #0005;
transition: opacity ease-out 0.25s;
padding: 1rem;
padding-right: 0;
min-width: 275px;
width: 275px;
`

const DropdownItem = styled(DropdownItemBase)`
Expand Down
55 changes: 42 additions & 13 deletions packages_rs/nextclade-web/src/components/Layout/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@ import {
NavItem as NavItemBase,
} from 'reactstrap'
import { useRecoilValue } from 'recoil'
import styled, { useTheme } from 'styled-components'
import { BsCaretRightFill as ArrowRight } from 'react-icons/bs'
import { Link } from 'src/components/Link/Link'
import { FaDocker, FaGithub, FaXTwitter, FaDiscourse } from 'react-icons/fa6'
import { NavigationMenu } from 'src/components/Layout/NavigationMenu'
import { Link } from 'src/components/Link/Link'
import { LinkSmart } from 'src/components/Link/LinkSmart'
import { ResultsStatus } from 'src/components/Results/ResultsStatus'
import { PROJECT_NAME } from 'src/constants'
import { canDownloadAtom, hasRanAtom, hasTreeAtom } from 'src/state/results.state'
import styled, { useTheme } from 'styled-components'
import { useTranslationSafe } from 'src/helpers/useTranslationSafe'
import BrandLogoBase from 'src/assets/img/nextclade_logo.svg'
import { CitationButton } from 'src/components/Citation/CitationButton'
import { NextcladeTextLogo } from 'src/components/Layout/NextcladeTextLogo'
import { LanguageSwitcher } from './LanguageSwitcher'
import { LanguageSwitcher } from 'src/components/Layout/LanguageSwitcher'

const LOGO_SIZE = 36

Expand All @@ -34,7 +35,6 @@ export const Navbar = styled(NavbarBase)`
export const Nav = styled(NavBase)`
display: flex;
padding: 0 !important;
margin: 0 !important;
`

const NavbarBrand = styled(NavbarBrandBase)`
Expand All @@ -49,10 +49,11 @@ const BrandLogo = styled(BrandLogoBase)`
height: ${LOGO_SIZE}px;
padding: 0 !important;
margin-left: 0.5rem;
margin-right: 1rem;
`

const BrandText = styled(NextcladeTextLogo)`
margin-left: 1rem;
margin: auto 0;
margin-right: 1rem;
`

Expand All @@ -69,8 +70,9 @@ export const NavLinkLocalStyle = styled(LinkSmart)<{ $active: boolean; disabled?
`

export const NavItemBreadcrumb = styled(NavItem)<{ $active: boolean; disabled?: boolean }>`
display: flex;
min-width: 90px;
padding: 3px 0;
min-height: 35px;
background: ${(props) =>
props.$active ? props.theme.primary : props.disabled ? props.theme.gray250 : props.theme.gray150};
text-align: center;
Expand All @@ -79,9 +81,23 @@ export const NavItemBreadcrumb = styled(NavItem)<{ $active: boolean; disabled?:
`

export const NavLinkBreadcrumbStyle = styled(NavLinkLocalStyle)<{ $active: boolean; disabled?: boolean }>`
display: block;
text-decoration: none !important;
color: ${({ $active, disabled, theme }) => (disabled ? theme.gray500 : $active ? theme.white : theme.bodyColor)};
width: 100%;
height: 100%;
max-width: 80px;
padding: 0 5px;
margin: auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
:hover {
color: ${({ $active, disabled, theme }) => (disabled ? theme.gray500 : $active ? theme.white : theme.bodyColor)};
}
Expand Down Expand Up @@ -191,6 +207,13 @@ export function NavigationBar() {
title: t('{{project}} documentation', { project: 'Nextclade CLI' }),
content: 'CLI',
},
].map((desc) => {
return <NavLinkImpl key={desc.title} desc={desc} active={pathname === desc.url} />
})
}, [pathname, t])

const linksSocial = useMemo(() => {
return [
{
url: 'https://twitter.com/nextstrain',
title: t('Link to our X.com (Twitter)'),
Expand All @@ -211,10 +234,6 @@ export function NavigationBar() {
title: t('Link to our GitHub page'),
content: <FaGithub size={20} color="#aaa" className="mb-1" />,
},
{
title: t('Change language'),
component: <LanguageSwitcher className="px-2" />,
},
].map((desc) => {
return <NavLinkImpl key={desc.title} desc={desc} active={pathname === desc.url} />
})
Expand All @@ -225,15 +244,25 @@ export function NavigationBar() {
<Nav>
<NavbarBrand tag={Link} href="/">
<BrandLogo />
<BrandText />
<BrandText className="d-none d-md-block" />
</NavbarBrand>

{linksLeft}
</Nav>

<ResultsStatus />
<ResultsStatus className="d-none d-md-inline-flex" />

<Nav className="ml-auto d-none d-xl-inline-flex">{linksRight}</Nav>

<Nav className="d-none d-xl-inline-flex">{linksSocial}</Nav>

<Nav className="ml-auto">{linksRight}</Nav>
<Nav title={t('Change language')} className="ml-auto ml-xl-0">
<LanguageSwitcher className="px-2" />
</Nav>

<Nav className="d-xl-none">
<NavigationMenu links={linksRight} className="pb-1" />
</Nav>
</Navbar>
)
}
Expand Down
59 changes: 59 additions & 0 deletions packages_rs/nextclade-web/src/components/Layout/NavigationMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { ReactNode, useCallback, useState } from 'react'
import {
Dropdown as DropdownBase,
DropdownToggle as DropdownToggleBase,
DropdownMenu as DropdownMenuBase,
DropdownProps,
} from 'reactstrap'
import styled from 'styled-components'
import { MdOutlineMenu } from 'react-icons/md'

export interface NavigationMenuProps extends DropdownProps {
links: ReactNode[]
}

export function NavigationMenu({ links, ...restProps }: NavigationMenuProps) {
const [dropdownOpen, setDropdownOpen] = useState(false)
const toggle = useCallback(() => setDropdownOpen((prevState) => !prevState), [])

return (
<Dropdown inNavbar nav direction="left" isOpen={dropdownOpen} toggle={toggle} {...restProps}>
<DropdownToggle nav>
<MdOutlineMenu size={30} />
</DropdownToggle>
<DropdownMenu>
<DropdownMenuListWrapper>{links}</DropdownMenuListWrapper>
</DropdownMenu>
</Dropdown>
)
}

const Dropdown = styled(DropdownBase)`
display: block !important;
margin: 0 !important;
`

const DropdownToggle = styled(DropdownToggleBase)`
color: ${(props) => props.theme.bodyColor};
padding: 2px;
margin: 0;
`

const DropdownMenu = styled(DropdownMenuBase)`
position: absolute !important;
right: 0 !important;
top: 20px !important;
background-color: ${(props) => props.theme.bodyBg};
box-shadow: 1px 1px 20px 0 #0005;
transition: opacity ease-out 0.25s;
padding: 1rem;
padding-right: 0;
width: 200px;
`

const DropdownMenuListWrapper = styled.div`
max-height: calc(80vh - 150px);
min-height: 100px;
overflow-y: auto;
`
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,4 @@ export function QuerySequenceFilePicker() {
const Container = styled.div`
display: flex;
flex-direction: column;
overflow: hidden;
`
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useCallback, useMemo } from 'react'
import { Button } from 'reactstrap'
import styled, { useTheme } from 'styled-components'
import { ImCross } from 'react-icons/im'
import { BsChevronLeft } from 'react-icons/bs'
import { AlgorithmInput } from 'src/types'
import { useQuerySeqInputs } from 'src/state/inputs.state'
import { useTranslationSafe } from 'src/helpers/useTranslationSafe'
Expand All @@ -22,8 +23,18 @@ export function QuerySequenceList({ toMainPage }: { toMainPage?: () => void }) {

const headerText = useMemo(() => {
if (qryInputs.length === 0) {
return null
return (
<div className="d-flex flex-1 mr-auto">
{toMainPage && (
<Button className="" color="secondary" onClick={toMainPage} title={t('Go to main page to add input files')}>
<BsChevronLeft className="mr-1" />
{t('Add data')}
</Button>
)}
</div>
)
}

return (
<div className="d-flex mt-3">
<h4>{t("Sequence data you've added")}</h4>
Expand All @@ -48,18 +59,21 @@ export function QuerySequenceList({ toMainPage }: { toMainPage?: () => void }) {
)
}, [clearQryInputs, qryInputs.length, t, toMainPage])

if (qryInputs.length === 0) {
return null
}

return (
<>
{headerText}
<ContainerMain>
<div>{headerText}</div>
<Ul>{listItems}</Ul>
</>
</ContainerMain>
)
}

const ContainerMain = styled.div`
display: flex;
flex-direction: column;
overflow: hidden;
padding: 3px;
`

const Ul = styled(UlGeneric)`
flex: 1;
overflow: auto;
Expand All @@ -75,7 +89,6 @@ export const InputName = styled.p`
flex: 1;
margin: auto 5px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const ResultsStatusSpinnerWrapper = styled.span`
margin: auto 0;
`

export function ResultsStatus() {
export function ResultsStatus({ ...restProps }) {
const theme = useTheme()

const numThreads = useRecoilValue(numThreadsAtom)
Expand Down Expand Up @@ -89,7 +89,7 @@ export function ResultsStatus() {

return (
<>
<ResultsStatusWrapper id="results-status" onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
<ResultsStatusWrapper id="results-status" onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} {...restProps}>
<ResultsStatusSpinnerWrapper>{spinner}</ResultsStatusSpinnerWrapper>
<ResultsStatusText className="ml-2">{text}</ResultsStatusText>
</ResultsStatusWrapper>
Expand Down

1 comment on commit 2a2fa48

@vercel
Copy link

@vercel vercel bot commented on 2a2fa48 Dec 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nextclade – ./

nextclade-nextstrain.vercel.app
nextclade-git-master-nextstrain.vercel.app
nextclade.vercel.app

Please sign in to comment.