Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 69 additions & 4 deletions website/src/components/VersionBadge/VersionBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,103 @@
'use client'

import { ChangeEvent } from 'react'
import styled from 'styled-components'
import { CARD_STYLES } from '@/utils/card'
import { SPACINGS } from '@/utils/spacings'
import { BORDER_RADIUSES } from '@/utils/border'
import { FONT_SIZES, FONT_WEIGHTS } from '@/utils/font-sizes'
import { COLORS } from '@/utils/theme'
import { usePathname } from 'next/navigation'
import { usePathname, useRouter } from 'next/navigation'
import { getVersionFromPathname } from '@/utils/slug'
import { DOCS_LATEST_VERSION, DOCS_VERSIONS } from '@/utils/global-data'

const VersionBadgeWrapper = styled.div`
${CARD_STYLES};
display: inline-flex;
padding: 0.2rem ${SPACINGS.THREE};
align-items: center;
padding: 0.6rem ${SPACINGS.THREE};
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
padding: 0.6rem ${SPACINGS.THREE};
padding: ${SPACINGS.ONE} ${SPACINGS.THREE};

border-radius: ${BORDER_RADIUSES.SOFT};
font-size: ${FONT_SIZES.COMPLEMENTARY};
color: ${COLORS.TEXT_LOW_CONTRAST};
`

const VersionBadgeKey = styled.span`
const VersionBadgeKey = styled.label`
font-weight: ${FONT_WEIGHTS.SEMI_BOLD};
margin-right: 0.4rem;
`

const VersionSelect = styled.select`
appearance: none;
background: transparent;
border: none;
padding: 0;
width: 100%;
cursor: pointer;
font-weight: ${FONT_WEIGHTS.SEMI_BOLD};
outline: none;

&::-ms-expand {
display: none;
}
`

type PropType = {}

const DOCS_VERSION_SEGMENT_REGEX = /^v\d+$/

function getDocsSubPath(pathname = ''): string[] {
if (!pathname.startsWith('/docs')) return []
const [, ...docsSubPath] = pathname.split('/').filter(Boolean)

return DOCS_VERSION_SEGMENT_REGEX.test(docsSubPath[0] ?? '')
? docsSubPath.slice(1)
: docsSubPath
}
Comment on lines +48 to +55
Copy link
Owner

Choose a reason for hiding this comment

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

An alternative approach is to use a regex like this. There’s no need to change it, though — feel free to choose whichever option you find more readable.

const DOCS_WITH_VERSION_REGEX = /^\/docs(?:\/v\d+)?/

function getDocsSubPath(pathname = ''): string[] {
  if (!pathname.startsWith('/docs')) return []
  return pathname
    .replace(DOCS_WITH_VERSION_REGEX, '')
    .split('/')
    .filter(Boolean)
}


function getVersionPathname(pathname = '', major: number): string {
const versionPrefix = major === DOCS_LATEST_VERSION.MAJOR ? [] : [`v${major}`]
return ['docs', ...versionPrefix, ...getDocsSubPath(pathname)].join('/')
Comment on lines +58 to +59
Copy link
Owner

Choose a reason for hiding this comment

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

We could reuse existing helpers to achieve the same result—see prefixSlugWithDocs() and joinSlugs.

function getVersionPathname(pathname = '', major: number): string {
  const versionPrefix = major === DOCS_LATEST_VERSION.MAJOR ? '' : `v${major}`
  const versionAndSubPath =  joinSlugs(versionPrefix, ...getDocsSubPath(pathname))
  return prefixSlugWithDocs(versionAndSubPath)
}

}

export function VersionBadge(props: PropType) {
const { ...restProps } = props
const router = useRouter()
const pathname = usePathname()
const version = getVersionFromPathname(pathname)

function onVersionChange(event: ChangeEvent<HTMLSelectElement>) {
const major = Number(event.target.value)
const nextPathname = `/${getVersionPathname(pathname, major)}`

if (nextPathname === pathname) return
Copy link
Owner

Choose a reason for hiding this comment

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

Let’s start loading the route here to maintain the strong INP score the website currently has 🙂:

Suggested change
if (nextPathname === pathname) return
if (nextPathname === pathname) return
dispatch(setRoutesLoading(true))

router.push(nextPathname)
}

return (
<VersionBadgeWrapper {...restProps}>
<VersionBadgeKey>Version:</VersionBadgeKey> {version.NAME}
<VersionBadgeKey htmlFor="version">Version:</VersionBadgeKey>

<VersionSelect
aria-label="Select documentation version"
value={String(version.MAJOR)}
name="version"
id="version"
onChange={onVersionChange}
>
{DOCS_VERSIONS.map((docsVersion) => {
const versionLabel = `v${docsVersion.MAJOR}`
const versionSuffix = docsVersion.SUFFIX
? ` (${docsVersion.SUFFIX})`
: ''

return (
<option key={versionLabel} value={docsVersion.MAJOR}>
{versionLabel}
{versionSuffix}
</option>
)
})}
</VersionSelect>
</VersionBadgeWrapper>
)
}
7 changes: 5 additions & 2 deletions website/src/utils/global-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,23 @@ export type VersionType = {
NAME: string
MAJOR: number
SLUG: string
SUFFIX?: string
}

export const DOCS_LATEST_VERSION: VersionType = {
NAME: packageJson.version,
MAJOR: Number(packageJson.version.split('.')[0]),
SLUG: prefixSlugWithDocs('')
SLUG: prefixSlugWithDocs(''),
SUFFIX: 'latest'
}

export const DOCS_VERSIONS: VersionType[] = [
DOCS_LATEST_VERSION,
{
NAME: '8.6.0',
MAJOR: 8,
SLUG: prefixSlugWithDocs('v8')
SLUG: prefixSlugWithDocs('v8'),
SUFFIX: 'stable'
}
]

Expand Down