Skip to content

Commit 5deb8ea

Browse files
authored
docs: support multiple sidebars in a project (medusajs#11768)
* changed to new sidebar across projects except resources * finalize multi sidebar support * clean up * remove redundant property * small changes * fixes * generate * fix error * fix initial open
1 parent 2a0bd86 commit 5deb8ea

File tree

108 files changed

+37343
-36458
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+37343
-36458
lines changed

www/apps/api-reference/app/layout.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ export default function RootLayout({
5858
gaId={process.env.NEXT_PUBLIC_GA_ID}
5959
>
6060
<WideLayout
61-
sidebarProps={{
62-
expandItems: false,
63-
}}
6461
showToc={false}
6562
showBreadcrumbs={false}
6663
ProvidersComponent={Providers}

www/apps/api-reference/components/MDXComponents/H2/index.tsx

+14-6
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
import { useScrollController, useSidebar, H2 as UiH2 } from "docs-ui"
44
import { useEffect, useMemo, useRef, useState } from "react"
55
import getSectionId from "../../../utils/get-section-id"
6-
import { SidebarItem } from "types"
6+
import { Sidebar } from "types"
77

88
type H2Props = React.HTMLAttributes<HTMLHeadingElement>
99

1010
const H2 = ({ children, ...props }: H2Props) => {
1111
const headingRef = useRef<HTMLHeadingElement>(null)
12-
const { activePath, addItems, removeItems } = useSidebar()
12+
const { activePath, addItems, removeItems, shownSidebar } = useSidebar()
1313
const { scrollableElement, scrollToElement } = useScrollController()
1414
const [scrolledFirstTime, setScrolledFirstTime] = useState(false)
1515

@@ -29,20 +29,28 @@ const H2 = ({ children, ...props }: H2Props) => {
2929
}, [scrollableElement, headingRef, id])
3030

3131
useEffect(() => {
32-
const item: SidebarItem[] = [
32+
if (!shownSidebar) {
33+
return
34+
}
35+
const items: Sidebar.SidebarItem[] = [
3336
{
3437
type: "link",
3538
path: `${id}`,
3639
title: children as string,
3740
loaded: true,
3841
},
3942
]
40-
addItems(item)
43+
addItems(items, {
44+
sidebar_id: shownSidebar.sidebar_id,
45+
})
4146

4247
return () => {
43-
removeItems(item)
48+
removeItems({
49+
items,
50+
sidebar_id: shownSidebar.sidebar_id,
51+
})
4452
}
45-
}, [id])
53+
}, [id, shownSidebar?.sidebar_id])
4654

4755
return (
4856
<UiH2 {...props} id={id} passRef={headingRef}>

www/apps/api-reference/components/Tags/Operation/index.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,12 @@ const TagOperation = ({
6060
}, [isBrowser, scrollableElement])
6161

6262
const scrollIntoView = useCallback(() => {
63-
if (!isBrowser) {
63+
if (!isBrowser || !nodeRef.current) {
64+
// repeat timeout
65+
setTimeout(scrollIntoView, 200)
6466
return
6567
}
66-
67-
if (nodeRef.current && !checkElementInViewport(nodeRef.current, 0)) {
68+
if (!checkElementInViewport(nodeRef.current, 0)) {
6869
const elm = nodeRef.current as HTMLElement
6970
scrollToTop(
7071
elm.offsetTop + (elm.offsetParent as HTMLElement)?.offsetTop,

www/apps/api-reference/components/Tags/Paths/index.tsx

+23-15
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
11
"use client"
22

3-
import type { OpenAPIV3 } from "openapi-types"
4-
import type { Operation, PathsObject } from "@/types/openapi"
5-
import { useSidebar } from "docs-ui"
3+
import type { Operation, PathsObject, TagObject } from "@/types/openapi"
4+
import { findSidebarItem, useSidebar } from "docs-ui"
65
import { Fragment, Suspense, useEffect } from "react"
76
import dynamic from "next/dynamic"
87
import type { TagOperationProps } from "../Operation"
98
import clsx from "clsx"
109
import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items"
1110
import { useLoading } from "@/providers/loading"
1211
import DividedLoading from "@/components/DividedLoading"
13-
import { SidebarItemSections, SidebarItem, SidebarItemCategory } from "types"
12+
import { Sidebar } from "types"
1413

1514
const TagOperation = dynamic<TagOperationProps>(
1615
async () => import("../Operation")
1716
) as React.FC<TagOperationProps>
1817

1918
export type TagPathsProps = {
20-
tag: OpenAPIV3.TagObject
19+
tag: TagObject
2120
paths: PathsObject
2221
} & React.HTMLAttributes<HTMLDivElement>
2322

2423
const TagPaths = ({ tag, className, paths }: TagPathsProps) => {
25-
const { items, addItems, findItemInSection } = useSidebar()
24+
const { shownSidebar, addItems } = useSidebar()
2625
const { loading } = useLoading()
2726

2827
useEffect(() => {
28+
if (!shownSidebar) {
29+
return
30+
}
31+
2932
if (paths) {
30-
const parentItem = findItemInSection(
31-
items[SidebarItemSections.DEFAULT],
32-
{ title: tag.name },
33-
false
34-
) as SidebarItemCategory
35-
const pathItems: SidebarItem[] = getTagChildSidebarItems(paths)
36-
if ((parentItem?.children?.length || 0) < pathItems.length) {
33+
const parentItem = findSidebarItem({
34+
sidebarItems:
35+
"items" in shownSidebar
36+
? shownSidebar.items
37+
: shownSidebar.children || [],
38+
item: { title: tag.name, type: "category" },
39+
checkChildren: false,
40+
}) as Sidebar.SidebarItemCategory
41+
const pathItems: Sidebar.SidebarItem[] = getTagChildSidebarItems(paths)
42+
const targetLength =
43+
pathItems.length + (tag["x-associatedSchema"] ? 1 : 0)
44+
if ((parentItem.children?.length || 0) < targetLength) {
3745
addItems(pathItems, {
38-
section: SidebarItemSections.DEFAULT,
46+
sidebar_id: shownSidebar.sidebar_id,
3947
parent: {
4048
type: "category",
4149
title: tag.name,
@@ -46,7 +54,7 @@ const TagPaths = ({ tag, className, paths }: TagPathsProps) => {
4654
}
4755
}
4856
// eslint-disable-next-line react-hooks/exhaustive-deps
49-
}, [paths])
57+
}, [paths, shownSidebar?.sidebar_id])
5058

5159
return (
5260
<Suspense>

www/apps/api-reference/components/Tags/Section/Schema/index.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client"
22

3-
import { Suspense, useEffect, useMemo, useRef } from "react"
3+
import { Suspense, useEffect, useMemo } from "react"
44
import { SchemaObject } from "../../../../types/openapi"
55
import TagOperationParameters from "../../Operation/Parameters"
66
import {
@@ -13,7 +13,6 @@ import {
1313
useScrollController,
1414
useSidebar,
1515
} from "docs-ui"
16-
import { SidebarItemSections } from "types"
1716
import getSectionId from "../../../../utils/get-section-id"
1817
import DividedLayout from "../../../../layouts/Divided"
1918
import SectionContainer from "../../../Section/Container"
@@ -30,7 +29,7 @@ export type TagSectionSchemaProps = {
3029
}
3130

3231
const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
33-
const { addItems, setActivePath, activePath } = useSidebar()
32+
const { addItems, setActivePath, activePath, shownSidebar } = useSidebar()
3433
const { displayedArea } = useArea()
3534
const formattedName = useMemo(
3635
() => singular(tagName).replaceAll(" ", ""),
@@ -58,6 +57,9 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
5857
}, [isBrowser, scrollableElement])
5958

6059
useEffect(() => {
60+
if (!shownSidebar) {
61+
return
62+
}
6163
addItems(
6264
[
6365
{
@@ -69,7 +71,7 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
6971
},
7072
],
7173
{
72-
section: SidebarItemSections.DEFAULT,
74+
sidebar_id: shownSidebar.sidebar_id,
7375
parent: {
7476
type: "category",
7577
title: tagName,
@@ -80,7 +82,7 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
8082
}
8183
)
8284
// eslint-disable-next-line react-hooks/exhaustive-deps
83-
}, [formattedName])
85+
}, [formattedName, shownSidebar?.sidebar_id])
8486

8587
useEffect(() => {
8688
if (!isBrowser) {

www/apps/api-reference/components/Tags/Section/index.tsx

+14-13
Original file line numberDiff line numberDiff line change
@@ -85,23 +85,24 @@ const TagSectionComponent = ({ tag }: TagSectionProps) => {
8585
)
8686

8787
useEffect(() => {
88-
if (!isBrowser) {
88+
if (!isBrowser || !activePath || !activePath.includes(slugTagName)) {
8989
return
9090
}
9191

92-
if (activePath && activePath.includes(slugTagName)) {
93-
const tagName = activePath.split("_")
94-
if (tagName.length === 1 && tagName[0] === slugTagName) {
95-
const elm = document.getElementById(tagName[0])
96-
if (elm && !checkElementInViewport(elm, 0)) {
97-
scrollToTop(
98-
elm.offsetTop + (elm.offsetParent as HTMLElement)?.offsetTop,
99-
0
100-
)
101-
}
102-
} else if (tagName.length > 1 && tagName[0] === slugTagName) {
103-
setLoadData(true)
92+
const tagName = activePath.split("_")
93+
if (tagName[0] !== slugTagName) {
94+
return
95+
}
96+
if (tagName.length === 1) {
97+
const elm = document.getElementById(tagName[0])
98+
if (elm && !checkElementInViewport(elm, 0)) {
99+
scrollToTop(
100+
elm.offsetTop + (elm.offsetParent as HTMLElement)?.offsetTop,
101+
0
102+
)
104103
}
104+
} else if (tagName.length > 1) {
105+
setLoadData(true)
105106
}
106107
}, [slugTagName, activePath, isBrowser])
107108

www/apps/api-reference/config/index.ts

+14-11
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@ export const config: DocsConfig = {
88
baseUrl,
99
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
1010
// sidebar is auto generated
11-
sidebar: {
12-
default: [
13-
{
14-
type: "link",
15-
title: "Introduction",
16-
path: "introduction",
17-
loaded: true,
18-
},
19-
],
20-
mobile: [],
21-
},
11+
sidebars: [
12+
{
13+
sidebar_id: "api-ref",
14+
title: "API Reference",
15+
items: [
16+
{
17+
type: "link",
18+
title: "Introduction",
19+
path: "introduction",
20+
loaded: true,
21+
},
22+
],
23+
},
24+
],
2225
project: {
2326
title: "API Reference",
2427
key: "api-reference",

www/apps/api-reference/providers/base-specs.tsx

+8-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { ExpandedDocument, SecuritySchemeObject } from "@/types/openapi"
44
import { ReactNode, createContext, useContext, useEffect, useMemo } from "react"
5-
import { SidebarItem, SidebarItemSections } from "types"
5+
import { Sidebar } from "types"
66
import getSectionId from "../utils/get-section-id"
77
import getTagChildSidebarItems from "../utils/get-tag-child-sidebar-items"
88
import { useRouter } from "next/navigation"
@@ -22,7 +22,8 @@ type BaseSpecsProviderProps = {
2222

2323
const BaseSpecsProvider = ({ children, baseSpecs }: BaseSpecsProviderProps) => {
2424
const router = useRouter()
25-
const { activePath, addItems, setActivePath, resetItems } = useSidebar()
25+
const { activePath, addItems, setActivePath, resetItems, shownSidebar } =
26+
useSidebar()
2627

2728
const getSecuritySchema = (
2829
securityName: string
@@ -48,7 +49,7 @@ const BaseSpecsProvider = ({ children, baseSpecs }: BaseSpecsProviderProps) => {
4849
return []
4950
}
5051

51-
const itemsToAdd: SidebarItem[] = [
52+
const itemsToAdd: Sidebar.SidebarItem[] = [
5253
{
5354
type: "separator",
5455
},
@@ -67,6 +68,7 @@ const BaseSpecsProvider = ({ children, baseSpecs }: BaseSpecsProviderProps) => {
6768
children: childItems,
6869
loaded: childItems.length > 0,
6970
showLoadingIfEmpty: true,
71+
initialOpen: false,
7072
onOpen: () => {
7173
if (location.hash !== tagPathName) {
7274
router.push(`#${tagPathName}`, {
@@ -84,14 +86,14 @@ const BaseSpecsProvider = ({ children, baseSpecs }: BaseSpecsProviderProps) => {
8486
}, [baseSpecs])
8587

8688
useEffect(() => {
87-
if (!itemsToAdd.length) {
89+
if (!itemsToAdd.length || !shownSidebar) {
8890
return
8991
}
9092

9193
addItems(itemsToAdd, {
92-
section: SidebarItemSections.DEFAULT,
94+
sidebar_id: shownSidebar.sidebar_id,
9395
})
94-
}, [itemsToAdd])
96+
}, [itemsToAdd, shownSidebar?.sidebar_id])
9597

9698
useEffect(() => {
9799
return () => {

www/apps/api-reference/providers/page-title.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { createContext, useEffect } from "react"
44
import { useSidebar } from "docs-ui"
55
import { useArea } from "./area"
6-
import { SidebarItemLink } from "types"
6+
import { Sidebar } from "types"
77

88
const PageTitleContext = createContext(null)
99

@@ -27,7 +27,7 @@ const PageTitleProvider = ({ children }: PageTitleProviderProps) => {
2727
// find the child that matches the active path
2828
const item = activeItem?.children?.find(
2929
(i) => i.type === "link" && i.path === activePath
30-
) as SidebarItemLink
30+
) as Sidebar.SidebarItemLink
3131
if (item) {
3232
document.title = `${item.title} - ${titleSuffix}`
3333
}

www/apps/api-reference/providers/sidebar.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
2020
isLoading={isLoading}
2121
setIsLoading={setIsLoading}
2222
shouldHandleHashChange={true}
23+
shouldHandlePathChange={false}
2324
scrollableElement={scrollableElement}
24-
initialItems={config.sidebar}
25-
persistState={false}
26-
projectName="api"
25+
sidebars={config.sidebars}
26+
persistCategoryState={false}
27+
disableActiveTransition={false}
28+
isSidebarStatic={false}
2729
>
2830
{children}
2931
</UiSidebarProvider>

www/apps/api-reference/utils/get-tag-child-sidebar-items.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import type { SidebarItem } from "types"
21
import type { Operation, PathsObject } from "@/types/openapi"
32
import type { OpenAPIV3 } from "openapi-types"
43
import dynamic from "next/dynamic"
54
import type { MethodLabelProps } from "@/components/MethodLabel"
65
import getSectionId from "./get-section-id"
6+
import { Sidebar } from "types"
77

88
const MethodLabel = dynamic<MethodLabelProps>(
99
async () => import("../components/MethodLabel")
1010
) as React.FC<MethodLabelProps>
1111

1212
export default function getTagChildSidebarItems(
1313
paths: PathsObject
14-
): SidebarItem[] {
15-
const items: SidebarItem[] = []
14+
): Sidebar.SidebarItem[] {
15+
const items: Sidebar.SidebarItem[] = []
1616
Object.entries(paths).forEach(([, operations]) => {
1717
Object.entries(operations).map(([method, operation]) => {
1818
const definedOperation = operation as Operation

www/apps/book/app/learn/layout.tsx

+1-7
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@ export default function RootLayout({
88
children: React.ReactNode
99
}) {
1010
return (
11-
<TightLayout
12-
sidebarProps={{
13-
expandItems: true,
14-
}}
15-
ProvidersComponent={Providers}
16-
footerComponent={<Footer />}
17-
>
11+
<TightLayout ProvidersComponent={Providers} footerComponent={<Footer />}>
1812
{children}
1913
</TightLayout>
2014
)

0 commit comments

Comments
 (0)