diff --git a/packages/docusaurus-playground/docs/test/1.md b/packages/docusaurus-playground/docs/test/1.md
new file mode 100644
index 0000000..ffb0a30
--- /dev/null
+++ b/packages/docusaurus-playground/docs/test/1.md
@@ -0,0 +1,6 @@
+---
+title: 1
+sidebar_position: 1
+---
+
+# 111
diff --git a/packages/docusaurus-playground/docs/test/2.md b/packages/docusaurus-playground/docs/test/2.md
new file mode 100644
index 0000000..c066eac
--- /dev/null
+++ b/packages/docusaurus-playground/docs/test/2.md
@@ -0,0 +1,6 @@
+---
+title: 2
+sidebar_position: 1
+---
+
+# 222
diff --git a/packages/docusaurus-playground/docs/test/3/33.md b/packages/docusaurus-playground/docs/test/3/33.md
new file mode 100644
index 0000000..9fc7246
--- /dev/null
+++ b/packages/docusaurus-playground/docs/test/3/33.md
@@ -0,0 +1,6 @@
+---
+title: 333
+sidebar_position: 1
+---
+
+# 333
diff --git a/packages/logos-docusaurus-theme/src/client/css/custom.scss b/packages/logos-docusaurus-theme/src/client/css/custom.scss
index f7a02fb..e4dca32 100644
--- a/packages/logos-docusaurus-theme/src/client/css/custom.scss
+++ b/packages/logos-docusaurus-theme/src/client/css/custom.scss
@@ -12,7 +12,6 @@
--ifm-navbar-link-color: rgb(var(--lsd-text-primary));
--ifm-dropdown-link-color: rgb(var(--lsd-text-secondary));
--ifm-dropdown-hover-background-color: rgb(var(--lsd-surface-secondary));
- --ifm-menu-color-active: rgb(var(--lsd-text-secondary));
/* Colors. */
/*--ifm-dark-value: 10%;*/
@@ -159,7 +158,8 @@
--ifm-menu-link-padding-horizontal: var(--ifm-spacing-horizontal);
--ifm-menu-link-padding-vertical: 0.375rem;
- --ifm-menu-color-background-active: var(--ifm-color-gray-300);
+ --ifm-menu-color: rgb(var(--lsd-text-primary), 0.6);
+ --ifm-menu-color-background-active: transparent;
--ifm-menu-link-sublist-icon: url('data:image/svg+xml;utf8,');
--ifm-menu-link-sublist-icon-filter: none;
@@ -317,6 +317,12 @@ small {
border: none !important;
}
+.menu__link {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
@media (max-width: 576px) {
:root {
--ifm-global-spacing: 0.5rem;
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocPage/Layout/Sidebar/index.tsx b/packages/logos-docusaurus-theme/src/client/theme/DocPage/Layout/Sidebar/index.tsx
new file mode 100644
index 0000000..87e18c0
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocPage/Layout/Sidebar/index.tsx
@@ -0,0 +1,74 @@
+import React, { useState, useCallback } from 'react'
+import clsx from 'clsx'
+import { prefersReducedMotion, ThemeClassNames } from '@docusaurus/theme-common'
+import { useDocsSidebar } from '@docusaurus/theme-common/internal'
+import { useLocation } from '@docusaurus/router'
+import DocSidebar from '@theme/DocSidebar'
+import ExpandButton from '@theme/DocPage/Layout/Sidebar/ExpandButton'
+import styles from './styles.module.css'
+// Reset sidebar state when sidebar changes
+// Use React key to unmount/remount the children
+// See https://github.com/facebook/docusaurus/issues/3414
+function ResetOnSidebarChange({ children }) {
+ const sidebar = useDocsSidebar()
+ return (
+
+ {children}
+
+ )
+}
+export default function DocPageLayoutSidebar({
+ sidebar,
+ hiddenSidebarContainer,
+ setHiddenSidebarContainer,
+}) {
+ const { pathname } = useLocation()
+ const [hiddenSidebar, setHiddenSidebar] = useState(false)
+ const toggleSidebar = useCallback(() => {
+ if (hiddenSidebar) {
+ setHiddenSidebar(false)
+ }
+ // onTransitionEnd won't fire when sidebar animation is disabled
+ // fixes https://github.com/facebook/docusaurus/issues/8918
+ if (!hiddenSidebar && prefersReducedMotion()) {
+ setHiddenSidebar(true)
+ }
+ setHiddenSidebarContainer((value) => !value)
+ }, [setHiddenSidebarContainer, hiddenSidebar])
+ return (
+
+ )
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocPage/Layout/Sidebar/styles.module.css b/packages/logos-docusaurus-theme/src/client/theme/DocPage/Layout/Sidebar/styles.module.css
new file mode 100644
index 0000000..ded4577
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocPage/Layout/Sidebar/styles.module.css
@@ -0,0 +1,31 @@
+:root {
+ --doc-sidebar-width: 300px;
+ --doc-sidebar-hidden-width: 30px;
+}
+
+.docSidebarContainer {
+ display: none;
+}
+
+@media (min-width: 997px) {
+ .docSidebarContainer {
+ display: block;
+ width: var(--doc-sidebar-width);
+ margin-top: calc(-1 * var(--ifm-navbar-height));
+ will-change: width;
+ transition: width var(--ifm-transition-fast) ease;
+ clip-path: inset(0);
+ }
+
+ .docSidebarContainerHidden {
+ width: var(--doc-sidebar-hidden-width);
+ cursor: pointer;
+ }
+
+ .sidebarViewport {
+ top: 0;
+ position: sticky;
+ height: 100%;
+ max-height: 100vh;
+ }
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/CollapseButton/index.tsx b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/CollapseButton/index.tsx
new file mode 100644
index 0000000..5198702
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/CollapseButton/index.tsx
@@ -0,0 +1,30 @@
+import React from 'react'
+import clsx from 'clsx'
+import { translate } from '@docusaurus/Translate'
+import IconArrow from '@theme/Icon/Arrow'
+import styles from './styles.module.css'
+
+export default function CollapseButton({ onClick }) {
+ return (
+
+ )
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/CollapseButton/styles.module.css b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/CollapseButton/styles.module.css
new file mode 100644
index 0000000..df46519
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/CollapseButton/styles.module.css
@@ -0,0 +1,40 @@
+:root {
+ --docusaurus-collapse-button-bg: transparent;
+ --docusaurus-collapse-button-bg-hover: rgb(0 0 0 / 10%);
+}
+
+[data-theme='dark']:root {
+ --docusaurus-collapse-button-bg: rgb(255 255 255 / 5%);
+ --docusaurus-collapse-button-bg-hover: rgb(255 255 255 / 10%);
+}
+
+@media (min-width: 997px) {
+ .collapseSidebarButton {
+ display: block !important;
+ background-color: var(--docusaurus-collapse-button-bg);
+ height: 40px;
+ position: sticky;
+ bottom: 0;
+ border-radius: 0;
+ border: 1px solid var(--ifm-toc-border-color);
+ }
+
+ .collapseSidebarButtonIcon {
+ transform: rotate(180deg);
+ margin-top: 4px;
+ }
+
+ [dir='rtl'] .collapseSidebarButtonIcon {
+ transform: rotate(0);
+ }
+
+ .collapseSidebarButton:hover,
+ .collapseSidebarButton:focus {
+ background-color: var(--docusaurus-collapse-button-bg-hover);
+ }
+}
+
+.collapseSidebarButton {
+ display: none;
+ margin: 0;
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/Content/index.js b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/Content/index.js
new file mode 100644
index 0000000..81f7c3f
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/Content/index.js
@@ -0,0 +1,45 @@
+import React, { useState } from 'react'
+import clsx from 'clsx'
+import { ThemeClassNames } from '@docusaurus/theme-common'
+import {
+ useAnnouncementBar,
+ useScrollPosition,
+} from '@docusaurus/theme-common/internal'
+import { translate } from '@docusaurus/Translate'
+import DocSidebarItems from '@theme/DocSidebarItems'
+import styles from './styles.module.css'
+function useShowAnnouncementBar() {
+ const { isActive } = useAnnouncementBar()
+ const [showAnnouncementBar, setShowAnnouncementBar] = useState(isActive)
+ useScrollPosition(
+ ({ scrollY }) => {
+ if (isActive) {
+ setShowAnnouncementBar(scrollY === 0)
+ }
+ },
+ [isActive],
+ )
+ return isActive && showAnnouncementBar
+}
+export default function DocSidebarDesktopContent({ path, sidebar, className }) {
+ const showAnnouncementBar = useShowAnnouncementBar()
+ return (
+
+ )
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/Content/styles.module.css b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/Content/styles.module.css
new file mode 100644
index 0000000..0c43a4e
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/Content/styles.module.css
@@ -0,0 +1,16 @@
+@media (min-width: 997px) {
+ .menu {
+ flex-grow: 1;
+ padding: 0.5rem;
+ }
+ @supports (scrollbar-gutter: stable) {
+ .menu {
+ padding: 0.5rem 0 0.5rem 0.5rem;
+ scrollbar-gutter: stable;
+ }
+ }
+
+ .menuWithAnnouncementBar {
+ margin-bottom: var(--docusaurus-announcement-bar-height);
+ }
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/index.tsx b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/index.tsx
new file mode 100644
index 0000000..7242ecf
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/index.tsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import clsx from 'clsx'
+import { useThemeConfig } from '@docusaurus/theme-common'
+import Logo from '@theme/Logo'
+import Content from '@theme/DocSidebar/Desktop/Content'
+import styles from './styles.module.css'
+function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }) {
+ const {
+ navbar: { hideOnScroll },
+ docs: {
+ sidebar: { hideable },
+ },
+ } = useThemeConfig()
+ return (
+
+ {hideOnScroll && }
+
+
+ )
+}
+export default React.memo(DocSidebarDesktop)
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/styles.module.css b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/styles.module.css
new file mode 100644
index 0000000..c5d5e50
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/Desktop/styles.module.css
@@ -0,0 +1,37 @@
+@media (min-width: 997px) {
+ .sidebar {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ padding-top: var(--ifm-navbar-height);
+ width: var(--doc-sidebar-width);
+ }
+
+ .sidebarWithHideableNavbar {
+ padding-top: 0;
+ }
+
+ .sidebarHidden {
+ opacity: 0;
+ visibility: hidden;
+ }
+
+ .sidebarLogo {
+ display: flex !important;
+ align-items: center;
+ margin: 0 var(--ifm-navbar-padding-horizontal);
+ min-height: var(--ifm-navbar-height);
+ max-height: var(--ifm-navbar-height);
+ color: inherit !important;
+ text-decoration: none !important;
+ }
+
+ .sidebarLogo img {
+ margin-right: 0.5rem;
+ height: 2rem;
+ }
+}
+
+.sidebarLogo {
+ display: none;
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/index.tsx b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/index.tsx
new file mode 100644
index 0000000..fd80d91
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebar/index.tsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import { useWindowSize } from '@docusaurus/theme-common'
+import DocSidebarDesktop from '@theme/DocSidebar/Desktop'
+import DocSidebarMobile from '@theme/DocSidebar/Mobile'
+export default function DocSidebar(props) {
+ const windowSize = useWindowSize()
+ // Desktop sidebar visible on hydration: need SSR rendering
+ const shouldRenderSidebarDesktop =
+ windowSize === 'desktop' || windowSize === 'ssr'
+ // Mobile sidebar not visible on hydration: can avoid SSR rendering
+ const shouldRenderSidebarMobile = windowSize === 'mobile'
+ return (
+ <>
+ {shouldRenderSidebarDesktop && }
+ {shouldRenderSidebarMobile && }
+ >
+ )
+}
diff --git a/packages/logos-docusaurus-theme/src/client/theme/DocSidebarItem/Category/index.tsx b/packages/logos-docusaurus-theme/src/client/theme/DocSidebarItem/Category/index.tsx
new file mode 100644
index 0000000..bba0b2d
--- /dev/null
+++ b/packages/logos-docusaurus-theme/src/client/theme/DocSidebarItem/Category/index.tsx
@@ -0,0 +1,193 @@
+import React, { useEffect, useMemo } from 'react'
+import clsx from 'clsx'
+import {
+ ThemeClassNames,
+ useThemeConfig,
+ usePrevious,
+ Collapsible,
+ useCollapsible,
+} from '@docusaurus/theme-common'
+import {
+ isActiveSidebarItem,
+ findFirstCategoryLink,
+ useDocSidebarItemsExpandedState,
+ isSamePath,
+} from '@docusaurus/theme-common/internal'
+import Link from '@docusaurus/Link'
+import { translate } from '@docusaurus/Translate'
+import useIsBrowser from '@docusaurus/useIsBrowser'
+import DocSidebarItems from '@theme/DocSidebarItems'
+import { ArrowDownIcon, ArrowUpIcon } from '@acid-info/lsd-react'
+
+// If we navigate to a category and it becomes active, it should automatically
+// expand itself
+function useAutoExpandActiveCategory({ isActive, collapsed, updateCollapsed }) {
+ const wasActive = usePrevious(isActive)
+ useEffect(() => {
+ const justBecameActive = isActive && !wasActive
+ if (justBecameActive && collapsed) {
+ updateCollapsed(false)
+ }
+ }, [isActive, wasActive, collapsed, updateCollapsed])
+}
+/**
+ * When a collapsible category has no link, we still link it to its first child
+ * during SSR as a temporary fallback. This allows to be able to navigate inside
+ * the category even when JS fails to load, is delayed or simply disabled
+ * React hydration becomes an optional progressive enhancement
+ * see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188
+ * see https://github.com/facebook/docusaurus/issues/3030
+ */
+
+function useCategoryHrefWithSSRFallback(item) {
+ const isBrowser = useIsBrowser()
+ return useMemo(() => {
+ if (item.href) {
+ return item.href
+ }
+ // In these cases, it's not necessary to render a fallback
+ // We skip the "findFirstCategoryLink" computation
+ if (isBrowser || !item.collapsible) {
+ return undefined
+ }
+ return findFirstCategoryLink(item)
+ }, [item, isBrowser])
+}
+
+function CollapseButton({ categoryLabel, onClick }) {
+ return (
+
+ )
+}
+
+export default function DocSidebarItemCategory({
+ item,
+ onItemClick,
+ activePath,
+ level,
+ index,
+ ...props
+}) {
+ const { items, label, collapsible, className, href } = item
+ const {
+ docs: {
+ sidebar: { autoCollapseCategories },
+ },
+ } = useThemeConfig()
+ const hrefWithSSRFallback = useCategoryHrefWithSSRFallback(item)
+ const isActive = isActiveSidebarItem(item, activePath)
+ const isCurrentPage = isSamePath(href, activePath)
+
+ const { collapsed, setCollapsed } = useCollapsible({
+ // Active categories are always initialized as expanded. The default
+ // (`item.collapsed`) is only used for non-active categories.
+ initialState: () => {
+ if (!collapsible) {
+ return false
+ }
+ return isActive ? false : item.collapsed
+ },
+ })
+
+ const { expandedItem, setExpandedItem } = useDocSidebarItemsExpandedState()
+
+ // Use this instead of `setCollapsed`, because it is also reactive
+ const updateCollapsed = (toCollapsed = !collapsed) => {
+ setExpandedItem(toCollapsed ? null : index)
+ setCollapsed(toCollapsed)
+ }
+
+ useAutoExpandActiveCategory({ isActive, collapsed, updateCollapsed })
+
+ useEffect(() => {
+ if (
+ collapsible &&
+ expandedItem != null &&
+ expandedItem !== index &&
+ autoCollapseCategories
+ ) {
+ setCollapsed(true)
+ }
+ }, [collapsible, expandedItem, index, setCollapsed, autoCollapseCategories])
+
+ return (
+
+
+
{
+ onItemClick?.(item)
+ if (href) {
+ updateCollapsed(false)
+ } else {
+ e.preventDefault()
+ updateCollapsed()
+ }
+ }
+ : () => {
+ onItemClick?.(item)
+ }
+ }
+ aria-current={isCurrentPage ? 'page' : undefined}
+ aria-expanded={collapsible ? !collapsed : undefined}
+ href={collapsible ? hrefWithSSRFallback ?? '#' : hrefWithSSRFallback}
+ {...props}
+ >
+ {label}
+ {collapsed ?
:
}
+
+ {href && collapsible && (
+
{
+ e.preventDefault()
+ updateCollapsed()
+ }}
+ />
+ )}
+
+
+
+
+
+
+ )
+}