From 8ede76911ec5f5dcb4d363de72113af71b9a4368 Mon Sep 17 00:00:00 2001 From: Jwahir Sundai Date: Tue, 8 Sep 2026 15:29:37 -0500 Subject: [PATCH 1/4] draft --- sidebars.js | 53 +++++ src/components/SecondaryNav/index.js | 101 +++++++++ src/components/SecondaryNav/styles.module.css | 197 ++++++++++++++++++ src/css/custom.css | 12 ++ src/theme/Navbar/index.js | 10 +- 5 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 src/components/SecondaryNav/index.js create mode 100644 src/components/SecondaryNav/styles.module.css diff --git a/sidebars.js b/sidebars.js index ba42163641..f31a7f5f04 100644 --- a/sidebars.js +++ b/sidebars.js @@ -2209,3 +2209,56 @@ module.exports = { 'tctl-v1/workflow', ], }; + +// --------------------------------------------------------------------------- +// Secondary navigation bar (proof of concept) +// +// Moves four sections out of the single `documentation` sidebar and gives each +// one its own sidebar, so a reader inside a section sees only that section's +// tree. src/components/SecondaryNav renders the tabs and works out which +// section the reader is in from the URL. +// +// Every other section stays in `documentation` and keeps today's sidebar. +// To undo the proof of concept, delete this block and the SecondaryNav import +// in src/theme/Navbar/index.js. +// --------------------------------------------------------------------------- + +const NAV_TAB_SECTIONS = [ + { sidebar: 'develop', category: 'Develop' }, + { sidebar: 'cloud', category: 'Temporal Cloud' }, + { sidebar: 'guides', category: 'Guides' }, + // The AI tab carries the Durable AI tree plus the standalone "Develop with + // AI" page, which lives at the top level of the documentation sidebar today. + { sidebar: 'ai', category: 'Durable AI', extraDocs: ['with-ai'] }, +]; + +// The tab label already names the section, so drop the wrapping category and +// promote its overview page to the first sidebar entry. +function flattenSection(category) { + const overview = category.link && category.link.type === 'doc' ? [category.link.id] : []; + return [...overview, ...category.items]; +} + +(function buildSectionSidebars(sidebars) { + const mainSidebar = sidebars.documentation; + const moved = new Set(); + + for (const section of NAV_TAB_SECTIONS) { + const category = mainSidebar.find((item) => item && item.type === 'category' && item.label === section.category); + + if (!category) { + throw new Error( + `Secondary nav: no "${section.category}" category found in the documentation sidebar. ` + + `Update NAV_TAB_SECTIONS in sidebars.js if the section was renamed or removed.` + ); + } + + const extraDocs = section.extraDocs || []; + moved.add(category); + extraDocs.forEach((id) => moved.add(id)); + + sidebars[section.sidebar] = [...flattenSection(category), ...extraDocs]; + } + + sidebars.documentation = mainSidebar.filter((item) => !moved.has(item)); +})(module.exports); diff --git a/src/components/SecondaryNav/index.js b/src/components/SecondaryNav/index.js new file mode 100644 index 0000000000..0428840b01 --- /dev/null +++ b/src/components/SecondaryNav/index.js @@ -0,0 +1,101 @@ +import React, { useEffect, useState } from 'react'; +import Link from '@docusaurus/Link'; +import { useLocation } from '@docusaurus/router'; +import styles from './styles.module.css'; + +const TABS = [ + { label: 'Develop', to: '/develop', match: ['/develop'] }, + { label: 'Cloud', to: '/cloud', match: ['/cloud'] }, + { label: 'Guides', to: '/guides', match: ['/guides'] }, + { label: 'AI agents', to: '/ai', match: ['/ai', '/with-ai'] }, +]; + +const VARIANTS = [ + { id: 'underline', label: 'A. Underline' }, + { id: 'segmented', label: 'B. Segmented' }, +]; + +const SURFACES = [ + { id: 'surfaceFlush', label: '1. Flush' }, + { id: 'surfaceRaised', label: '2. Raised' }, + { id: 'surfaceTint', label: '3. Indigo tint' }, + { id: 'surfaceGradient', label: '4. Gradient wash' }, + { id: 'surfaceInk', label: '5. Ink' }, +]; + +function isActive(pathname, prefixes) { + const path = pathname.replace(/\/+$/, '') || '/'; + return prefixes.some((prefix) => path === prefix || path.startsWith(`${prefix}/`)); +} + +// Read after mount so the server markup and first client render agree. +function useChoice(storageKey, options, fallback) { + const [value, setValue] = useState(fallback); + + useEffect(() => { + try { + const stored = window.localStorage.getItem(storageKey); + if (stored && options.some((option) => option.id === stored)) setValue(stored); + } catch { + // Blocked storage. Keep the default. + } + }, [storageKey, options]); + + const choose = (next) => { + setValue(next); + try { + window.localStorage.setItem(storageKey, next); + } catch { + // Not worth surfacing in a POC control. + } + }; + + return [value, choose]; +} + +function Picker({ value, options, onChange, label }) { + return ( + + ); +} + +export default function SecondaryNav() { + const { pathname } = useLocation(); + const [variant, chooseVariant] = useChoice('poc-secondary-nav-variant', VARIANTS, 'underline'); + const [surface, chooseSurface] = useChoice('poc-secondary-nav-surface', SURFACES, 'surfaceFlush'); + + const current = TABS.find((tab) => isActive(pathname, tab.match)); + + const tabs = TABS.map((tab) => ( + + {tab.label} + + )); + + return ( + + ); +} diff --git a/src/components/SecondaryNav/styles.module.css b/src/components/SecondaryNav/styles.module.css new file mode 100644 index 0000000000..af9130b362 --- /dev/null +++ b/src/components/SecondaryNav/styles.module.css @@ -0,0 +1,197 @@ +.secondaryNav { + --secondary-nav-accent: var(--interactive-primary-surface, #444ce7); + --secondary-nav-gradient: linear-gradient(255.4deg, #444ce7 0%, #b664ff 100%); + + position: sticky; + top: var(--navbar-primary-height); + z-index: 150; + height: var(--secondary-nav-height); + border-bottom: 1px solid var(--ifm-toc-border-color); + font-size: 0.875rem; +} + +.inner { + display: flex; + align-items: center; + height: 100%; + padding: 0 var(--ifm-navbar-padding-horizontal); + overflow-x: auto; + scrollbar-width: none; +} + +.inner::-webkit-scrollbar { + display: none; +} + +.tabs { + display: flex; + align-items: center; +} + +.tab { + display: inline-flex; + align-items: center; + white-space: nowrap; + font-weight: 500; + color: var(--ifm-navbar-link-color); + text-decoration: none; + transition: + color 120ms ease, + background-color 120ms ease, + border-color 120ms ease; +} + +.tab:hover { + text-decoration: none; +} + +/* POC scaffolding. Delete with the unused variants. */ +.pickers { + display: flex; + gap: 0.375rem; + margin-left: auto; + padding-left: 1rem; +} + +.picker { + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + font-family: inherit; + color: var(--ifm-color-emphasis-600); + background: transparent; + border: 1px solid var(--ifm-color-emphasis-300); + border-radius: 6px; + cursor: pointer; +} + +/* A. Underline ----------------------------------------------------------- */ + +.underline .tabs { + gap: 2.25rem; +} + +.underline .tab { + height: var(--secondary-nav-height); + margin-bottom: -1px; + border-bottom: 2px solid transparent; +} + +.underline .tab:hover { + color: var(--ifm-navbar-link-hover-color); +} + +.underline .tabActive, +.underline .tabActive:hover { + color: var(--ifm-color-primary); + border-bottom-color: var(--ifm-color-primary); +} + +/* B. Segmented ------------------------------------------------------------ + * border-image-source cannot follow a border-radius, so the 1px ring is a + * padded gradient masked to its own edge. + */ + +.segmented .group { + position: relative; + display: inline-flex; + gap: 0.5rem; + padding: 0.3125rem; + border-radius: 999px; +} + +.segmented .group::before { + content: ''; + position: absolute; + inset: 0; + padding: 1px; + border-radius: inherit; + background: var(--secondary-nav-gradient); + mask: + linear-gradient(#000 0 0) content-box, + linear-gradient(#000 0 0); + mask-composite: exclude; + -webkit-mask: + linear-gradient(#000 0 0) content-box, + linear-gradient(#000 0 0); + -webkit-mask-composite: xor; + pointer-events: none; +} + +.segmented .tab { + padding: 0.4375rem 1.5rem; + border-radius: 999px; +} + +.segmented .tab:hover { + color: var(--ifm-navbar-link-hover-color); +} + +.segmented .tabActive, +.segmented .tabActive:hover { + color: #fff; + background: var(--secondary-nav-accent); +} + +/* Surfaces --------------------------------------------------------------- */ + +.surfaceFlush { + background: var(--ifm-navbar-background-color); +} + +.surfaceRaised { + background: #f4f5f7; +} + +/* Tints composite over an opaque base. The bar is sticky and sits above the + * doc sidebar's right border, so any transparency lets both show through. */ + +.surfaceTint { + background: + linear-gradient(rgb(68 76 231 / 5%), rgb(68 76 231 / 5%)), + var(--ifm-navbar-background-color); +} + +.surfaceGradient { + background: + linear-gradient(90deg, rgb(68 76 231 / 10%) 0%, rgb(182 100 255 / 5%) 100%), + var(--ifm-navbar-background-color); +} + +.surfaceInk { + background: #0d0f1c; + border-bottom-color: transparent; +} + +.surfaceInk .tab { + color: rgb(255 255 255 / 72%); +} + +.surfaceInk .tab:hover, +.surfaceInk.underline .tabActive { + color: #fff; +} + +.surfaceInk.underline .tabActive { + border-bottom-color: #fff; +} + +.surfaceInk .picker { + color: rgb(255 255 255 / 60%); + border-color: rgb(255 255 255 / 20%); +} + +[data-theme='dark'] .surfaceRaised { + background: #14141a; +} + +[data-theme='dark'] .surfaceTint { + background: + linear-gradient(rgb(68 76 231 / 16%), rgb(68 76 231 / 16%)), + var(--ifm-navbar-background-color); +} + +[data-theme='dark'] .surfaceGradient { + background: + linear-gradient(90deg, rgb(68 76 231 / 28%) 0%, rgb(182 100 255 / 14%) 100%), + var(--ifm-navbar-background-color); +} diff --git a/src/css/custom.css b/src/css/custom.css index ca7543e019..02351dfe87 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -1928,3 +1928,15 @@ code { background: transparent; cursor: pointer; } + +/* Secondary nav: --ifm-navbar-height must cover both header rows. */ + +:root { + --navbar-primary-height: 3.75rem; + --secondary-nav-height: 4.25rem; + --ifm-navbar-height: calc(var(--navbar-primary-height) + var(--secondary-nav-height)); +} + +.navbar { + height: var(--navbar-primary-height); +} diff --git a/src/theme/Navbar/index.js b/src/theme/Navbar/index.js index 382ba4a96e..52101596bc 100644 --- a/src/theme/Navbar/index.js +++ b/src/theme/Navbar/index.js @@ -1,6 +1,12 @@ import React from 'react'; import Navbar from '@theme-original/Navbar'; +import SecondaryNav from '@site/src/components/SecondaryNav'; export default function NavbarWrapper(props) { - return ; -} \ No newline at end of file + return ( + <> + + + + ); +} From 807ffa55315e647eba76dd7e56f94371f98a2688 Mon Sep 17 00:00:00 2001 From: Jwahir Sundai Date: Tue, 8 Sep 2026 16:03:40 -0500 Subject: [PATCH 2/4] contextual nav bar for dev sdk guides --- sidebars.js | 32 ++++++++++ src/components/SdkNav/activeSdk.js | 17 +++++ src/components/SdkNav/index.js | 35 ++++++++++ src/components/SdkNav/styles.module.css | 85 +++++++++++++++++++++++++ src/components/SecondaryNav/index.js | 4 ++ src/css/custom.css | 3 +- src/theme/Navbar/index.js | 2 + 7 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 src/components/SdkNav/activeSdk.js create mode 100644 src/components/SdkNav/index.js create mode 100644 src/components/SdkNav/styles.module.css diff --git a/sidebars.js b/sidebars.js index f31a7f5f04..2ade4fd228 100644 --- a/sidebars.js +++ b/sidebars.js @@ -2262,3 +2262,35 @@ function flattenSection(category) { sidebars.documentation = mainSidebar.filter((item) => !moved.has(item)); })(module.exports); + +// Develop splits one level further: each SDK gets its own sidebar, so a reader +// on /develop/go sees the Go tree instead of all eight. src/components/SdkNav +// renders the SDKs as a third row, shown only inside Develop. What is left in +// `develop` is the language-agnostic material. +(function buildSdkSidebars(sidebars) { + const developSidebar = sidebars.develop; + const moved = new Set(); + const sdkLinks = []; + + for (const { id } of SDKS) { + const category = developSidebar.find( + (item) => item && item.type === 'category' && item.link && item.link.id === `develop/${id}/index` + ); + + if (!category) { + throw new Error(`Secondary nav: no sidebar category found for the ${id} SDK (expected link develop/${id}/index).`); + } + + moved.add(category); + sidebars[`develop-${id}`] = flattenSection(category); + + // The SDKs stay listed in Develop as plain links. A doc can belong to only + // one sidebar, and its pages now live in the per-SDK sidebar above. + sdkLinks.push({ type: 'link', label: category.label, href: `/develop/${id}` }); + } + + const remaining = developSidebar.filter((item) => !moved.has(item)); + const afterOverview = remaining.indexOf('develop/index') + 1; + + sidebars.develop = [...remaining.slice(0, afterOverview), ...sdkLinks, ...remaining.slice(afterOverview)]; +})(module.exports); diff --git a/src/components/SdkNav/activeSdk.js b/src/components/SdkNav/activeSdk.js new file mode 100644 index 0000000000..9d17547dbc --- /dev/null +++ b/src/components/SdkNav/activeSdk.js @@ -0,0 +1,17 @@ +import { SDKS } from '@site/src/constants/sdks'; + +export const DEVELOP_SECTION = '/develop'; + +export function normalizePath(pathname) { + return pathname.replace(/\/+$/, '') || '/'; +} + +// The SDK row and the section tabs are mutually exclusive, so both rows read +// this to decide which one renders. +export function findActiveSdk(pathname) { + const path = normalizePath(pathname); + return SDKS.find(({ id }) => { + const base = `${DEVELOP_SECTION}/${id}`; + return path === base || path.startsWith(`${base}/`); + }); +} diff --git a/src/components/SdkNav/index.js b/src/components/SdkNav/index.js new file mode 100644 index 0000000000..b0b8ceaf11 --- /dev/null +++ b/src/components/SdkNav/index.js @@ -0,0 +1,35 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import { useLocation } from '@docusaurus/router'; +import { SDKS } from '@site/src/constants/sdks'; +import { DEVELOP_SECTION, findActiveSdk } from './activeSdk'; +import styles from './styles.module.css'; + +export default function SdkNav() { + const activeSdk = findActiveSdk(useLocation().pathname); + + if (!activeSdk) return null; + + return ( + + ); +} diff --git a/src/components/SdkNav/styles.module.css b/src/components/SdkNav/styles.module.css new file mode 100644 index 0000000000..cc4f2dbdde --- /dev/null +++ b/src/components/SdkNav/styles.module.css @@ -0,0 +1,85 @@ +.sdkNav { + --sdk-nav-accent: var(--interactive-primary-surface, #444ce7); + --sdk-nav-gradient: linear-gradient(255.4deg, #444ce7 0%, #b664ff 100%); + + position: sticky; + top: var(--navbar-primary-height); + z-index: 150; + height: var(--secondary-nav-height); + background: var(--ifm-navbar-background-color); + border-bottom: 1px solid var(--ifm-toc-border-color); + font-size: 0.875rem; +} + +.inner { + display: flex; + align-items: center; + height: 100%; + padding: 0 var(--ifm-navbar-padding-horizontal); + overflow-x: auto; + scrollbar-width: none; +} + +.inner::-webkit-scrollbar { + display: none; +} + +/* border-image-source cannot follow a border-radius, so the 1px ring is a + * padded gradient masked to its own edge. */ +.group { + position: relative; + display: inline-flex; + gap: 0.375rem; + padding: 0.3125rem; + border-radius: 999px; +} + +.group::before { + content: ''; + position: absolute; + inset: 0; + padding: 1px; + border-radius: inherit; + background: var(--sdk-nav-gradient); + mask: + linear-gradient(#000 0 0) content-box, + linear-gradient(#000 0 0); + mask-composite: exclude; + -webkit-mask: + linear-gradient(#000 0 0) content-box, + linear-gradient(#000 0 0); + -webkit-mask-composite: xor; + pointer-events: none; +} + +.sdk { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.4375rem 1rem; + white-space: nowrap; + font-weight: 500; + color: var(--ifm-navbar-link-color); + text-decoration: none; + border-radius: 999px; + transition: + color 120ms ease, + background-color 120ms ease; +} + +.sdk:hover { + color: var(--ifm-navbar-link-hover-color); + text-decoration: none; +} + +.sdkActive, +.sdkActive:hover { + color: #fff; + background: var(--sdk-nav-accent); +} + +.icon { + width: 1.125rem; + height: 1.125rem; + flex-shrink: 0; +} diff --git a/src/components/SecondaryNav/index.js b/src/components/SecondaryNav/index.js index 0428840b01..cac796cd4a 100644 --- a/src/components/SecondaryNav/index.js +++ b/src/components/SecondaryNav/index.js @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import Link from '@docusaurus/Link'; import { useLocation } from '@docusaurus/router'; +import { findActiveSdk } from '@site/src/components/SdkNav/activeSdk'; import styles from './styles.module.css'; const TABS = [ @@ -70,6 +71,9 @@ export default function SecondaryNav() { const [variant, chooseVariant] = useChoice('poc-secondary-nav-variant', VARIANTS, 'underline'); const [surface, chooseSurface] = useChoice('poc-secondary-nav-surface', SURFACES, 'surfaceFlush'); + // Inside an SDK guide the SDK row takes this row's place. + if (findActiveSdk(pathname)) return null; + const current = TABS.find((tab) => isActive(pathname, tab.match)); const tabs = TABS.map((tab) => ( diff --git a/src/css/custom.css b/src/css/custom.css index 02351dfe87..d9af533b5e 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -1929,7 +1929,8 @@ code { cursor: pointer; } -/* Secondary nav: --ifm-navbar-height must cover both header rows. */ +/* Secondary nav: --ifm-navbar-height must cover both header rows. The second + * row is either the section tabs or the SDK row, never both. */ :root { --navbar-primary-height: 3.75rem; diff --git a/src/theme/Navbar/index.js b/src/theme/Navbar/index.js index 52101596bc..3d1ec1be93 100644 --- a/src/theme/Navbar/index.js +++ b/src/theme/Navbar/index.js @@ -1,12 +1,14 @@ import React from 'react'; import Navbar from '@theme-original/Navbar'; import SecondaryNav from '@site/src/components/SecondaryNav'; +import SdkNav from '@site/src/components/SdkNav'; export default function NavbarWrapper(props) { return ( <> + ); } From e3f3f286b916596364033c95f39423b7c7a34a82 Mon Sep 17 00:00:00 2001 From: Jwahir Sundai Date: Tue, 8 Sep 2026 16:16:13 -0500 Subject: [PATCH 3/4] fix ring --- src/components/SdkNav/styles.module.css | 27 ++----- src/components/SecondaryNav/styles.module.css | 73 ++++++++----------- 2 files changed, 37 insertions(+), 63 deletions(-) diff --git a/src/components/SdkNav/styles.module.css b/src/components/SdkNav/styles.module.css index cc4f2dbdde..4f0af616ce 100644 --- a/src/components/SdkNav/styles.module.css +++ b/src/components/SdkNav/styles.module.css @@ -24,32 +24,17 @@ display: none; } -/* border-image-source cannot follow a border-radius, so the 1px ring is a - * padded gradient masked to its own edge. */ +/* Keep the two-background ring: a masked pseudo-element fills solid in + * production, autoprefixer drops mask-composite. */ .group { - position: relative; display: inline-flex; gap: 0.375rem; padding: 0.3125rem; + border: 1px solid transparent; border-radius: 999px; -} - -.group::before { - content: ''; - position: absolute; - inset: 0; - padding: 1px; - border-radius: inherit; - background: var(--sdk-nav-gradient); - mask: - linear-gradient(#000 0 0) content-box, - linear-gradient(#000 0 0); - mask-composite: exclude; - -webkit-mask: - linear-gradient(#000 0 0) content-box, - linear-gradient(#000 0 0); - -webkit-mask-composite: xor; - pointer-events: none; + background: + linear-gradient(var(--ifm-navbar-background-color), var(--ifm-navbar-background-color)) padding-box, + var(--sdk-nav-gradient) border-box; } .sdk { diff --git a/src/components/SecondaryNav/styles.module.css b/src/components/SecondaryNav/styles.module.css index af9130b362..e858ae1860 100644 --- a/src/components/SecondaryNav/styles.module.css +++ b/src/components/SecondaryNav/styles.module.css @@ -1,6 +1,7 @@ .secondaryNav { --secondary-nav-accent: var(--interactive-primary-surface, #444ce7); --secondary-nav-gradient: linear-gradient(255.4deg, #444ce7 0%, #b664ff 100%); + --secondary-nav-surface: var(--ifm-navbar-background-color); position: sticky; top: var(--navbar-primary-height); @@ -86,35 +87,18 @@ border-bottom-color: var(--ifm-color-primary); } -/* B. Segmented ------------------------------------------------------------ - * border-image-source cannot follow a border-radius, so the 1px ring is a - * padded gradient masked to its own edge. - */ +/* B. Segmented. Keep the two-background ring: a masked pseudo-element fills + * solid in production, autoprefixer drops mask-composite. */ .segmented .group { - position: relative; display: inline-flex; gap: 0.5rem; padding: 0.3125rem; + border: 1px solid transparent; border-radius: 999px; -} - -.segmented .group::before { - content: ''; - position: absolute; - inset: 0; - padding: 1px; - border-radius: inherit; - background: var(--secondary-nav-gradient); - mask: - linear-gradient(#000 0 0) content-box, - linear-gradient(#000 0 0); - mask-composite: exclude; - -webkit-mask: - linear-gradient(#000 0 0) content-box, - linear-gradient(#000 0 0); - -webkit-mask-composite: xor; - pointer-events: none; + background: + linear-gradient(var(--secondary-nav-surface), var(--secondary-nav-surface)) padding-box, + var(--secondary-nav-gradient) border-box; } .segmented .tab { @@ -134,31 +118,38 @@ /* Surfaces --------------------------------------------------------------- */ +/* Surfaces stay opaque: the bar is sticky over the doc sidebar's right border + * and the page content. Each sets --secondary-nav-surface so the segmented + * ring's inner fill matches the bar. */ + .surfaceFlush { - background: var(--ifm-navbar-background-color); + --secondary-nav-surface: var(--ifm-navbar-background-color); + + background: var(--secondary-nav-surface); } .surfaceRaised { - background: #f4f5f7; -} + --secondary-nav-surface: #f4f5f7; -/* Tints composite over an opaque base. The bar is sticky and sits above the - * doc sidebar's right border, so any transparency lets both show through. */ + background: var(--secondary-nav-surface); +} .surfaceTint { - background: - linear-gradient(rgb(68 76 231 / 5%), rgb(68 76 231 / 5%)), - var(--ifm-navbar-background-color); + --secondary-nav-surface: #f6f6fe; + + background: var(--secondary-nav-surface); } .surfaceGradient { - background: - linear-gradient(90deg, rgb(68 76 231 / 10%) 0%, rgb(182 100 255 / 5%) 100%), - var(--ifm-navbar-background-color); + --secondary-nav-surface: #ecedfd; + + background: linear-gradient(90deg, #ecedfd 0%, #fbf5ff 100%); } .surfaceInk { - background: #0d0f1c; + --secondary-nav-surface: #0d0f1c; + + background: var(--secondary-nav-surface); border-bottom-color: transparent; } @@ -181,17 +172,15 @@ } [data-theme='dark'] .surfaceRaised { - background: #14141a; + --secondary-nav-surface: #14141a; } [data-theme='dark'] .surfaceTint { - background: - linear-gradient(rgb(68 76 231 / 16%), rgb(68 76 231 / 16%)), - var(--ifm-navbar-background-color); + --secondary-nav-surface: #0b0c25; } [data-theme='dark'] .surfaceGradient { - background: - linear-gradient(90deg, rgb(68 76 231 / 28%) 0%, rgb(182 100 255 / 14%) 100%), - var(--ifm-navbar-background-color); + --secondary-nav-surface: #131541; + + background: linear-gradient(90deg, #131541 0%, #1a0f26 100%); } From 5745ce1998ddf026f2cf15a7a76725c70f2c8c71 Mon Sep 17 00:00:00 2001 From: Jwahir Sundai Date: Tue, 8 Sep 2026 16:33:52 -0500 Subject: [PATCH 4/4] fix underline for sdknav --- src/components/SdkNav/index.js | 44 +++++++----- src/components/SdkNav/styles.module.css | 65 ------------------ src/components/SecondaryNav/index.js | 67 +++---------------- src/components/SecondaryNav/styles.module.css | 3 +- src/components/navStyle.js | 65 ++++++++++++++++++ 5 files changed, 102 insertions(+), 142 deletions(-) create mode 100644 src/components/navStyle.js diff --git a/src/components/SdkNav/index.js b/src/components/SdkNav/index.js index b0b8ceaf11..aaac681556 100644 --- a/src/components/SdkNav/index.js +++ b/src/components/SdkNav/index.js @@ -2,33 +2,43 @@ import React from 'react'; import Link from '@docusaurus/Link'; import { useLocation } from '@docusaurus/router'; import { SDKS } from '@site/src/constants/sdks'; +import { StylePickers, useNavStyle } from '@site/src/components/navStyle'; +import styles from '@site/src/components/SecondaryNav/styles.module.css'; import { DEVELOP_SECTION, findActiveSdk } from './activeSdk'; -import styles from './styles.module.css'; +import sdkStyles from './styles.module.css'; export default function SdkNav() { const activeSdk = findActiveSdk(useLocation().pathname); + const navStyle = useNavStyle(); if (!activeSdk) return null; + const tabs = SDKS.map(({ id, label, icon: Icon }) => { + const active = id === activeSdk.id; + return ( + +