storybook-addon-data-theme-switcher
Version:
A Storybook addon to switch the data-theme attribute on the html element
48 lines (47 loc) • 1.66 kB
JavaScript
import { useEffect, useGlobals, useRef } from "storybook/preview-api";
//#region src/constants.ts
const ADDON_ID = "storybook/addon-data-theme-switcher";
`${ADDON_ID}`;
`${ADDON_ID}`;
const DATA_THEME_KEY = "dataTheme";
//#endregion
//#region src/withGlobals.ts
const withGlobals = (StoryFn) => {
const [globals, updateGlobals] = useGlobals();
const dataTheme = globals[DATA_THEME_KEY];
const dataAttribute = globals["dataThemes"]?.dataAttribute || "data-theme";
const lastSetValue = useRef(null);
if (!dataTheme || dataTheme === "none") {
document.documentElement.removeAttribute(dataAttribute);
globalThis.localStorage.removeItem(dataAttribute);
lastSetValue.current = null;
} else {
document.documentElement.setAttribute(dataAttribute, dataTheme);
globalThis.localStorage.setItem(dataAttribute, dataTheme);
lastSetValue.current = dataTheme;
}
useEffect(() => {
const observer = new MutationObserver(() => {
const currentValue = document.documentElement.getAttribute(dataAttribute);
if (currentValue !== lastSetValue.current) {
lastSetValue.current = currentValue;
updateGlobals({ [DATA_THEME_KEY]: currentValue ?? "none" });
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: [dataAttribute]
});
return () => observer.disconnect();
}, [dataAttribute, updateGlobals]);
return StoryFn();
};
//#endregion
//#region src/preset/preview.ts
/**
* Note: if you want to use JSX in this file, rename it to `preview.tsx`
* and update the entry prop in tsup.config.ts to use "src/preview.tsx",
*/
const preview = { decorators: [withGlobals] };
//#endregion
export { preview as t };