storybook-addon-themes
storybook-addon-themes copied to clipboard
Theme support for mdx story files
We have a number of themes and aligned to this a number of document only pages that just give details about the design. The idea is that a theme will have a document only pages in mdx format - for instance, the colors, but the colors are preset and are not changeable, they are there for reference to developers. Hence having a story is "overkill" as we would use the story variant as a "theme" to switch the different colors.
We where hoping to use the theme switcher to trigger a change of the color documentation. However, theme switcher doesn't seem to trigger on the theme change so there is no decorator invoked.
We attempted to use the onChange
function but this doesn't appear to work in the sense that there is no this
context provided so we cannot access anything.
Is there a way of using theme switcher with mdx files?
Using Storybook 7, found out that the theme selector addon was present on the toolbar in documents (.mdx) but wasn't working.
A workaround for this is to make use of the URL GET parameter which is triggering the theme switch: globals=theme:Theme1
Changes in preview.js
In my case, I was relying on data-attibute which was applied on the <html>
in each story/doc etc like this: [data-theme="AAA"]
. In case you defined your themes inside the decorator, try to have them in a const
in order to use it in your .mdx
files, and pass the object to your decorator like so:
import { withThemeByDataAttribute } from '@storybook/addon-themes';
export const themeConfig = {
themes: {
Theme1: 'AAA',
Theme2: 'BBB',
Theme3: 'CCC',
},
defaultTheme: 'Theme1',
};
export const decorators = [
withThemeByDataAttribute({
...themeConfig,
attributeName: 'data-theme',
}),
];
Then create a themeSwitcher.js
inside your assets where you need to import the themeConfig
from your preview.js
and use the MutationObserver
to observe the URL changes.
Once the URL is changed, switch the theme by extracting the value from your themeConfig
object, based on the key taken from URL and set the data-theme
attribute on your document.
import { themeConfig } from '../../.storybook/preview';
function themeSwitcher() {
let previousUrl = '';
const observer = new MutationObserver(function() {
if (window.location.href !== previousUrl) {
switchTheme();
}
});
const config = {subtree: true, childList: true};
observer.observe(document, config);
}
function findGetParameter(parameterName) {
var result = null,
tmp = [];
location.search
.substr(1)
.split("&")
.forEach(function (item) {
tmp = item.split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
});
return result;
}
function switchTheme(){
const requestTheme = findGetParameter("globals");
if (requestTheme === null)
return;
const themeName = requestTheme.split(":")[1];
if (document.documentElement.dataset.theme === themeConfig.themes[themeName])
return;
document.documentElement.setAttribute('data-theme', themeConfig.themes[themeName]);
}
themeSwitcher()
Then all you need to do, is to import the themeSwitcher
in your mdx files.
import '../assets/themeSwitcher';