diff --git a/.storybook/preview.js b/.storybook/preview.js index a8af2b9..3e48619 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -22,3 +22,7 @@ export const parameters = { export const decorators = [ cssVariablesTheme, ]; + +export const globals = { + cssVariables: null, +}; diff --git a/Readme.md b/Readme.md index f2df5f5..5e6d886 100644 --- a/Readme.md +++ b/Readme.md @@ -123,9 +123,10 @@ document.addEventListener( ### Set a Theme by Query String -Pass the theme to the url as a query by adding `&theme=mytheme` to the url. -If multi word theme query is `&theme=my%20theme` +Themes are stored in storybook globals. +Pass the theme to the url as a query by adding `&globals=cssVariables:mytheme` to the url. +If multi word theme query is `&globals=cssVariables:my+theme` --- diff --git a/package-lock.json b/package-lock.json index af834da..ad38296 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@etchteam/storybook-addon-css-variables-theme", - "version": "1.6.0", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 3df37b8..8e46431 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@etchteam/storybook-addon-css-variables-theme", - "version": "1.6.0", + "version": "2.0.0", "description": "Switch CSS files to change themes", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/index.ts b/src/index.ts index 00cf6a0..9090ceb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,4 @@ -/* eslint-disable react-hooks/rules-of-hooks */ - import { addons, makeDecorator } from '@storybook/addons'; -import queryString from 'query-string'; -import { useState } from 'react'; import { ADDON_PARAM_KEY, CLEAR_LABEL, EVENT_NAME } from './constants'; import getCookie from './getCookie'; @@ -59,6 +55,7 @@ export default makeDecorator({ wrapper: (getStory, context, { parameters }) => { const { files, theme, defaultTheme } = parameters; + const globalsTheme = context.globals.cssVariables; const channel = addons.getChannel(); const cookieId = getCookie('cssVariables'); // eslint-disable-next-line max-len @@ -67,22 +64,14 @@ export default makeDecorator({ (Object.hasOwnProperty.call(files, cookieId) || cookieId === CLEAR_LABEL) ? cookieId : null; - const parsed = queryString.parse(window.location.search); - let urlTheme: string | undefined; - if (parsed.theme) { - if (!Array.isArray(parsed.theme)) { - urlTheme = parsed.theme; - } - } - const themeToLoad = urlTheme || theme || savedTheme || defaultTheme; - const [themeId, setThemeId] = useState(themeToLoad); + + const themeToLoad = globalsTheme || theme || savedTheme || defaultTheme; handleStyleSwitch({ id: themeToLoad, files, save: !theme || !savedTheme }); channel.on('cssVariablesChange', ({ id }: { id: string }) => { handleStyleSwitch({ id, files, save: true }); - setThemeId(id); }); - return getStory({ ...context, themeId }); + return getStory(context); }, }); diff --git a/src/register.tsx b/src/register.tsx index cb6f126..12aeda9 100644 --- a/src/register.tsx +++ b/src/register.tsx @@ -1,5 +1,5 @@ import { addons, types } from '@storybook/addons'; -import { useChannel, useParameter } from '@storybook/api'; +import { useChannel, useParameter, useGlobals } from '@storybook/api'; import { Icons, IconButton, @@ -7,8 +7,7 @@ import { TooltipLinkList, } from '@storybook/components'; import { styled } from '@storybook/theming'; -import queryString from 'query-string'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import { ADDON_ID, ADDON_PARAM_KEY, CLEAR_LABEL } from './constants'; import getCookie from './getCookie'; @@ -43,27 +42,27 @@ const ActiveViewportLabel = styled.div(({ theme }) => ({ })); const Dropdown = () => { + const [globals, updateGlobals] = useGlobals(); const cookieTheme = getCookie('cssVariables'); const addonParams: Params = useParameter(ADDON_PARAM_KEY, {}); const { theme, defaultTheme, files } = addonParams; const id = files && Object.hasOwnProperty.call(files, cookieTheme) && cookieTheme; - const [selected, setSelected] = useState(theme || id); + + const selected = globals.cssVariables || theme || id; + const setSelected = (value: string | null) => { + updateGlobals({ + cssVariables: value, + }); + }; const emit = useChannel({}); - const parsed = queryString.parse(window.location.search); - let urlTheme: string | undefined; - if (parsed.theme) { - if (!Array.isArray(parsed.theme)) { - urlTheme = parsed.theme; - } - } useEffect(() => { if (!selected) { - setSelected(urlTheme || theme || id || defaultTheme); + setSelected(theme || id || defaultTheme); } - }, [selected, urlTheme, theme, defaultTheme, id]); + }, [selected, theme, defaultTheme, id]); function handleChange(onHide: () => void, value: string | null) { const newValue = value.indexOf(CLEAR_LABEL) > -1 ? CLEAR_LABEL : value; diff --git a/stories/Button.stories.tsx b/stories/Button.stories.tsx index 5985035..d35a934 100644 --- a/stories/Button.stories.tsx +++ b/stories/Button.stories.tsx @@ -14,7 +14,9 @@ export default { } as ComponentMeta; // More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args -const Template: ComponentStory = (args) =>