From 869755ee6e2a5501608ff3678a74a89cc91991ad Mon Sep 17 00:00:00 2001 From: Einar Date: Fri, 12 Jun 2026 13:59:56 +0200 Subject: [PATCH] Sync Storybook manager UI and component theme with embedding docs site - Add manager.js that reads docsSiteTheme from the URL param and applies themes.dark/light to the Storybook manager UI via addons.setConfig. On STORYBOOK_THEME_CHANGE postMessages from the docs site it reloads the frame with the updated URL so the UI theme takes effect immediately. On STORY_RENDERED it relays the current theme to the preview via channel. - Fix preview.js to listen on the Storybook channel (addons.getChannel()) instead of window.addEventListener, which never fires in the preview frame since postMessages from the parent page go to the manager frame. Co-Authored-By: Claude Sonnet 4.6 --- Source/.storybook/manager.js | 30 ++++++++++++++++++++++++++++++ Source/.storybook/preview.js | 8 ++++---- 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 Source/.storybook/manager.js diff --git a/Source/.storybook/manager.js b/Source/.storybook/manager.js new file mode 100644 index 0000000..5a2ff8a --- /dev/null +++ b/Source/.storybook/manager.js @@ -0,0 +1,30 @@ +// Copyright (c) Cratis. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +import { addons } from 'storybook/manager-api'; +import { themes } from 'storybook/theming'; + +const urlParams = new URLSearchParams(window.location.search); +let currentTheme = urlParams.get('docsSiteTheme') ?? 'dark'; + +addons.setConfig({ + theme: currentTheme === 'light' ? themes.light : themes.dark, +}); + +// Relay the current theme to the preview canvas whenever a story renders, +// so the PrimeReact component theme stays in sync with the docs-site preference. +addons.getChannel().on('STORY_RENDERED', () => { + addons.getChannel().emit('STORYBOOK_THEME_CHANGE', { theme: currentTheme }); +}); + +// Receive theme-sync messages from the embedding docs site (StorybookEmbed.astro). +// Reload the manager with the new theme in the URL so addons.setConfig takes effect. +window.addEventListener('message', (event) => { + if (event.data?.type !== 'STORYBOOK_THEME_CHANGE') return; + const newTheme = event.data.theme; + if (currentTheme === newTheme) return; + currentTheme = newTheme; + const url = new URL(window.location.href); + url.searchParams.set('docsSiteTheme', newTheme); + window.location.href = url.toString(); +}); diff --git a/Source/.storybook/preview.js b/Source/.storybook/preview.js index 0541e09..8d43d14 100644 --- a/Source/.storybook/preview.js +++ b/Source/.storybook/preview.js @@ -1,6 +1,7 @@ // Copyright (c) Cratis. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +import { addons } from 'storybook/preview-api'; import React from 'react'; import 'primeicons/primeicons.css'; import './preview.css'; @@ -46,13 +47,12 @@ const ALL_BODY_CLASSES = Object.values(STYLING_MODES) .map(mode => mode.bodyClass) .filter(Boolean); -// Tracks the theme pushed from the embedding docs site via postMessage. +// Tracks the theme relayed from manager.js via the Storybook channel. // null means "not embedded — use the toolbar selection". let _docsSiteTheme = null; -window.addEventListener('message', (event) => { - if (event.data?.type !== 'STORYBOOK_THEME_CHANGE') return; - _docsSiteTheme = event.data.theme === 'light' ? 'lara-light' : 'lara-dark'; +addons.getChannel().on('STORYBOOK_THEME_CHANGE', ({ theme }) => { + _docsSiteTheme = theme === 'light' ? 'lara-light' : 'lara-dark'; const mode = STYLING_MODES[_docsSiteTheme]; if (mode) { applyThemeLink(mode.themeUrl);