Fix embed ignoring explicit ?theme override on single-theme sites (RND-11571)

resolveEmbeddableTheme checked the non-toggeable branch before the explicit
forcedTheme, so a site with the theme toggle disabled silently ignored the
embed's ?theme=light/dark (SDK colorScheme) request. Reorder so an explicit
override always wins, which is the only reliable way to force the scheme from
a mobile webview that can't run JS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MN7HAu1vHzuFeND4UCRCBo
This commit is contained in:
Claude
2026-07-10 00:21:00 +00:00
parent 49d35aa026
commit 09ef328357
3 changed files with 36 additions and 10 deletions
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Embed: an explicit `?theme=light` / `?theme=dark` (the SDK `colorScheme` option) now reliably forces the embed's color scheme, even on sites where the theme toggle is disabled. Previously single-theme sites ignored the requested scheme.
+19 -2
View File
@@ -146,14 +146,31 @@ describe('resolveEmbeddableTheme', () => {
});
});
it('keeps the site theme for single-theme sites', () => {
it('keeps the site theme for single-theme sites without an override', () => {
expect(
resolveEmbeddableTheme(
createCustomization({
toggeable: false,
default: CustomizationDefaultThemeMode.Light,
})
)
).toEqual({
htmlTheme: CustomizationDefaultThemeMode.Light,
defaultTheme: CustomizationDefaultThemeMode.Light,
forcedTheme: CustomizationDefaultThemeMode.Light,
});
});
it('honors an explicit override on single-theme sites (RND-11571)', () => {
// A `?theme=light` embed on a site with the theme toggle disabled must still
// force the requested scheme, since a webview can only pass it via the URL.
expect(
resolveEmbeddableTheme(
createCustomization({
toggeable: false,
default: CustomizationDefaultThemeMode.Dark,
}),
CustomizationDefaultThemeMode.Dark
CustomizationDefaultThemeMode.Light
)
).toEqual({
htmlTheme: CustomizationDefaultThemeMode.Light,
+12 -8
View File
@@ -46,6 +46,18 @@ export function resolveEmbeddableTheme(
customization: Pick<SiteCustomizationSettings, 'themes'>,
forcedTheme?: CustomizationDefaultThemeMode | null
) {
// An explicit override (the embed's `?theme=` / `colorScheme` option) always wins, even for
// single-theme sites: the embedder is deliberately matching the color scheme of their own page,
// and a webview can only pass it via the URL. This must be checked before the toggeable branch,
// otherwise a site with the theme toggle disabled silently ignores the requested scheme. RND-11571
if (forcedTheme) {
return {
htmlTheme: forcedTheme,
defaultTheme: forcedTheme,
forcedTheme,
};
}
if (!customization.themes.toggeable) {
const mode = customization.themes.default;
return {
@@ -56,14 +68,6 @@ export function resolveEmbeddableTheme(
};
}
if (forcedTheme) {
return {
htmlTheme: forcedTheme,
defaultTheme: forcedTheme,
forcedTheme,
};
}
return {
htmlTheme: CustomizationDefaultThemeMode.System,
defaultTheme: CustomizationDefaultThemeMode.System,