Skip to content

Commit

Permalink
Picker refactor (github#33113)
Browse files Browse the repository at this point in the history
Co-authored-by: Peter Bengtsson <peterbe@github.com>
  • Loading branch information
gracepark and peterbe authored Dec 7, 2022
1 parent c3f5734 commit baa53b7
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 131 deletions.
11 changes: 5 additions & 6 deletions components/page-header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,15 @@ import styles from './Header.module.scss'
export const Header = () => {
const router = useRouter()
const { error } = useMainContext()
const { allVersions } = useMainContext()
const { currentProduct, allVersions } = useMainContext()
const { currentVersion } = useVersion()
const { t } = useTranslation(['header', 'homepage'])
const isRestPage = currentProduct && currentProduct.id === 'rest'
const [isMenuOpen, setIsMenuOpen] = useState(
router.pathname !== '/' && router.query.query && true
)
const [scroll, setScroll] = useState(false)

const { hasAccount } = useHasAccount()

const signupCTAVisible =
hasAccount === false && // don't show if `null`
(currentVersion === DEFAULT_VERSION || currentVersion === 'enterprise-cloud@latest')
Expand Down Expand Up @@ -92,8 +91,8 @@ export const Header = () => {
<Breadcrumbs />
</div>
<div className="d-flex flex-items-center">
<VersionPicker />
<LanguagePicker />
<VersionPicker variant="header" />
<LanguagePicker variant="header" />

{signupCTAVisible && (
<a
Expand Down Expand Up @@ -161,7 +160,7 @@ export const Header = () => {
<div className="border-top my-2" />
<LanguagePicker variant="inline" />

{allVersions[currentVersion].apiVersions.length > 0 && (
{isRestPage && allVersions[currentVersion].apiVersions.length > 0 && (
<ApiVersionPicker variant="inline" />
)}

Expand Down
19 changes: 13 additions & 6 deletions components/page-header/LanguagePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useRouter } from 'next/router'
import Cookies from 'js-cookie'

import { useLanguages } from 'components/context/LanguagesContext'
import { Picker } from 'components/ui/Picker'
import { useTranslation } from 'components/hooks/useTranslation'
import { Picker } from 'components/ui/Picker'
import { USER_LANGUAGE_COOKIE_NAME } from '../../lib/constants.js'

function rememberPreferredLanguage(value: string) {
Expand Down Expand Up @@ -31,7 +31,7 @@ function rememberPreferredLanguage(value: string) {
}

type Props = {
variant?: 'inline'
variant: 'inline' | 'header'
}

export const LanguagePicker = ({ variant }: Props) => {
Expand Down Expand Up @@ -61,13 +61,20 @@ export const LanguagePicker = ({ variant }: Props) => {
<Picker
variant={variant}
defaultText={t('language_picker_default_text')}
options={langs.map((lang) => ({
items={langs.map((lang) => ({
text: lang.nativeName || lang.name,
selected: lang === selectedLang,
locale: lang.code,
href: `${routerPath}`,
onselect: rememberPreferredLanguage,
href: `/${lang.code}${routerPath}`,
extra: {
locale: lang.code,
},
}))}
onSelect={(item) => {
if (item.extra?.locale) rememberPreferredLanguage(item.extra.locale)
}}
dataTestId="field"
ariaLabel="Select field type"
alignment="center"
/>
</div>
)
Expand Down
22 changes: 19 additions & 3 deletions components/page-header/ProductPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useRouter } from 'next/router'
import { LinkExternalIcon } from '@primer/octicons-react'

import { useMainContext } from 'components/context/MainContext'
import { Picker } from 'components/ui/Picker'
import { useTranslation } from 'components/hooks/useTranslation'
import { Picker } from 'components/ui/Picker'

export const ProductPicker = () => {
const router = useRouter()
Expand All @@ -14,12 +15,27 @@ export const ProductPicker = () => {
<Picker
variant="inline"
defaultText={t('product_picker_default_text')}
options={activeProducts.map((product) => ({
items={activeProducts.map((product) => ({
text: product.name,
selected: product.name === currentProduct?.name,
external: product.external,
href: `${product.external ? '' : `/${router.locale}`}${product.href}`,
extra: {
external: product.external,
},
}))}
alignment="end"
dataTestId="field"
ariaLabel="Select field type"
renderItem={(item) => {
return item.extra?.external ? (
<>
{item.text}
<LinkExternalIcon size="small" className="ml-1" />
</>
) : (
item.text
)
}}
/>
</div>
)
Expand Down
41 changes: 33 additions & 8 deletions components/page-header/VersionPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useRouter } from 'next/router'
import { ArrowRightIcon, InfoIcon } from '@primer/octicons-react'

import { useMainContext } from 'components/context/MainContext'
import { DEFAULT_VERSION, useVersion } from 'components/hooks/useVersion'
import { useTranslation } from 'components/hooks/useTranslation'
import { Picker } from 'components/ui/Picker'

type Props = {
variant?: 'inline'
variant: 'inline' | 'header'
}

export const VersionPicker = ({ variant }: Props) => {
Expand All @@ -23,8 +24,10 @@ export const VersionPicker = ({ variant }: Props) => {
text: allVersions[permalink.pageVersion].versionTitle,
selected: currentVersion === permalink.pageVersion,
href: permalink.href,
arrow: false,
info: false,
extra: {
arrow: false,
info: false,
},
}))

const hasEnterpriseVersions = (page.permalinks || []).some((permalink) =>
Expand All @@ -35,9 +38,11 @@ export const VersionPicker = ({ variant }: Props) => {
allLinks.push({
text: t('all_enterprise_releases'),
selected: false,
arrow: true,
href: `/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`,
info: false,
extra: {
arrow: true,
info: false,
},
})
}

Expand All @@ -47,15 +52,35 @@ export const VersionPicker = ({ variant }: Props) => {
allLinks.push({
text: t('about_versions'),
selected: false,
arrow: false,
info: true,
href: `/${router.locale}${currentVersionPathSegment}/get-started/learning-about-github/about-versions-of-github-docs`,
extra: {
arrow: false,
info: true,
},
})
}

return (
<div data-testid="version-picker">
<Picker variant={variant} defaultText={t('version_picker_default_text')} options={allLinks} />
<Picker
variant={variant}
defaultText={t('version_picker_default_text')}
items={allLinks}
alignment="end"
dataTestId="field"
ariaLabel="Select field type"
renderItem={(item) => {
return (
<div className={item.extra?.arrow || item.extra?.info ? 'f6' : undefined}>
{item.text}
{item.extra?.arrow && (
<ArrowRightIcon verticalAlign="middle" size={15} className="ml-1" />
)}
{item.extra?.info && <InfoIcon verticalAlign="middle" size={15} className="ml-1" />}
</div>
)
}}
/>
</div>
)
}
36 changes: 29 additions & 7 deletions components/sidebar/ApiVersionPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useRouter } from 'next/router'
import cx from 'classnames'
import Cookies from 'js-cookie'
import { InfoIcon } from '@primer/octicons-react'

import { useMainContext } from 'components/context/MainContext'
import { DEFAULT_VERSION, useVersion } from 'components/hooks/useVersion'
Expand All @@ -13,7 +14,7 @@ import styles from './SidebarProduct.module.scss'
const API_VERSION_SUFFIX = ' (latest)'

type Props = {
variant?: 'inline'
variant: 'inline' | 'header'
width?: number
}

Expand Down Expand Up @@ -67,19 +68,23 @@ export const ApiVersionPicker = ({ variant, width }: Props) => {
text: dateDisplayText,
selected: router.query.apiVersion === date,
href: itemLink,
info: false,
onselect: rememberApiVersion,
extra: {
info: false,
currentDate,
},
}
})

apiVersionLinks.push({
text: t('rest.versioning.about_versions'),
selected: false,
info: true,
href: `/${router.locale}${
currentVersion === DEFAULT_VERSION ? '' : `/${currentVersion}`
}/rest/overview/api-versions`,
onselect: rememberApiVersion,
extra: {
info: true,
currentDate,
},
})

// This only shows the REST Version picker if it's calendar date versioned
Expand All @@ -99,9 +104,26 @@ export const ApiVersionPicker = ({ variant, width }: Props) => {
<div data-testid="api-version-picker" className="width-full">
<Picker
variant={variant}
apiVersion={true}
defaultText={currentDateDisplayText}
options={apiVersionLinks}
items={apiVersionLinks}
pickerLabel="Version"
alignment="center"
buttonBorder={true}
dataTestId="version"
ariaLabel="Select API Version"
onSelect={(item) => {
if (item.extra?.currentDate) rememberApiVersion(item.extra.currentDate)
}}
renderItem={(item) => {
return item.extra?.info ? (
<div className="f6">
{item.text}
<InfoIcon verticalAlign="middle" size={15} className="ml-1" />
</div>
) : (
item.text
)
}}
/>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/sidebar/SidebarProduct.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const SidebarProduct = () => {
)
return (
<>
<ApiVersionPicker width={sidebarWidth} />
<ApiVersionPicker width={sidebarWidth} variant="header" />
<li className="my-3">
<ul className="list-style-none">
{conceptualPages.map((childPage, i) => {
Expand Down
33 changes: 33 additions & 0 deletions components/ui/Picker/Fields.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ReactNode } from 'react'
import { ActionList } from '@primer/react'

import { PickerItem } from './Picker'
import { Link } from 'components/Link'

export const Fields = (fieldProps: {
open: boolean
setOpen: React.Dispatch<React.SetStateAction<boolean>>
items: PickerItem[]
onSelect?: (item: PickerItem) => void
renderItem?: (item: PickerItem) => ReactNode | string
}) => {
const { open, setOpen, items, onSelect, renderItem } = fieldProps

return (
<ActionList selectionVariant="single">
{items.map((item) => (
<ActionList.LinkItem
as={Link}
key={item.text}
href={item.href}
onClick={() => {
if (onSelect) onSelect(item)
setOpen(!open)
}}
>
{renderItem ? renderItem(item) : item.text}
</ActionList.LinkItem>
))}
</ActionList>
)
}
Loading

0 comments on commit baa53b7

Please sign in to comment.