From 91eb2196ba4663a0afc01de359a62186b3166539 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 24 Jul 2026 17:10:13 +0100 Subject: [PATCH] Introduce secondary site nav, relocate nav items --- website/docusaurus.config.ts | 39 +-- website/sidebarsCommunity.ts | 10 +- .../src/components/DocsSecondaryNav/index.tsx | 247 ++++++++++++++++++ .../DocsSecondaryNav/styles.module.css | 181 +++++++++++++ website/src/css/customTheme.scss | 10 +- website/src/css/docs-secondary-nav.scss | 115 ++++++++ website/src/theme/BlogLayout/index.tsx | 40 +++ .../src/theme/BlogSidebar/Desktop/index.tsx | 3 - .../BlogSidebar/Desktop/styles.module.css | 13 +- website/src/theme/DocItem/Layout/index.tsx | 35 +-- .../theme/DocItem/Layout/styles.module.css | 86 ------ website/src/theme/DocRoot/Layout/index.tsx | 26 ++ 12 files changed, 631 insertions(+), 174 deletions(-) create mode 100644 website/src/components/DocsSecondaryNav/index.tsx create mode 100644 website/src/components/DocsSecondaryNav/styles.module.css create mode 100644 website/src/css/docs-secondary-nav.scss create mode 100644 website/src/theme/BlogLayout/index.tsx create mode 100644 website/src/theme/DocRoot/Layout/index.tsx diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index b0a53998ede..6aa2b17f985 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -212,6 +212,7 @@ const config: Config = { require.resolve('./src/css/index.scss'), require.resolve('./src/css/showcase.scss'), require.resolve('./src/css/versions.scss'), + require.resolve('./src/css/docs-secondary-nav.scss'), ], }, gtag: { @@ -426,31 +427,14 @@ const config: Config = { style: 'dark', items: [ { - label: 'Development', type: 'dropdown', + label: 'Docs', position: 'right', items: [ - { - label: 'Guides', - type: 'doc', - docId: 'getting-started', - }, - { - label: 'Components', - type: 'doc', - docId: 'components-and-apis', - }, - { - label: 'APIs', - type: 'doc', - docId: 'accessibilityinfo', - }, - { - label: 'Architecture', - type: 'doc', - docId: 'architecture-overview', - docsPluginId: 'architecture', - }, + {label: 'Guides', to: '/docs/getting-started'}, + {label: 'Components', to: '/docs/components-and-apis'}, + {label: 'APIs', to: '/docs/accessibilityinfo'}, + {label: 'Architecture', to: '/architecture/overview'}, ], }, { @@ -477,17 +461,6 @@ const config: Config = { label: 'Blog', position: 'right', }, - { - type: 'docsVersionDropdown', - position: 'left', - dropdownActiveClassDisabled: true, - dropdownItemsAfter: [ - { - to: '/versions', - label: 'All versions', - }, - ], - }, { href: 'https://github.com/facebook/react-native', 'aria-label': 'GitHub repository', diff --git a/website/sidebarsCommunity.ts b/website/sidebarsCommunity.ts index cbe83d78989..d517a6794b6 100644 --- a/website/sidebarsCommunity.ts +++ b/website/sidebarsCommunity.ts @@ -1,13 +1,5 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; export default { - community: [ - { - type: 'category', - label: 'Community', - collapsed: false, - collapsible: false, - items: ['overview', 'staying-updated', 'communities', 'support'], - }, - ], + community: ['overview', 'staying-updated', 'communities', 'support'], } satisfies SidebarsConfig; diff --git a/website/src/components/DocsSecondaryNav/index.tsx b/website/src/components/DocsSecondaryNav/index.tsx new file mode 100644 index 00000000000..79f1b53f94d --- /dev/null +++ b/website/src/components/DocsSecondaryNav/index.tsx @@ -0,0 +1,247 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, {useEffect, useRef, useState} from 'react'; +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import {useLocation} from '@docusaurus/router'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import {useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; +import DocsVersionDropdownNavbarItem from '@theme/NavbarItem/DocsVersionDropdownNavbarItem'; +import CopyPageButton from 'docusaurus-plugin-copy-page-button/react'; + +import styles from './styles.module.css'; + +type SectionLink = {label: string; to: string}; + +// The section dropdown mirrors the navbar "Docs" dropdown; read its entries from +// the site config so the two can't drift. +function useSectionLinks(): readonly SectionLink[] { + const {siteConfig} = useDocusaurusContext(); + const navbar = siteConfig.themeConfig.navbar as { + items?: ReadonlyArray<{ + type?: string; + label?: string; + items?: SectionLink[]; + }>; + }; + return ( + navbar.items?.find( + item => item.type === 'dropdown' && item.label === 'Docs' + )?.items ?? [] + ); +} + +// Guides, Components and APIs all share the /docs/ URL space, so the active +// section is read from the current doc's sidebar rather than the pathname. +const SECTION_BY_SIDEBAR: Record = { + docs: 'Guides', + components: 'Components', + api: 'APIs', + architecture: 'Architecture', +}; + +type Section = { + title: string; + // The active entry to show on the dropdown toggle, or null to hide the + // dropdown entirely (sections outside the Docs area). + activeSectionLink: string | null; + // A "return to index" link shown to the right of the heading, or null. + backLink: {label: string; href: string} | null; + showCopyButton: boolean; +}; + +function getSection( + pathname: string, + sidebarName: string | undefined +): Section { + if (pathname.startsWith('/blog')) { + // The index and pagination are the blog listing itself; tags, archive, + // authors and individual posts all link back to it via "All posts". + const isBlogIndex = + pathname === '/blog' || + pathname === '/blog/' || + pathname.startsWith('/blog/page/'); + // Copy page is only meaningful on an individual post, not on the listing or + // the other list-style blog routes (tags, archive, authors). + const isBlogPost = + !isBlogIndex && + !pathname.startsWith('/blog/tags') && + !pathname.startsWith('/blog/archive') && + !pathname.startsWith('/blog/authors'); + return { + title: 'Blog', + activeSectionLink: null, + backLink: isBlogIndex ? null : {label: 'All posts', href: '/blog'}, + showCopyButton: isBlogPost, + }; + } + if (pathname.startsWith('/community')) { + return { + title: 'Community', + activeSectionLink: null, + backLink: null, + showCopyButton: true, + }; + } + if (pathname.startsWith('/contributing')) { + return { + title: 'Contributing', + activeSectionLink: null, + backLink: null, + showCopyButton: true, + }; + } + // Docs area (main docs + architecture): the active section follows the doc's + // sidebar (Guides / Components / APIs / Architecture). + return { + title: 'Docs', + activeSectionLink: sidebarName + ? (SECTION_BY_SIDEBAR[sidebarName] ?? null) + : null, + backLink: null, + showCopyButton: true, + }; +} + +function SectionDropdown({ + activeLabel, + links, +}: { + activeLabel: string; + links: readonly SectionLink[]; +}) { + const [open, setOpen] = useState(false); + const containerRef = useRef(null); + + useEffect(() => { + if (!open) { + return undefined; + } + const onDocumentClick = (event: MouseEvent) => { + if ( + containerRef.current && + !containerRef.current.contains(event.target as Node) + ) { + setOpen(false); + } + }; + document.addEventListener('click', onDocumentClick); + return () => document.removeEventListener('click', onDocumentClick); + }, [open]); + + return ( +
+ +
    + {links.map(link => ( +
  • + setOpen(false)}> + {link.label} + +
  • + ))} +
+
+ ); +} + +export default function DocsSecondaryNav({ + sidebarName, +}: { + sidebarName?: string; +}) { + const {pathname} = useLocation(); + const sectionLinks = useSectionLinks(); + const {title, activeSectionLink, backLink, showCopyButton} = getSection( + pathname, + sidebarName + ); + // The docs version dropdown belongs to the main docs; it self-hides elsewhere. + const {activeVersion, activeDoc} = useActiveDocContext('default'); + const showVersionDropdown = Boolean(activeDoc); + const isNextVersion = activeVersion?.name === 'current'; + + return ( + + ); +} diff --git a/website/src/components/DocsSecondaryNav/styles.module.css b/website/src/components/DocsSecondaryNav/styles.module.css new file mode 100644 index 00000000000..04dedf7cd2c --- /dev/null +++ b/website/src/components/DocsSecondaryNav/styles.module.css @@ -0,0 +1,181 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.secondaryNav { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + height: var(--rn-subnav-height); + padding: 0 1.5rem; + background-color: var(--ifm-background-color); + + /* Pin directly below the main navbar so page content scrolls underneath. */ + position: sticky; + top: var(--ifm-navbar-height); + z-index: calc(var(--ifm-z-index-fixed) - 1); +} + +/* Bottom keyline, inset from both edges so it comes in from the screen edges + without lining up with the inner elements' padding. */ +.secondaryNav:after { + content: ""; + position: absolute; + right: 0.75rem; + bottom: 0; + left: 0.75rem; + height: 1px; + background-color: var(--ifm-toc-border-color); +} + +.start { + display: flex; + align-items: center; + gap: 1rem; + min-width: 0; +} + +.end { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.title { + font-size: 1.5rem; + font-weight: var(--ifm-heading-font-weight); + line-height: 1.2; +} + +/* Outlined controls: the section dropdown toggle and the back link share the + bordered box style of the Copy page button. */ + +.dropdown { + font-size: 0.9rem; +} + +.dropdownToggle, +.backLink { + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.35rem 0.6rem; + font-family: inherit; + font-size: 0.9rem; + color: var(--ifm-font-color-base); + background: transparent; + border: 1px solid var(--ifm-color-gray-500); + border-radius: var(--ifm-global-radius); + text-decoration: none; +} + +.dropdownToggle { + cursor: pointer; +} + +.dropdownToggle:after { + content: ""; + display: inline-block; + width: 0; + height: 0; + border-left: 0.3rem solid transparent; + border-right: 0.3rem solid transparent; + border-top: 0.3rem solid currentcolor; + opacity: 0.6; + transform: translateY(1px); +} + +.backLink { + /* Trim vertical padding so the taller chevron doesn't inflate the box, and + tighten the inset before the icon. Match the Copy page button weight. */ + padding: 0.2rem 0.6rem 0.2rem 0.4rem; + font-weight: 500; +} + +.backChevron { + opacity: 0.75; +} + +.dropdownToggle:hover, +.backLink:hover { + color: var(--ifm-font-color-base); + text-decoration: none; + background-color: var(--ifm-menu-color-background-hover); + border-color: var(--ifm-color-gray-400); +} + +/* Docs version dropdown wrapper. The dropdown reuses the theme navbar dropdown; + its pill styling lives in docs-secondary-nav.scss (it targets the theme's + global navbar classes). */ + +.versionDropdown { + display: flex; + align-items: center; + + /* Sit closer to the section dropdown than the .start gap allows. */ + margin-left: -0.5rem; +} + +/* Copy page button — appearance shared with its former home in DocItem */ + +.copyPageContainer { + margin-bottom: 0; +} + +button.copyPageButton { + border-radius: var(--ifm-global-radius); + border-color: var(--ifm-color-gray-500); +} + +button.copyPageButton:hover { + background-color: var(--ifm-menu-color-background-hover) !important; + border-color: var(--ifm-color-gray-400) !important; +} + +button.copyPageButton svg { + opacity: 0.75; +} + +.copyPageDropdown { + border-color: var(--ifm-table-border-color) !important; +} + +.copyPageDropdown button[class^="dropdownItem"] { + border-bottom-color: var(--ifm-table-border-color) !important; +} + +.copyPageDropdown button[class^="dropdownItem"]:hover { + background-color: var(--ifm-menu-color-background-hover); +} + +.copyPageDropdown div[class^="itemDescription"] { + font-weight: 300; + font-size: 12px; +} + +[data-theme="dark"] .dropdownToggle:hover, +[data-theme="dark"] .backLink:hover { + background-color: var(--dark); + border-color: var(--ifm-color-gray-800); +} + +[data-theme="dark"] button.copyPageButton:hover { + background-color: var(--dark) !important; + border-color: var(--ifm-color-gray-800) !important; +} + +[data-theme="dark"] .copyPageDropdown { + background-color: var(--ifm-navbar-background-color); +} + +[data-theme="dark"] .copyPageDropdown button[class^="dropdownItem"]:hover { + background-color: var(--dark); +} + +[data-theme="dark"] .copyPageDropdown div[class^="itemDescription"] { + color: var(--ifm-color-gray-600) !important; +} diff --git a/website/src/css/customTheme.scss b/website/src/css/customTheme.scss index b08da1ee456..269bf2a7939 100644 --- a/website/src/css/customTheme.scss +++ b/website/src/css/customTheme.scss @@ -2257,13 +2257,21 @@ html[data-theme="dark"] .docsRating { /* Blog */ +// Keep blog anchors clear of the sticky DocsSecondaryNav. +html.blog-wrapper { + scroll-padding-top: calc(var(--ifm-navbar-height) + var(--rn-subnav-height)); +} + .blog-wrapper .main-wrapper { h3[class*="sidebarItemTitle"] { color: var(--ifm-font-color-secondary); } div[class*="tableOfContents"] { - top: calc(var(--ifm-navbar-height)); + top: calc(var(--ifm-navbar-height) + var(--rn-subnav-height)); + max-height: calc( + 100vh - (var(--ifm-navbar-height) + var(--rn-subnav-height) + 2rem) + ); } .table-of-contents { diff --git a/website/src/css/docs-secondary-nav.scss b/website/src/css/docs-secondary-nav.scss new file mode 100644 index 00000000000..f8fbcf66d02 --- /dev/null +++ b/website/src/css/docs-secondary-nav.scss @@ -0,0 +1,115 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * Offsets that keep the sticky doc sidebar, table of contents and anchor + * scrolling clear of the sticky DocsSecondaryNav. Scoped to `.plugin-docs`, the + * class Docusaurus sets on for every content-docs page (the pages that + * render the secondary nav). + */ + +:root { + --rn-subnav-height: 3rem; +} + +html.plugin-docs { + scroll-padding-top: calc(var(--ifm-navbar-height) + var(--rn-subnav-height)); +} + +@media (min-width: 997px) { + // Position the sticky sidebar like the blog sidebar: drop the theme's + // negative margin and instead stick the viewport just below the secondary + // nav. This keeps the first item's normal top spacing at every scroll + // position (the negative-margin mechanism otherwise drifts once a second + // sticky bar is added above it). + html.plugin-docs aside[class^="theme-doc-sidebar-container"] { + margin-top: 0; + } + + html.plugin-docs aside[class^="theme-doc-sidebar-container"] > div { + top: calc(var(--ifm-navbar-height) + var(--rn-subnav-height)); + max-height: calc( + 100vh - (var(--ifm-navbar-height) + var(--rn-subnav-height)) + ); + } + + // The viewport now clears both bars, so the content box no longer needs the + // theme's navbar-height top padding. + html.plugin-docs aside[class^="theme-doc-sidebar-container"] > div > div { + padding-top: 0; + } + + html.plugin-docs div[class^="tableOfContents"] { + top: calc(var(--ifm-navbar-height) + var(--rn-subnav-height) + 34px); + max-height: calc( + 100vh - (var(--ifm-navbar-height) + var(--rn-subnav-height) + 2rem) + ); + } +} + +/** + * Docs version dropdown. Reuses the theme navbar dropdown, styled to match the + * other outlined controls in this nav but with fully rounded corners for + * differentiation. Only the "Next" version is highlighted in the brand blue; + * released versions use the same white/grey outline as the other dropdowns. + */ + +[class*="versionDropdown"] { + .navbar__item { + // Keep it visible on mobile too — Infima hides navbar items below 996px. + display: inline-flex; + margin: 0; + padding: 0; + } + + .navbar__link { + display: inline-flex; + align-items: center; + margin: 0; + padding: 0.35rem 0.6rem; + font-size: 0.9rem; + font-weight: var(--ifm-font-weight-normal); + + // Match the section dropdown button's compact height (it uses the browser + // default line-height rather than the taller inherited base). + line-height: normal; + color: var(--ifm-font-color-base); + background: transparent; + border: 1px solid var(--ifm-color-gray-500); + border-radius: 999px; + + // Match the section dropdown caret: nudged down and dimmed to grey. + &:after { + opacity: 0.6; + transform: translateY(-1px); + } + + &:hover { + color: var(--ifm-font-color-base); + background-color: var(--ifm-menu-color-background-hover); + border-color: var(--ifm-color-gray-400); + } + } +} + +[data-theme="dark"] [class*="versionDropdown"] .navbar__link:hover { + background-color: var(--dark); + border-color: var(--ifm-color-gray-800); +} + +[class*="versionDropdown"][data-version-next] .navbar__link { + color: var(--ifm-button-color, #fff); + background-color: var(--ifm-color-primary); + border-color: var(--ifm-color-primary); + + &:hover { + color: var(--ifm-button-color, #fff); + background-color: var(--ifm-color-primary); + border-color: var(--ifm-color-primary); + filter: brightness(0.92); + } +} diff --git a/website/src/theme/BlogLayout/index.tsx b/website/src/theme/BlogLayout/index.tsx new file mode 100644 index 00000000000..7bb44c0730c --- /dev/null +++ b/website/src/theme/BlogLayout/index.tsx @@ -0,0 +1,40 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import type {Props} from '@theme/BlogLayout'; + +import React from 'react'; +import clsx from 'clsx'; +import Layout from '@theme/Layout'; +import BlogSidebar from '@theme/BlogSidebar'; +import DocsSecondaryNav from '@site/src/components/DocsSecondaryNav'; + +// Ejected from @docusaurus/theme-classic to render the shared secondary nav +// full-width below the main navbar, above the blog content. +export default function BlogLayout(props: Props) { + const {sidebar, toc, children, ...layoutProps} = props; + const hasSidebar = sidebar && sidebar.items.length > 0; + + return ( + + +
+
+ +
+ {children} +
+ {toc &&
{toc}
} +
+
+
+ ); +} diff --git a/website/src/theme/BlogSidebar/Desktop/index.tsx b/website/src/theme/BlogSidebar/Desktop/index.tsx index 157fd9c0b0a..bbbb05b1959 100644 --- a/website/src/theme/BlogSidebar/Desktop/index.tsx +++ b/website/src/theme/BlogSidebar/Desktop/index.tsx @@ -23,9 +23,6 @@ export default function BlogSidebarDesktop({sidebar}: Props) { message: 'Blog recent posts navigation', description: 'The ARIA label for recent posts in the blog sidebar', })}> -
- {sidebar.title} -
    {sidebar.items.map(item => { const postYear = item.permalink.split('/')[2]; diff --git a/website/src/theme/BlogSidebar/Desktop/styles.module.css b/website/src/theme/BlogSidebar/Desktop/styles.module.css index dd70c522bf0..e9c18f633a2 100644 --- a/website/src/theme/BlogSidebar/Desktop/styles.module.css +++ b/website/src/theme/BlogSidebar/Desktop/styles.module.css @@ -6,21 +6,16 @@ */ .sidebar { - max-height: calc(100vh - (var(--ifm-navbar-height) + 2rem)); + max-height: calc( + 100vh - (var(--ifm-navbar-height) + var(--rn-subnav-height) + 2rem) + ); overflow-y: auto; position: sticky; - top: var(--ifm-navbar-height); + top: calc(var(--ifm-navbar-height) + var(--rn-subnav-height)); padding: 20px 12px 0 0; margin-left: -20px; } -.sidebarHeader { - font-size: var(--ifm-h4-font-size); - font-weight: var(--ifm-font-weight-bold); - padding-left: 12px; - display: block; -} - .sidebarItemTitle { margin: 0.75rem 0 0.5rem; color: var(--subtle); diff --git a/website/src/theme/DocItem/Layout/index.tsx b/website/src/theme/DocItem/Layout/index.tsx index 734e2007ffe..f3552e0618b 100644 --- a/website/src/theme/DocItem/Layout/index.tsx +++ b/website/src/theme/DocItem/Layout/index.tsx @@ -9,7 +9,6 @@ import React, {type ReactNode} from 'react'; import clsx from 'clsx'; import {useWindowSize} from '@docusaurus/theme-common'; import {useDoc} from '@docusaurus/plugin-content-docs/client'; -import CopyPageButton from 'docusaurus-plugin-copy-page-button/react'; import DocItemPaginator from '@theme/DocItem/Paginator'; import DocVersionBanner from '@theme/DocVersionBanner'; import DocVersionBadge from '@theme/DocVersionBadge'; @@ -23,23 +22,6 @@ import type {Props} from '@theme/DocItem/Layout'; import styles from './styles.module.css'; -function DocItemCopyPageButton({className}: {className?: string}) { - return ( -
    - -
    - ); -} - /** * Decide if the toc should be rendered, on mobile or desktop viewports */ @@ -76,15 +58,7 @@ export default function DocItemLayout({children}: Props): ReactNode {
    -
    - - -
    + {docTOC.mobile} {children} @@ -92,12 +66,7 @@ export default function DocItemLayout({children}: Props): ReactNode {
    - {docTOC.desktop && ( -
    - - {docTOC.desktop} -
    - )} + {docTOC.desktop &&
    {docTOC.desktop}
    } ); } diff --git a/website/src/theme/DocItem/Layout/styles.module.css b/website/src/theme/DocItem/Layout/styles.module.css index d2d6137c74e..13db8d3fa32 100644 --- a/website/src/theme/DocItem/Layout/styles.module.css +++ b/website/src/theme/DocItem/Layout/styles.module.css @@ -10,94 +10,8 @@ margin-top: 0; } -.docHeaderContainer { - display: flex; - justify-content: space-between; - align-items: center; -} - -.copyPageAsideAction { - margin-bottom: 1rem; -} - -div[class^="copyPageArticleAction"] { - margin-bottom: 0; -} - -.copyPageArticleAction { - margin-left: auto; -} - -button[class^="copyPageButton"] { - border-radius: var(--ifm-global-radius); - border-color: var(--ifm-color-gray-500); - - &:hover { - background-color: var(--ifm-menu-color-background-hover) !important; - border-color: var(--ifm-color-gray-400) !important; - } - - svg { - opacity: 0.75; - } -} - -div[class^="copyPageDropdown"] { - border-color: var(--ifm-table-border-color) !important; - - button[class^="dropdownItem"] { - border-bottom-color: var(--ifm-table-border-color) !important; - - &:hover { - background-color: var(--ifm-menu-color-background-hover); - } - - &:not([data-copy-page-action="copy"], [data-copy-page-action="view"]) { - div[class^="itemTitle"] { - margin-bottom: 0; - } - - div[class^="itemDescription"] { - display: none; - } - } - } - - div[class^="itemDescription"] { - font-weight: 300; - font-size: 12px; - } -} - -[data-theme="dark"] { - button[class^="copyPageButton"] { - &:hover { - background-color: var(--dark) !important; - border-color: var(--ifm-color-gray-800) !important; - } - } - - button[class^="dropdownItem"] { - &:hover { - background-color: var(--dark); - } - } - - div[class^="copyPageDropdown"] { - background-color: var(--ifm-navbar-background-color); - - div[class^="itemDescription"] { - color: var(--ifm-color-gray-600) !important; - } - } -} - @media (min-width: 997px) { .docItemCol { max-width: 75% !important; } - - .copyPageArticleActionWithToc { - display: none; - } } diff --git a/website/src/theme/DocRoot/Layout/index.tsx b/website/src/theme/DocRoot/Layout/index.tsx new file mode 100644 index 00000000000..d65fed9a6f1 --- /dev/null +++ b/website/src/theme/DocRoot/Layout/index.tsx @@ -0,0 +1,26 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import type {Props} from '@theme/DocRoot/Layout'; + +import React from 'react'; +import {useDocsSidebar} from '@docusaurus/plugin-content-docs/client'; +import OriginalDocRootLayout from '@theme-original/DocRoot/Layout'; +import DocsSecondaryNav from '@site/src/components/DocsSecondaryNav'; + +// Renders a full-width secondary nav above every docs-plugin layout (docs, +// architecture, community, contributing). The sidebar name drives which section +// the nav shows as active. +export default function DocRootLayout(props: Props) { + const sidebar = useDocsSidebar(); + return ( + <> + + + + ); +}