From b3f1fb6a47847a9c408f89f9923514325658d076 Mon Sep 17 00:00:00 2001 From: Gracjan Sadowicz Date: Tue, 15 Sep 2026 13:51:33 +0200 Subject: [PATCH 1/2] RDoc-4106 Lack of active state in docs subpage select is misleading The section you are in was removed from the switcher and replaced by a generic "Start" entry, so the list showed every destination except the current one. In Quill that left "Guides" and "Samples" reading as Quill's own. Keep every section on the list and mark the current one active instead. The entry links to the section landing page, so it also covers what "Start" did. Both sidebars now render one shared list from getSectionNavItems(), which drops the per-section conditionals and the hover-only "Switch" labels. Desktop and mobile had drifted apart in the meantime: different order, and mobile still used the sparkles icon for Quill. --- src/components/Common/SectionNavLink.tsx | 30 +++++++++++ src/theme/DocSidebar/Desktop/index.tsx | 65 +++--------------------- src/theme/DocSidebar/Mobile/index.tsx | 65 +++++------------------- src/typescript/pathUtils.ts | 43 ++++++++++++++++ 4 files changed, 93 insertions(+), 110 deletions(-) create mode 100644 src/components/Common/SectionNavLink.tsx diff --git a/src/components/Common/SectionNavLink.tsx b/src/components/Common/SectionNavLink.tsx new file mode 100644 index 0000000000..90defce483 --- /dev/null +++ b/src/components/Common/SectionNavLink.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import clsx from "clsx"; +import Link from "@docusaurus/Link"; +import { Icon } from "@site/src/components/Common/Icon"; +import type { SectionNavItem } from "@site/src/typescript/pathUtils"; + +interface SectionNavLinkProps { + item: SectionNavItem; + isActive: boolean; + onClick?: () => void; +} + +export function SectionNavLink({ item, isActive, onClick }: SectionNavLinkProps) { + return ( + + + {item.label} + {item.external && } + + ); +} diff --git a/src/theme/DocSidebar/Desktop/index.tsx b/src/theme/DocSidebar/Desktop/index.tsx index 426902f0b1..f809dc5d8a 100644 --- a/src/theme/DocSidebar/Desktop/index.tsx +++ b/src/theme/DocSidebar/Desktop/index.tsx @@ -12,7 +12,8 @@ import SidebarVersionDropdown from "@site/src/components/SidebarVersionDropdown" import { useActiveDocContext, useLatestVersion } from "@docusaurus/plugin-content-docs/client"; import { Icon } from "@site/src/components/Common/Icon"; -import { getPathType, getLandingPagePath, PathType } from "../../../typescript/pathUtils"; +import { SectionNavLink } from "@site/src/components/Common/SectionNavLink"; +import { getPathType, getSectionNavItems, PathType } from "../../../typescript/pathUtils"; function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props) { const { @@ -28,7 +29,7 @@ function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props) { const versionLabel = activeVersion?.label ?? latestVersion.label; const pathType = getPathType(path); - const landingPagePath = getLandingPagePath(pathType, versionLabel); + const sectionNavItems = getSectionNavItems(pathType, versionLabel); const shouldDisplayContent = pathType !== PathType.Guides && pathType !== PathType.Samples; @@ -41,66 +42,16 @@ function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props) { )} > {hideOnScroll && } -
-
- - Start - -
- {pathType !== PathType.Guides && ( - - Guides - - Switch - - - )} - {pathType !== PathType.Samples && ( - - Samples - - Switch - - - )} - {pathType !== PathType.Documentation && ( - - RavenDB Docs - - Switch - - - )} - {pathType !== PathType.Cloud && ( - - RavenDB Cloud Docs - - Switch - - - )} - {pathType !== PathType.Quill && ( - - Quill Docs - - Switch - - - )} - - Community - - +
+ {shouldDisplayContent &&
} {pathType === PathType.Documentation && } {shouldDisplayContent && } diff --git a/src/theme/DocSidebar/Mobile/index.tsx b/src/theme/DocSidebar/Mobile/index.tsx index 960568b237..853075e5fa 100644 --- a/src/theme/DocSidebar/Mobile/index.tsx +++ b/src/theme/DocSidebar/Mobile/index.tsx @@ -7,9 +7,10 @@ import type { Props } from "@theme/DocSidebar/Mobile"; import Link from "@docusaurus/Link"; import { useActiveDocContext, useLatestVersion } from "@docusaurus/plugin-content-docs/client"; import { Icon } from "@site/src/components/Common/Icon"; +import { SectionNavLink } from "@site/src/components/Common/SectionNavLink"; import type { Props as DocSidebarProps } from "@theme/DocSidebar"; import SidebarVersionDropdown from "@site/src/components/SidebarVersionDropdown"; -import { getPathType, getLandingPagePath, PathType } from "../../../typescript/pathUtils"; +import { getPathType, getSectionNavItems, PathType } from "../../../typescript/pathUtils"; function DocSidebarMobileSecondaryMenu({ sidebar, path }: DocSidebarProps) { const mobileSidebar = useNavbarMobileSidebar(); @@ -20,63 +21,21 @@ function DocSidebarMobileSecondaryMenu({ sidebar, path }: DocSidebarProps) { const versionLabel = activeVersion?.label ?? latestVersion.label; const pathType = getPathType(path); - const landingPagePath = getLandingPagePath(pathType, versionLabel); + const sectionNavItems = getSectionNavItems(pathType, versionLabel); const shouldDisplayContent = pathType !== PathType.Guides && pathType !== PathType.Samples; return (
    -
  • -
    - mobileSidebar.toggle()}> - Start - -
    -
  • - {pathType !== PathType.Guides && ( - - Guides - - Switch - - - )} - {pathType !== PathType.Documentation && ( - - RavenDB Docs - - Switch - - - )} - {pathType !== PathType.Samples && ( - - Samples - - Switch - - - )} - {pathType !== PathType.Cloud && ( - - RavenDB Cloud Docs - - Switch - - - )} - {pathType !== PathType.Quill && ( - - Quill Docs - - Switch - - - )} - - Community - - + {sectionNavItems.map((item) => ( +
  • + mobileSidebar.toggle()} + /> +
  • + ))} {pathType === PathType.Documentation && (
  • candidate.type === pathType); return section ? `/${section.segment}` : `/${versionLabel}`; } + +export interface SectionNavItem { + label: string; + icon: IconName; + to: string; + pathType: PathTypeValue | null; + // Shown only while you are already inside it, for areas that are not public destinations. + currentOnly?: boolean; + external?: boolean; +} + +const NAV_SECTIONS: readonly { type: PathTypeValue; label: string; icon: IconName; currentOnly?: boolean }[] = [ + { type: PathType.Documentation, label: "RavenDB Docs", icon: "database" }, + { type: PathType.Cloud, label: "RavenDB Cloud Docs", icon: "cloud" }, + { type: PathType.Quill, label: "Quill Docs", icon: "quill" }, + { type: PathType.Guides, label: "Guides", icon: "guides" }, + { type: PathType.Samples, label: "Samples", icon: "create-sample-data" }, + { type: PathType.Templates, label: "Templates", icon: "documentation-guide", currentOnly: true }, +]; + +export function getSectionNavItems(pathType: PathTypeValue, versionLabel: string): SectionNavItem[] { + const sections = NAV_SECTIONS.filter((section) => !section.currentOnly || section.type === pathType).map( + (section) => ({ + label: section.label, + icon: section.icon, + to: getLandingPagePath(section.type, versionLabel), + pathType: section.type, + }) + ); + + return [ + ...sections, + { + label: "Community", + icon: "community", + to: "https://ravendb.net/community", + pathType: null, + external: true, + }, + ]; +} From c19e58ff15faf5c9f356e631eb557edb46b07a3c Mon Sep 17 00:00:00 2001 From: Gracjan Sadowicz Date: Wed, 30 Sep 2026 17:51:00 +0200 Subject: [PATCH 2/2] RDoc-4106 Bring Start back as the active section entry Review feedback: keep the Start entry and treat it as the home of the product documentation you are reading, with the active state on it. The entry for the section you are in no longer repeats the product name that the header already shows, and the remaining sections follow it unchanged. Name the two section registry types instead of declaring them inline at the point of use. --- src/typescript/pathUtils.ts | 60 +++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/typescript/pathUtils.ts b/src/typescript/pathUtils.ts index c25d0b9e16..7b6b5660bf 100644 --- a/src/typescript/pathUtils.ts +++ b/src/typescript/pathUtils.ts @@ -13,7 +13,12 @@ export type PathTypeValue = (typeof PathType)[keyof typeof PathType]; // Versionless content areas, in match order. The URL segment doubles as the landing page path. // Anything that matches none of these is versioned documentation. -const SECTIONS: readonly { segment: string; type: PathTypeValue }[] = [ +interface Section { + segment: string; + type: PathTypeValue; +} + +const SECTIONS: readonly Section[] = [ { segment: "cloud", type: PathType.Cloud }, { segment: "quill", type: PathType.Quill }, { segment: "guides", type: PathType.Guides }, @@ -36,38 +41,47 @@ export interface SectionNavItem { icon: IconName; to: string; pathType: PathTypeValue | null; - // Shown only while you are already inside it, for areas that are not public destinations. - currentOnly?: boolean; external?: boolean; } -const NAV_SECTIONS: readonly { type: PathTypeValue; label: string; icon: IconName; currentOnly?: boolean }[] = [ +interface NavSection { + type: PathTypeValue; + label: string; + icon: IconName; +} + +const NAV_SECTIONS: readonly NavSection[] = [ { type: PathType.Documentation, label: "RavenDB Docs", icon: "database" }, { type: PathType.Cloud, label: "RavenDB Cloud Docs", icon: "cloud" }, { type: PathType.Quill, label: "Quill Docs", icon: "quill" }, { type: PathType.Guides, label: "Guides", icon: "guides" }, { type: PathType.Samples, label: "Samples", icon: "create-sample-data" }, - { type: PathType.Templates, label: "Templates", icon: "documentation-guide", currentOnly: true }, ]; +const COMMUNITY: SectionNavItem = { + label: "Community", + icon: "community", + to: "https://ravendb.net/community", + pathType: null, + external: true, +}; + export function getSectionNavItems(pathType: PathTypeValue, versionLabel: string): SectionNavItem[] { - const sections = NAV_SECTIONS.filter((section) => !section.currentOnly || section.type === pathType).map( - (section) => ({ - label: section.label, - icon: section.icon, - to: getLandingPagePath(section.type, versionLabel), - pathType: section.type, - }) - ); + // The section you are in keeps its place on the list, named for what the entry does rather + // than repeating the product name already shown in the header. The sidebars mark it active. + const start: SectionNavItem = { + label: "Start", + icon: "home", + to: getLandingPagePath(pathType, versionLabel), + pathType, + }; + + const others = NAV_SECTIONS.filter((section) => section.type !== pathType).map((section) => ({ + label: section.label, + icon: section.icon, + to: getLandingPagePath(section.type, versionLabel), + pathType: section.type, + })); - return [ - ...sections, - { - label: "Community", - icon: "community", - to: "https://ravendb.net/community", - pathType: null, - external: true, - }, - ]; + return [start, ...others, COMMUNITY]; }