Skip to content

Commit c10f2f9

Browse files
docs: add slugify to select tab framework (#11951)
* feat: add slugify to select tab framework * chore: improve code --------- Co-authored-by: Balázs Orbán <[email protected]>
1 parent 80a2c14 commit c10f2f9

1 file changed

Lines changed: 37 additions & 24 deletions

File tree

docs/components/Code/index.tsx

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import { useSearchParams } from "next/navigation"
12
import { useRouter } from "next/router"
23
import { useThemeConfig } from "nextra-theme-docs"
34
import { Tabs } from "nextra/components"
4-
import React, { Children, useEffect, useState } from "react"
5+
import React, { Children, useEffect, MouseEvent } from "react"
56

67
interface ChildrenProps {
78
children: React.ReactNode
@@ -33,18 +34,20 @@ const allFrameworks = {
3334
[ExpressCode.name]: "Express",
3435
}
3536

36-
const findTabIndex = (frameworks: Record<string, string>, tab: string) => {
37-
// TODO: Slugify instead of matching on indexes
38-
return Object.values(frameworks).findIndex(
39-
(f) => f.toLowerCase() === tab.toLowerCase()
40-
)
37+
/**
38+
* Replace all non-alphabetic characters with a hyphen
39+
*
40+
* @param url - URL to parse
41+
* @returns - A string parsed from the URL
42+
*/
43+
const parseParams = (url: string): string => {
44+
let parsedUrl = url.toLowerCase().replaceAll(/[^a-zA-z]+/g, "-")
45+
return parsedUrl.endsWith("-") ? parsedUrl.slice(0, -1) : parsedUrl
4146
}
4247

4348
export function Code({ children }: ChildrenProps) {
4449
const router = useRouter()
45-
const {
46-
query: { framework },
47-
} = router
50+
const searchParams = useSearchParams()
4851
const childs = Children.toArray(children)
4952
const { project } = useThemeConfig()
5053

@@ -54,29 +57,39 @@ export function Code({ children }: ChildrenProps) {
5457
)
5558

5659
const renderedFrameworks = withNextJsPages ? allFrameworks : baseFrameworks
57-
const [tabIndex, setTabIndex] = useState(0)
60+
61+
const updateFrameworkStorage = (value: string): void => {
62+
const params = new URLSearchParams(searchParams?.toString())
63+
params.set("framework", value)
64+
router.push(`${router.pathname}?${params.toString()}`)
65+
}
66+
67+
const handleClickFramework = (event: MouseEvent<HTMLDivElement>) => {
68+
if (!(event.target instanceof HTMLButtonElement)) return
69+
const { textContent } = event.target as unknown as HTMLDivElement
70+
updateFrameworkStorage(parseParams(textContent!))
71+
}
5872

5973
useEffect(() => {
60-
const savedTabPreference = Number(
61-
window.localStorage.getItem(AUTHJS_TAB_KEY)
62-
)
63-
if (framework) {
64-
window.localStorage.setItem(
65-
AUTHJS_TAB_KEY,
66-
String(findTabIndex(renderedFrameworks, framework as string))
67-
)
68-
setTabIndex(findTabIndex(renderedFrameworks, framework as string))
69-
} else if (savedTabPreference) {
70-
setTabIndex(savedTabPreference)
74+
const length = Object.keys(renderedFrameworks).length
75+
const getFrameworkStorage = window.localStorage.getItem(AUTHJS_TAB_KEY)
76+
const indexFramework = parseInt(getFrameworkStorage ?? "0") % length
77+
if (!getFrameworkStorage) {
78+
window.localStorage.setItem(AUTHJS_TAB_KEY, "0")
7179
}
72-
}, [framework, renderedFrameworks])
80+
updateFrameworkStorage(
81+
parseParams(Object.values(renderedFrameworks)[indexFramework])
82+
)
83+
}, [router.pathname, renderedFrameworks])
7384

7485
return (
75-
<div className="[&_div[role='tablist']]:!pb-0">
86+
<div
87+
className="[&_div[role='tablist']]:!pb-0"
88+
onClick={handleClickFramework}
89+
>
7690
<Tabs
7791
storageKey={AUTHJS_TAB_KEY}
7892
items={Object.values(renderedFrameworks)}
79-
selectedIndex={tabIndex}
8093
>
8194
{Object.keys(renderedFrameworks).map((f) => {
8295
// @ts-expect-error: Hacky dynamic child wrangling

0 commit comments

Comments
 (0)