+ );
+};
From 123a034207bb3b86722cdc1df18b261a178f360a Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 15:29:47 +0000
Subject: [PATCH 02/13] fix(docs): size the theme switcher's cells to their
glyphs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The cells were square and a fixed 28px, so the thumb could move in whole
cell widths and never had to be measured. The glyphs are not square: 🖥
is half again as wide as ☾, so a square cell crops the padding around
the wide one and hangs it around the narrow ones.
The cells are padding-sized now, and the thumb takes the position and
the width of the active one from the DOM — one `ResizeObserver` per
active cell, through a ref callback rather than an effect, so the
measurement lands before the browser paints. `left` and `width` are what
animate, which is also what makes the thumb resize as it travels.
---
docs/src/components/theme-switch.tsx | 39 +++++++++++++++++++++-------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index ee82849..8eae3ed 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -3,21 +3,24 @@
import { cn } from "cnfast";
import { useTheme } from "fumadocs-ui/provider/base";
import type { ComponentProps } from "react";
-import { useSyncExternalStore } from "react";
+import { useCallback, useState, useSyncExternalStore } from "react";
import { flushSync } from "react-dom";
type ThemeSwitchProps = ComponentProps<"div"> & {
mode?: "light-dark" | "light-dark-system";
};
+interface Thumb {
+ left: number;
+ width: number;
+}
+
const THEMES = [
{ glyph: "🖥", label: "System theme", value: "system" },
{ glyph: "☉", label: "Light theme", value: "light" },
{ glyph: "☾", label: "Dark theme", value: "dark" },
] as const;
-const STEP = 100;
-
const listeners = new Set<() => void>();
const subscribe = (listener: () => void) => {
listeners.add(listener);
@@ -33,6 +36,22 @@ export const ThemeSwitch = ({
}: ThemeSwitchProps) => {
const { resolvedTheme, setTheme, theme } = useTheme();
const hydrated = useSyncExternalStore(subscribe, onClient, onServer);
+ const [thumb, setThumb] = useState(null);
+
+ const measure = useCallback((cell: HTMLButtonElement | null) => {
+ if (!cell) {
+ return;
+ }
+
+ const place = () =>
+ setThumb({ left: cell.offsetLeft, width: cell.offsetWidth });
+
+ place();
+ const observer = new ResizeObserver(place);
+ observer.observe(cell);
+
+ return () => observer.disconnect();
+ }, []);
const themes =
mode === "light-dark"
@@ -40,7 +59,6 @@ export const ThemeSwitch = ({
: THEMES;
const selected = mode === "light-dark" ? resolvedTheme : theme;
const active = hydrated ? selected : null;
- const index = themes.findIndex((option) => option.value === active);
const change = (value: string) => {
if (document.startViewTransition) {
@@ -54,31 +72,32 @@ export const ThemeSwitch = ({
{/* Closing the gap opened by not using Fumapress's own nav: without
this the home page had no way to change appearance. */}
-
+
From 26d63c054031f868b90b53e0428d09fcd907e087 Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 15:40:35 +0000
Subject: [PATCH 04/13] fix(docs): draw the theme switcher with Geist icons
The glyphs were characters, and a character is at the mercy of whatever
font the platform resolves it to. `U+1F5A5 DESKTOP COMPUTER` is text
presentation by default, but almost no text font carries it, so most
systems fell through to a colour emoji font: a full-colour monitor next
to two thin monochrome symbols, at a size and baseline neither of them
shared.
The three Geist icons are one 16px grid, `currentColor` throughout, so
they inherit the cell's colour and its states. The cells come out 36px
wide, which is what the design they are modelled on measures.
---
docs/src/components/theme-switch.tsx | 36 ++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index 8eae3ed..17472fe 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -16,9 +16,30 @@ interface Thumb {
}
const THEMES = [
- { glyph: "🖥", label: "System theme", value: "system" },
- { glyph: "☉", label: "Light theme", value: "light" },
- { glyph: "☾", label: "Dark theme", value: "dark" },
+ {
+ icon: {
+ d: "M2.5 5.25C2.5 3.45 3.96 2 5.75 2h4.5c1.8 0 3.25 1.46 3.25 3.25V14h-11V5.25M5.75 3.5C4.78 3.5 4 4.28 4 5.25v7.25h8V5.25c0-.97-.78-1.75-1.75-1.75zM5 5.5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1V9H5zm3.5 6H11V10H8.5z",
+ rule: "evenodd",
+ },
+ label: "System theme",
+ value: "system",
+ },
+ {
+ icon: {
+ d: "M8.75 2v-.75h-1.5V3h1.5V2M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4m0 1.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7m.75 1.5v1.75h-1.5V13zM13 7.25h1.75v1.5H13zm-11 0h-.75v1.5H3v-1.5H2m9-3.32.54-.53.17-.17.53-.53 1.06 1.06-.53.53-.17.17-.53.53zm-7.77 7.78-.53.53 1.06 1.06.53-.53.17-.17.53-.53L3.93 11l-.53.53zM3.93 5l-.53-.53-.17-.17-.53-.53L3.76 2.7l.53.53.17.17.53.53zm7.78 7.78.53.53 1.06-1.06-.53-.53-.17-.17-.53-.53L11 12.07l.53.53z",
+ rule: "evenodd",
+ },
+ label: "Light theme",
+ value: "light",
+ },
+ {
+ icon: {
+ d: "m6.3 3.3.7.25A4.25 4.25 0 0 0 12.45 9l.96.96-.08.2A5.75 5.75 0 1 1 6.04 2.6zM5.25 4.76a4.24 4.24 0 1 0 6 5.99H11a5.75 5.75 0 0 1-5.75-6M12.5 3.5h1.25V5H12.5v1.25H11V5H9.75V3.5H11V2.25h1.5zM7 3.55l-.7-.25-.26-.7z",
+ rule: "nonzero",
+ },
+ label: "Dark theme",
+ value: "dark",
+ },
] as const;
const listeners = new Set<() => void>();
@@ -100,7 +121,14 @@ export const ThemeSwitch = ({
ref={active === option.value ? measure : null}
type="button"
>
- {option.glyph}
+
))}
From 83779e5022a14e0a753a5c5c400d9dfd5f6f53d9 Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 15:50:00 +0000
Subject: [PATCH 05/13] fix(docs): make the theme switcher visible on the
footer's card
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The pill was a fill and nothing else: `bg-fd-secondary/50` over
`bg-fd-card` measures 1.03:1, which is not a surface, it is the same
surface. On the home page's footer the control had no edge at all, and
the thumb marking the active theme sat at 1.21:1 against the track it
travels along — the two cues that say "this is a control" and "this one
is selected" were both invisible.
The track takes the hairline the rest of the site gives a bordered
control (`header.tsx` bounds its ghost pill at `foreground/20`), and the
thumb now carries a raised fill and a `foreground/50` ring: 3.02:1 in
light and 4.61:1 in dark against the track, over the 3:1 that WCAG 1.4.11
asks of anything that identifies a state. It is also how the switcher
this is modelled on marks its checked cell — a 1px ring, not a fill.
`text-sm` and `text-center` went with it. Since the cells became icons
they had nothing left to size or align.
---
docs/src/components/theme-switch.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index 17472fe..9df1051 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -93,7 +93,7 @@ export const ThemeSwitch = ({
) : null}
From a54dc0c4a833bf1a526c65a1271828254a409b13 Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 16:02:57 +0000
Subject: [PATCH 06/13] fix(docs): drop the switcher's own surface inside the
sidebar
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The docs sidebar already wraps its bottom row in a bordered
`bg-fd-secondary/50` box padded `pe-0`, expecting whatever sits at the
end to read as the trailing segment of that box — which is why Fumadocs
hands its own switch `rounded-none border-e-0`. The pill arrived with a
second `bg-fd-secondary/50` over the first, a second hairline 2px inside
the box's border, and a ring that landed on the border itself.
The `plain` variant keeps the shape, the cells and the thumb, and gives
up the surface it does not need there; the thumb's ring still measures
3.02:1 against the box it now sits directly on. `PlainThemeSwitch` is
what the layout slot renders. The home page's footer stands alone on the
card with nothing around it, so it keeps the pill.
---
docs/press.config.tsx | 4 ++--
docs/src/components/theme-switch.tsx | 9 ++++++++-
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/docs/press.config.tsx b/docs/press.config.tsx
index d9ce7ca..066ef3c 100644
--- a/docs/press.config.tsx
+++ b/docs/press.config.tsx
@@ -6,7 +6,7 @@ import { linkValidationPlugin } from "fumapress/plugins/link-validation";
import { sitemapPlugin } from "fumapress/plugins/sitemap";
import { takumiPlugin } from "fumapress/plugins/takumi";
-import { ThemeSwitch } from "./src/components/theme-switch";
+import { PlainThemeSwitch } from "./src/components/theme-switch";
import { MARKETPLACE, REPO } from "./src/lib/links";
import { MARK_VIEW_BOX, markPath } from "./src/lib/mark";
import { url } from "./src/lib/url";
@@ -43,7 +43,7 @@ export default defineConfig({
{ text: "Marketplace", url: MARKETPLACE },
],
nav: { title: SITE_NAME },
- slots: { themeSwitch: ThemeSwitch },
+ slots: { themeSwitch: PlainThemeSwitch },
},
meta: {
root() {
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index 9df1051..dbb44f1 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -8,6 +8,7 @@ import { flushSync } from "react-dom";
type ThemeSwitchProps = ComponentProps<"div"> & {
mode?: "light-dark" | "light-dark-system";
+ variant?: "pill" | "plain";
};
interface Thumb {
@@ -53,6 +54,7 @@ const onServer = () => false;
export const ThemeSwitch = ({
className,
mode = "light-dark-system",
+ variant = "pill",
...props
}: ThemeSwitchProps) => {
const { resolvedTheme, setTheme, theme } = useTheme();
@@ -93,7 +95,8 @@ export const ThemeSwitch = ({
);
};
+
+export const PlainThemeSwitch = (props: ThemeSwitchProps) => (
+
+);
From b111a6e0b58c7dd1a024b6de448b5c2c194dcede Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 16:22:36 +0000
Subject: [PATCH 07/13] fix(docs): give the sidebar its own footer instead of
Fumadocs' strip
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The bottom of the sidebar is a bordered box that Fumadocs fills with
whatever icon links and theme switch it is handed. Ours held one icon
link — a GitHub button duplicating the GitHub link already in the nav —
and the switch pinned to the far end, which read as a full-width border
drawn around a lone button and a stretch of nothing.
Dropping `githubUrl` and turning the built-in switch off empties that
box, and it carries `empty:hidden`, so it takes itself out of the
layout. The switch moves to `sidebar.footer`, which the desktop sidebar
and the mobile drawer both render, reached through a `renderLayout`
interceptor because `defaultLayoutProps` cannot describe sidebar props.
It stands on its own there, so the `plain` variant — which existed only
to survive being nested inside the strip — goes with the strip.
---
docs/press.config.tsx | 21 +++++++++++++++++++--
docs/src/components/theme-switch.tsx | 9 +--------
2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/docs/press.config.tsx b/docs/press.config.tsx
index 066ef3c..3cc295d 100644
--- a/docs/press.config.tsx
+++ b/docs/press.config.tsx
@@ -2,11 +2,12 @@ import { defineDocs } from "fumadocs-mdx/macro";
import { defineConfig } from "fumapress";
import { fumadocsMdx } from "fumapress/adapters/mdx";
import { metaSchema, pageSchema } from "fumapress/adapters/mdx/schema";
+import { createDocsLayoutPage } from "fumapress/layouts/docs";
import { linkValidationPlugin } from "fumapress/plugins/link-validation";
import { sitemapPlugin } from "fumapress/plugins/sitemap";
import { takumiPlugin } from "fumapress/plugins/takumi";
-import { PlainThemeSwitch } from "./src/components/theme-switch";
+import { ThemeSwitch } from "./src/components/theme-switch";
import { MARKETPLACE, REPO } from "./src/lib/links";
import { MARK_VIEW_BOX, markPath } from "./src/lib/mark";
import { url } from "./src/lib/url";
@@ -38,12 +39,17 @@ const OG = {
export default defineConfig({
content: docs.toFumadocsSource(),
defaultLayoutProps: {
+ // The sidebar's bottom strip is a bordered box holding whatever icon links
+ // and the theme switch it is given. With one icon link duplicating a nav
+ // link it was a full-width border around a lone button, so both go and the
+ // switch is rendered as the sidebar's own footer below.
+ githubUrl: "",
links: [
{ text: "GitHub", url: REPO },
{ text: "Marketplace", url: MARKETPLACE },
],
nav: { title: SITE_NAME },
- slots: { themeSwitch: PlainThemeSwitch },
+ themeSwitch: { enabled: false },
},
meta: {
root() {
@@ -86,6 +92,17 @@ export default defineConfig({
},
// Deployed to a CDN as a static site, so no route may depend on a server.
mode: "static",
+ renderPage: createDocsLayoutPage({
+ renderLayout({ next, props }) {
+ return next({
+ ...props,
+ sidebar: {
+ ...props.sidebar,
+ footer: ,
+ },
+ });
+ },
+ }),
site: {
baseUrl: url,
git: {
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index dbb44f1..9df1051 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -8,7 +8,6 @@ import { flushSync } from "react-dom";
type ThemeSwitchProps = ComponentProps<"div"> & {
mode?: "light-dark" | "light-dark-system";
- variant?: "pill" | "plain";
};
interface Thumb {
@@ -54,7 +53,6 @@ const onServer = () => false;
export const ThemeSwitch = ({
className,
mode = "light-dark-system",
- variant = "pill",
...props
}: ThemeSwitchProps) => {
const { resolvedTheme, setTheme, theme } = useTheme();
@@ -95,8 +93,7 @@ export const ThemeSwitch = ({
);
};
-
-export const PlainThemeSwitch = (props: ThemeSwitchProps) => (
-
-);
From ab50f23d437766766f56baf924e4a0927717958d Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 16:32:14 +0000
Subject: [PATCH 08/13] fix(docs): make the theme switcher a real radio group
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Three buttons carrying `aria-pressed` announce as three unrelated
toggles — "System theme, toggle button, not pressed", three times, with
nothing to say they are one choice, that only one can hold, or what the
choice is about. Arrow keys did nothing; Tab stopped at each of them.
A `fieldset` with a screen-reader-only `legend` and three radios is the
same control described honestly, and the platform then supplies what
was missing: the group is announced with its name, each option reports
its position in it, arrow keys move between them and Tab treats the
three as one stop. The inputs are `sr-only` rather than hidden, so they
keep their focus and their semantics, and the label draws the focus ring
through `has-[:focus-visible]` — at the `outline-offset-2` every other
control on this site uses.
The thumb's observer now watches the group as well as the active cell,
so a sibling changing width moves the thumb with it instead of stranding
it where the cell used to start.
---
docs/src/components/theme-switch.tsx | 37 ++++++++++++++++++----------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index 9df1051..7c45f05 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -3,10 +3,10 @@
import { cn } from "cnfast";
import { useTheme } from "fumadocs-ui/provider/base";
import type { ComponentProps } from "react";
-import { useCallback, useState, useSyncExternalStore } from "react";
+import { useCallback, useId, useState, useSyncExternalStore } from "react";
import { flushSync } from "react-dom";
-type ThemeSwitchProps = ComponentProps<"div"> & {
+type ThemeSwitchProps = ComponentProps<"fieldset"> & {
mode?: "light-dark" | "light-dark-system";
};
@@ -58,8 +58,9 @@ export const ThemeSwitch = ({
const { resolvedTheme, setTheme, theme } = useTheme();
const hydrated = useSyncExternalStore(subscribe, onClient, onServer);
const [thumb, setThumb] = useState(null);
+ const name = useId();
- const measure = useCallback((cell: HTMLButtonElement | null) => {
+ const measure = useCallback((cell: HTMLLabelElement | null) => {
if (!cell) {
return;
}
@@ -70,6 +71,9 @@ export const ThemeSwitch = ({
place();
const observer = new ResizeObserver(place);
observer.observe(cell);
+ if (cell.parentElement) {
+ observer.observe(cell.parentElement);
+ }
return () => observer.disconnect();
}, []);
@@ -90,14 +94,16 @@ export const ThemeSwitch = ({
};
return (
-
+
+
{thumb ? (
(
-
+
))}
-
+
);
};
From 6450901cbcd6befe1ffd1c17be59ae9be4330d90 Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 16:50:53 +0000
Subject: [PATCH 09/13] fix(docs): let colour mark the selected theme instead
of a hard ring
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The thumb was outlined at `foreground/50` — 3.02:1 against the track,
which cleared what WCAG asks of a state indicator, but read as a drawn
border on a control whose whole design is soft fills. The switcher this
follows draws no outline at all.
The selected icon takes `text-fd-primary` instead, which is already how
this sidebar marks the page you are on, and measures 3.28:1 in light and
4.41:1 in dark against the raised fill it sits on — so the state still
carries at a glance and still clears the bar. That frees the rings to
retreat to `foreground/15` on the thumb and `/10` on the track, where
they only have to suggest an edge.
---
docs/src/components/theme-switch.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index 7c45f05..0c3cd48 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -97,7 +97,7 @@ export const ThemeSwitch = ({
) : null}
@@ -117,7 +117,7 @@ export const ThemeSwitch = ({
className={cn(
"has-[:focus-visible]:outline-fd-ring relative inline-flex cursor-pointer items-center justify-center rounded-full px-2.5 py-1.5 leading-none transition-colors has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2",
active === option.value
- ? "text-fd-foreground"
+ ? "text-fd-primary"
: "text-fd-muted-foreground hover:text-fd-foreground"
)}
key={option.value}
From 1fcca77d9f82602022c569e5e93a38e1ee989891 Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 16:51:09 +0000
Subject: [PATCH 10/13] feat(docs): put the version and a rule in the sidebar's
footer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Removing Fumadocs' strip left the switch alone at the bottom of the
sidebar with nothing to anchor it: no line to say where the page tree
ends, and a row holding a single control at one edge.
A rule now separates the two zones, bleeding past the block's gutter to
the sidebar's edges the way a rule between zones should, and standing
down inside the drawer, which draws one of its own. The version of the
action the site documents sits at the start of that row, linked to its
release notes — the one fact a reader of these pages has no other way to
learn — with the switch at the end.
It is read from the root `package.json` at build time, so it cannot
drift from what is published.
---
docs/press.config.tsx | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/docs/press.config.tsx b/docs/press.config.tsx
index 3cc295d..2df4faf 100644
--- a/docs/press.config.tsx
+++ b/docs/press.config.tsx
@@ -7,6 +7,7 @@ import { linkValidationPlugin } from "fumapress/plugins/link-validation";
import { sitemapPlugin } from "fumapress/plugins/sitemap";
import { takumiPlugin } from "fumapress/plugins/takumi";
+import { version } from "../package.json";
import { ThemeSwitch } from "./src/components/theme-switch";
import { MARKETPLACE, REPO } from "./src/lib/links";
import { MARK_VIEW_BOX, markPath } from "./src/lib/mark";
@@ -98,7 +99,23 @@ export default defineConfig({
...props,
sidebar: {
...props.sidebar,
- footer: ,
+ // The rule bleeds past the block's own gutter to the sidebar edges,
+ // which is where a rule that separates two zones belongs. The drawer
+ // draws one of its own, so this one stands down inside it.
+ footer: (
+
+ ),
},
});
},
From f4f882d9b90968201dd3e6a1bfbc826e58c4ffac Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 16:58:57 +0000
Subject: [PATCH 11/13] revert(docs): return the selected theme's icon to the
foreground colour
`text-fd-primary` borrowed the sidebar's language for the page you are
on and put it on a control that is not navigation. The icon goes back to
`text-fd-foreground`, and with it the switcher goes back to marking the
selection with the raised thumb alone.
---
docs/src/components/theme-switch.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/src/components/theme-switch.tsx b/docs/src/components/theme-switch.tsx
index 0c3cd48..ec324f2 100644
--- a/docs/src/components/theme-switch.tsx
+++ b/docs/src/components/theme-switch.tsx
@@ -117,7 +117,7 @@ export const ThemeSwitch = ({
className={cn(
"has-[:focus-visible]:outline-fd-ring relative inline-flex cursor-pointer items-center justify-center rounded-full px-2.5 py-1.5 leading-none transition-colors has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2",
active === option.value
- ? "text-fd-primary"
+ ? "text-fd-foreground"
: "text-fd-muted-foreground hover:text-fd-foreground"
)}
key={option.value}
From b4b31e6ac8a891ffb23cdd914727a280287c9156 Mon Sep 17 00:00:00 2001
From: PunGrumpy <108584943+PunGrumpy@users.noreply.github.com>
Date: Mon, 17 Aug 2026 17:07:43 +0000
Subject: [PATCH 12/13] fix(docs): drop the rule above the sidebar's footer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The row holds two things now, one at each edge, which is enough to read
as its own zone; the line was doing work the spacing already does. The
gutter bleed and the drawer override went with it — both existed only to
carry the line to the sidebar's edges and to stand it down where the
drawer draws its own.
---
docs/press.config.tsx | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/docs/press.config.tsx b/docs/press.config.tsx
index 2df4faf..350b791 100644
--- a/docs/press.config.tsx
+++ b/docs/press.config.tsx
@@ -99,11 +99,8 @@ export default defineConfig({
...props,
sidebar: {
...props.sidebar,
- // The rule bleeds past the block's own gutter to the sidebar edges,
- // which is where a rule that separates two zones belongs. The drawer
- // draws one of its own, so this one stands down inside it.
footer: (
-