Skip to content

Commit

Permalink
Picker improvements (github#21765)
Browse files Browse the repository at this point in the history
* close Language and ArticleVersion pickers after click

* cleanup ArticleGridLayout due to VersionPicker changes

* fix tsc errors resulting from primer upgrade

* fix / update tests

* cleanup mobile pickers visual consistency

* use btn-sm on VersionPicker

* update translation and close on click for enterprise releases

Co-authored-by: Kevin Heis <[email protected]>
  • Loading branch information
mikesurowiec and heiskr authored Sep 30, 2021
1 parent b9d3257 commit d81f51e
Show file tree
Hide file tree
Showing 22 changed files with 465 additions and 653 deletions.
2 changes: 1 addition & 1 deletion components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function Link(props: Props) {
}

return (
<NextLink href={href || ''} locale={locale || false}>
<NextLink href={locale ? `/${locale}${href}` : href || ''} locale={locale || false}>
{/* eslint-disable-next-line jsx-a11y/anchor-has-content */}
<a rel={isExternal ? 'noopener' : ''} {...restProps} />
</NextLink>
Expand Down
2 changes: 1 addition & 1 deletion components/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export function Search({
)}
>
{results.length > 0 ? (
<ol data-testid="search-results" className="d-block mt-2">
<ol data-testid="search-results" className="d-block mt-4">
{results.map(({ url, breadcrumbs, heading, title, content }, index) => {
const isActive = index === activeHit
return (
Expand Down
126 changes: 126 additions & 0 deletions components/VersionPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { useRouter } from 'next/router'
import cx from 'classnames'
import { Dropdown, Heading, Details, Box, Text, useDetails } from '@primer/components'
import { ArrowRightIcon, ChevronDownIcon } from '@primer/octicons-react'

import { Link } from 'components/Link'
import { useMainContext } from 'components/context/MainContext'
import { useVersion } from 'components/hooks/useVersion'
import { useTranslation } from 'components/hooks/useTranslation'

type Props = {
hideLabel?: boolean
variant?: 'default' | 'compact' | 'inline'
popoverVariant?: 'inline' | 'dropdown'
}
export const VersionPicker = ({ variant = 'default', popoverVariant, hideLabel }: Props) => {
const router = useRouter()
const { currentVersion } = useVersion()
const { allVersions, page, enterpriseServerVersions } = useMainContext()
const { getDetailsProps, setOpen } = useDetails({ closeOnOutsideClick: true })
const { t } = useTranslation('pages')

if (page.permalinks && page.permalinks.length <= 1) {
return null
}

return (
<>
{!hideLabel && (
<Heading as="span" fontSize={1} className="d-none d-xl-inline-block mb-1">
{t('article_version')}
</Heading>
)}
<div>
<Details
{...getDetailsProps()}
className={cx(
'position-relative details-reset',
variant === 'inline' ? 'd-block' : 'd-inline-block'
)}
data-testid="article-version-picker"
>
{(variant === 'compact' || variant === 'inline') && (
<summary
className="d-block btn btn-invisible color-text-primary"
aria-haspopup="true"
aria-label="Toggle version list"
>
{variant === 'inline' ? (
<div className="d-flex flex-items-center flex-justify-between">
<Text>{allVersions[currentVersion].versionTitle}</Text>
<ChevronDownIcon size={24} className="arrow ml-md-1" />
</div>
) : (
<>
<Text>{allVersions[currentVersion].versionTitle}</Text>
<Dropdown.Caret />
</>
)}
</summary>
)}

{variant === 'default' && (
<summary aria-haspopup="true" className="btn btn-sm">
<Text>{allVersions[currentVersion].versionTitle}</Text>
<Dropdown.Caret />
</summary>
)}

{popoverVariant === 'inline' ? (
<Box py="2">
{(page.permalinks || []).map((permalink) => {
return (
<Dropdown.Item key={permalink.href} onClick={() => setOpen(false)}>
<Link href={permalink.href}>{permalink.pageVersionTitle}</Link>
</Dropdown.Item>
)
})}
<Box mt={1}>
<Link
onClick={() => {
setOpen(false)
}}
href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}
className="f6 no-underline color-text-tertiary pl-3 pr-2 no-wrap"
>
{t('all_enterprise_releases')}{' '}
<ArrowRightIcon verticalAlign="middle" size={15} className="mr-2" />
</Link>
</Box>
</Box>
) : (
<Dropdown.Menu direction="sw" style={{ width: 'unset' }}>
{(page.permalinks || []).map((permalink) => {
return (
<Dropdown.Item key={permalink.href} onClick={() => setOpen(false)}>
<Link href={permalink.href}>{permalink.pageVersionTitle}</Link>
</Dropdown.Item>
)
})}
<Box
borderColor="border.default"
borderTopWidth={1}
borderTopStyle="solid"
mt={2}
pt={2}
pb={1}
>
<Link
onClick={() => {
setOpen(false)
}}
href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}
className="f6 no-underline color-text-tertiary pl-3 pr-2 no-wrap"
>
{t('all_enterprise_releases')}{' '}
<ArrowRightIcon verticalAlign="middle" size={15} className="mr-2" />
</Link>
</Box>
</Dropdown.Menu>
)}
</Details>
</div>
</>
)
}
44 changes: 0 additions & 44 deletions components/article/ArticleGridLayout.module.scss

This file was deleted.

80 changes: 64 additions & 16 deletions components/article/ArticleGridLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,78 @@
import React from 'react'
import cx from 'classnames'
import styles from './ArticleGridLayout.module.scss'
import styled from 'styled-components'
import { Box, themeGet } from '@primer/components'

type Props = {
head?: React.ReactNode
intro?: React.ReactNode
topperSidebar?: React.ReactNode
topper?: React.ReactNode
toc?: React.ReactNode
children?: React.ReactNode
className?: string
}
export const ArticleGridLayout = ({ head, toc, children, className }: Props) => {
export const ArticleGridLayout = ({
intro,
topperSidebar,
topper,
toc,
children,
className,
}: Props) => {
return (
<div className={cx(styles.container, className)}>
{/* head */}
{head && <div className={styles.head}>{head}</div>}

{/* toc */}
<Container className={className}>
{topper && <Box gridArea="topper">{topper}</Box>}
{topperSidebar && <Box gridArea="topper-sidebar">{topperSidebar}</Box>}
{toc && (
<div className={cx(styles.sidebar, 'border-bottom border-xl-0 pb-4 mb-5 pb-xl-0 mb-xl-0')}>
<div className={styles.sidebarContent}>{toc}</div>
</div>
<SidebarContent
gridArea="sidebar"
alignSelf="flex-start"
className="border-bottom border-xl-0 pb-4 mb-5 pb-xl-0 mb-xl-0"
>
{toc}
</SidebarContent>
)}

{/* content */}
<div data-search="article-body" className={styles.content}>
{intro && <Box gridArea="intro">{intro}</Box>}

<Box gridArea="content" data-search="article-body">
{children}
</div>
</div>
</Box>
</Container>
)
}

const Container = styled(Box)`
max-width: 720px;
display: grid;
grid-template-areas:
'topper'
'topper-sidebar'
'intro'
'sidebar'
'content';
row-gap: ${themeGet('space.2')};
@media (min-width: ${themeGet('breakpoints.3')}) {
max-width: none;
grid-template-rows: auto 1fr;
grid-template-columns: minmax(500px, 720px) minmax(220px, 1fr);
grid-template-areas:
'topper topper-sidebar'
'intro sidebar'
'content sidebar';
column-gap: ${themeGet('space.9')};
row-gap: 0;
}
`

const SidebarContent = styled(Box)`
@media (min-width: ${themeGet('breakpoints.3')}) {
position: sticky;
padding-top: ${themeGet('space.4')};
top: 0;
max-height: calc(100vh - ${themeGet('space.4')});
overflow-y: auto;
padding-bottom: ${themeGet('space.4')};
}
`
17 changes: 9 additions & 8 deletions components/article/ArticlePage.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { useRouter } from 'next/router'
import cx from 'classnames'
import { Heading } from '@primer/components'

import { ZapIcon, InfoIcon } from '@primer/octicons-react'
import { Callout } from 'components/ui/Callout'

import { Link } from 'components/Link'
import { DefaultLayout } from 'components/DefaultLayout'
import { ArticleTopper } from 'components/article/ArticleTopper'
import { ArticleTitle } from 'components/article/ArticleTitle'
import { useArticleContext } from 'components/context/ArticleContext'
import { useTranslation } from 'components/hooks/useTranslation'
import { LearningTrackNav } from './LearningTrackNav'
import { MarkdownContent } from 'components/ui/MarkdownContent'
import { Lead } from 'components/ui/Lead'
import { ArticleGridLayout } from './ArticleGridLayout'
import { VersionPicker } from 'components/VersionPicker'
import { Breadcrumbs } from 'components/Breadcrumbs'

// Mapping of a "normal" article to it's interactive counterpart
const interactiveAlternatives: Record<string, { href: string }> = {
Expand Down Expand Up @@ -44,12 +46,11 @@ export const ArticlePage = () => {

return (
<DefaultLayout>
<div className="container-xl px-3 px-md-6 my-4 my-lg-4">
<ArticleTopper />

<div className="container-xl px-3 px-md-6 my-4">
<ArticleGridLayout
className="mt-7"
head={
topper={<Breadcrumbs />}
topperSidebar={<VersionPicker />}
intro={
<>
<ArticleTitle>{title}</ArticleTitle>

Expand Down Expand Up @@ -124,11 +125,11 @@ export const ArticlePage = () => {
)}
{miniTocItems.length > 1 && (
<>
<h2 id="in-this-article" className="f5 mb-2">
<Heading as="h2" fontSize={1} id="in-this-article" className="mb-1">
<a className="Link--primary" href="#in-this-article">
{t('miniToc')}
</a>
</h2>
</Heading>
<ul className="list-style-none pl-0 f5 mb-0">
{miniTocItems.map((item) => {
return (
Expand Down
2 changes: 1 addition & 1 deletion components/article/ArticleTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ type Props = {
export const ArticleTitle = ({ children }: Props) => {
return (
<div className="d-flex flex-items-baseline flex-justify-between">
<h1 className="my-4 border-bottom-0">{children}</h1>
<h1 className="mt-4 border-bottom-0">{children}</h1>
</div>
)
}
18 changes: 0 additions & 18 deletions components/article/ArticleTopper.tsx

This file was deleted.

Loading

0 comments on commit d81f51e

Please sign in to comment.