docs: collapse sidebar by default in main docs + persist state (#8608)

* docs: collapse sidebar by default in main docs + persist state

* persist sidebar hidden
This commit is contained in:
Shahed Nasser
2024-08-16 09:29:14 +03:00
committed by GitHub
parent 1bfdceb34c
commit 0cc2a62b9b
9 changed files with 101 additions and 6 deletions

View File

@@ -33,6 +33,8 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
scrollableElement={scrollableElement}
initialItems={config.sidebar}
resetOnCondition={resetOnCondition}
persistState={false}
projectName="api"
>
{children}
</UiSidebarProvider>

View File

@@ -21,6 +21,7 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
initialItems={config.sidebar}
staticSidebarItems={true}
disableActiveTransition={true}
projectName="docs"
>
{children}
</UiSidebarProvider>

View File

@@ -14,24 +14,27 @@ export default function numberSidebarItems(sidebarItems, numbering = [1]) {
const numberedItems = []
/** @type {import("@/types").SidebarItem | undefined} */
let parentItem
sidebarItems.forEach((item) => {
sidebarItems.forEach((item, index) => {
if (item.type === "separator") {
;(parentItem?.children || numberedItems).push(item)
}
// append current number to the item's title
item.number = `${numbering.join(".")}.`
item.title = `${item.number} ${item.title.trim()}`
if (isTopItems) {
// Add chapter category
numberedItems.push({
type: "category",
title: `Chapter ${padNumber(numbering[0])}`,
title: item.title,
children: [],
loaded: true,
initialOpen: false,
})
parentItem = numberedItems[numberedItems.length - 1]
}
// append current number to the item's title
item.number = `${numbering.join(".")}.`
item.title = `${item.number} ${item.title.trim()}`
if (item.children) {
item.children = numberSidebarItems(item.children, [...numbering, 1])

View File

@@ -20,6 +20,7 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
initialItems={config.sidebar}
staticSidebarItems={true}
disableActiveTransition={true}
projectName="resources"
>
{children}
</UiSidebarProvider>

View File

@@ -17,6 +17,7 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
shouldHandlePathChange={true}
scrollableElement={scrollableElement}
disableActiveTransition={true}
projectName="ui"
>
{children}
</UiSidebarProvider>

View File

@@ -20,6 +20,7 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
initialItems={config.sidebar}
staticSidebarItems={true}
disableActiveTransition={true}
projectName="user-guide"
>
{children}
</UiSidebarProvider>

View File

@@ -23,7 +23,12 @@ export const SidebarItemCategory = ({
item.initialOpen !== undefined ? item.initialOpen : expandItems
)
const childrenRef = useRef<HTMLUListElement>(null)
const { isChildrenActive } = useSidebar()
const {
isChildrenActive,
updatePersistedCategoryState,
getPersistedCategoryState,
persistState,
} = useSidebar()
useEffect(() => {
if (open && !item.loaded) {
@@ -44,6 +49,16 @@ export const SidebarItemCategory = ({
}
}, [isChildrenActive])
useEffect(() => {
if (!persistState) {
return
}
const persistedOpen = getPersistedCategoryState(item.title)
if (persistedOpen !== undefined) {
setOpen(persistedOpen)
}
}, [persistState])
const handleOpen = () => {
item.onOpen?.()
}
@@ -70,6 +85,9 @@ export const SidebarItemCategory = ({
if (!open) {
handleOpen()
}
if (persistState) {
updatePersistedCategoryState(item.title, !open)
}
setOpen((prev) => !prev)
}}
>

View File

@@ -56,6 +56,9 @@ export type SidebarContextType = {
setSidebarTopHeight: React.Dispatch<React.SetStateAction<number>>
resetItems: () => void
isItemLoaded: (path: string) => boolean
updatePersistedCategoryState: (title: string, opened: boolean) => void
getPersistedCategoryState: (title: string) => boolean | undefined
persistState: boolean
} & SidebarStyleOptions
export const SidebarContext = createContext<SidebarContextType | null>(null)
@@ -191,6 +194,8 @@ export type SidebarProviderProps = {
scrollableElement?: Element | Window
staticSidebarItems?: boolean
resetOnCondition?: () => boolean
projectName: string
persistState?: boolean
} & SidebarStyleOptions
export const SidebarProvider = ({
@@ -204,7 +209,11 @@ export const SidebarProvider = ({
staticSidebarItems = false,
disableActiveTransition = false,
resetOnCondition,
projectName,
persistState = true,
}: SidebarProviderProps) => {
const categoriesStorageKey = `${projectName}_categories`
const hideSidebarStorageKey = `hide_sidebar`
const [items, dispatch] = useReducer(reducer, {
default: initialItems?.default || [],
mobile: initialItems?.mobile || [],
@@ -462,6 +471,56 @@ export const SidebarProvider = ({
}
}, [resetOnCondition, resetItems])
useEffect(() => {
if (!isBrowser) {
return
}
const storageValue = localStorage.getItem(hideSidebarStorageKey)
if (storageValue !== null) {
setDesktopSidebarOpen(storageValue === "false")
}
}, [isBrowser])
useEffect(() => {
if (!isBrowser) {
return
}
localStorage.setItem(
hideSidebarStorageKey,
`${desktopSidebarOpen === false}`
)
}, [isBrowser, desktopSidebarOpen])
const updatePersistedCategoryState = (title: string, opened: boolean) => {
const storageData = JSON.parse(
localStorage.getItem(categoriesStorageKey) || "{}"
)
if (!Object.hasOwn(storageData, projectName)) {
storageData[projectName] = {}
}
storageData[projectName] = {
...storageData[projectName],
[title]: opened,
}
localStorage.setItem(categoriesStorageKey, JSON.stringify(storageData))
}
const getPersistedCategoryState = (title: string): boolean | undefined => {
const storageData = JSON.parse(
localStorage.getItem(categoriesStorageKey) || "{}"
)
return !Object.hasOwn(storageData, projectName) ||
!Object.hasOwn(storageData[projectName], title)
? undefined
: storageData[projectName][title]
}
return (
<SidebarContext.Provider
value={{
@@ -487,6 +546,9 @@ export const SidebarProvider = ({
setSidebarTopHeight,
resetItems,
isItemLoaded,
updatePersistedCategoryState,
getPersistedCategoryState,
persistState,
}}
>
{children}

View File

@@ -54,3 +54,9 @@ export type RawSidebarItem = SidebarItem & {
custom_autogenerate?: string
number?: string
}
export type PersistedSidebarCategoryState = {
[k: string]: {
[k: string]: boolean
}
}