Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use storybook globals to store the current theme #55

Merged
merged 1 commit into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ export const parameters = {
export const decorators = [
cssVariablesTheme,
];

export const globals = {
cssVariables: null,
};
5 changes: 3 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

---

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
19 changes: 4 additions & 15 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
/* 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';

let currentCSS: any = null;

Check warning on line 6 in src/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

async function addBrandStyles(id: string, files: { [key: string]: any }) {

Check warning on line 8 in src/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
const file = files[id];
if (file) {
file.use();
Expand Down Expand Up @@ -40,7 +36,7 @@
save,
}: {
id: string;
files: { [key: string]: any };

Check warning on line 39 in src/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
save: boolean;
}) {
addBrandStyles(id, files);
Expand All @@ -59,6 +55,7 @@

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
Expand All @@ -67,22 +64,14 @@
(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);
},
});
25 changes: 12 additions & 13 deletions src/register.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { addons, types } from '@storybook/addons';
import { useChannel, useParameter } from '@storybook/api';
import { useChannel, useParameter, useGlobals } from '@storybook/api';
import {
Icons,
IconButton,
WithTooltip,
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';

type Files = {
[key: string]: any;

Check warning on line 16 in src/register.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
};

type Params = {
Expand Down Expand Up @@ -43,27 +42,27 @@
}));

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]);

Check warning on line 65 in src/register.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has a missing dependency: 'setSelected'. Either include it or remove the dependency array

function handleChange(onHide: () => void, value: string | null) {
const newValue = value.indexOf(CLEAR_LABEL) > -1 ? CLEAR_LABEL : value;
Expand All @@ -83,7 +82,7 @@

function generateLinks(items: Files, onHide: () => void) {
// eslint-disable-next-line max-len
const result: any[] = Object.keys(items).map((value) =>

Check warning on line 85 in src/register.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
toLink(value, value === selected, onHide),
);
if (selected !== CLEAR_LABEL && !defaultTheme) {
Expand Down
4 changes: 3 additions & 1 deletion stories/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export default {
} as ComponentMeta<typeof Button>;

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
const Template: ComponentStory<typeof Button> = (args) => {
return <Button {...args} />;
};

export const Primary = Template.bind({});
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Expand Down
Loading