Skip to content

Commit 06f3575

Browse files
committed
feat(storybook): Reimplement "Themes" add on with React95 style
This also upgrades many dependencies and removes storybook-addon-styled-component-theme.
1 parent 5abcb3e commit 06f3575

File tree

17 files changed

+1446
-1118
lines changed

17 files changed

+1446
-1118
lines changed

.babelrc

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,6 @@
11
{
22
"presets": [
3-
[
4-
"@babel/preset-env",
5-
{
6-
"modules": false
7-
}
8-
],
9-
"@babel/preset-react"
10-
],
11-
"plugins": [
12-
"babel-plugin-styled-components",
13-
"@babel/plugin-proposal-class-properties",
14-
"@babel/plugin-transform-runtime"
15-
],
16-
"env": {
17-
"test": {
18-
"presets": ["@babel/preset-env"],
19-
"plugins": [
20-
["babel-plugin-styled-components", { "ssr": false, "displayName": false }]
21-
]
22-
}
23-
}
3+
"@babel/preset-env",
4+
"@babel/preset-typescript"
5+
]
246
}

.storybook/decorators/globalStyle.js renamed to .storybook/decorators/withGlobalStyle.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { DecoratorFn } from '@storybook/react';
12
import React from 'react';
23
import { createGlobalStyle } from 'styled-components';
34

4-
import styleReset from '../../src/common/styleReset';
5-
// TODO is there a way to keep import paths consistent with what end user will get?
65
import ms_sans_serif from '../../src/assets/fonts/dist/ms_sans_serif.woff2';
76
import ms_sans_serif_bold from '../../src/assets/fonts/dist/ms_sans_serif_bold.woff2';
7+
import styleReset from '../../src/common/styleReset';
88

99
const GlobalStyle = createGlobalStyle`
1010
${styleReset}
@@ -25,9 +25,9 @@ const GlobalStyle = createGlobalStyle`
2525
}
2626
`;
2727

28-
export default storyFn => (
28+
export const withGlobalStyle: DecoratorFn = story => (
2929
<>
3030
<GlobalStyle />
31-
{storyFn()}
31+
{story()}
3232
</>
3333
);

.storybook/main.js

Lines changed: 0 additions & 29 deletions
This file was deleted.

.storybook/main.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import type { StorybookConfig } from '@storybook/react/types';
2+
import type { PropItem } from 'react-docgen-typescript';
3+
4+
const path = require('path');
5+
6+
const storybookConfig: StorybookConfig = {
7+
stories: ['../src/**/*.stories.@(tsx|mdx)'],
8+
addons: [
9+
{
10+
name: '@storybook/addon-docs',
11+
options: {
12+
sourceLoaderOptions: {
13+
injectStoryParameters: false
14+
}
15+
}
16+
},
17+
'@storybook/addon-storysource',
18+
'./theme-picker/register'
19+
],
20+
core: {
21+
builder: 'webpack5'
22+
},
23+
features: {
24+
postcss: false
25+
},
26+
typescript: {
27+
check: false,
28+
checkOptions: {},
29+
reactDocgen: 'react-docgen-typescript',
30+
reactDocgenTypescriptOptions: {
31+
shouldExtractLiteralValuesFromEnum: true,
32+
propFilter: (prop: PropItem) =>
33+
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true
34+
}
35+
},
36+
webpackFinal: config => {
37+
config.resolve = {
38+
...config.resolve,
39+
alias: {
40+
...config.resolve?.alias,
41+
react95: path.resolve(__dirname, '../src/index')
42+
}
43+
};
44+
45+
return config;
46+
}
47+
};
48+
49+
module.exports = storybookConfig;
File renamed without changes.

.storybook/preview.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

.storybook/preview.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { DecoratorFn, Parameters } from '@storybook/react';
2+
import { withGlobalStyle } from './decorators/withGlobalStyle';
3+
import { withThemesProvider } from './theme-picker/ThemeProvider';
4+
5+
export const decorators: DecoratorFn[] = [withGlobalStyle, withThemesProvider];
6+
7+
export const parameters: Parameters = {
8+
layout: 'fullscreen'
9+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React, { useCallback } from 'react';
2+
import { ThemeProvider } from 'styled-components';
3+
import { Button } from '../../src/Button/Button';
4+
import { Theme } from '../../src/types';
5+
6+
export function ThemeButton({
7+
active,
8+
onChoose,
9+
theme
10+
}: {
11+
active: boolean;
12+
onChoose: (themeName: string) => void;
13+
theme: Theme;
14+
}) {
15+
const handleClick = useCallback(() => {
16+
onChoose(theme.name);
17+
}, []);
18+
19+
return (
20+
<ThemeProvider theme={theme}>
21+
<Button active={active} onClick={handleClick}>
22+
{theme.name}
23+
</Button>
24+
</ThemeProvider>
25+
);
26+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { useAddonState } from '@storybook/api';
2+
import React, { useCallback } from 'react';
3+
import styled from 'styled-components';
4+
5+
import themes from '../../src/common/themes';
6+
import { Theme } from '../../src/types';
7+
import { THEMES_ID } from './register';
8+
import { ThemeButton } from './ThemeButton';
9+
10+
const {
11+
original,
12+
rainyDay,
13+
vaporTeal,
14+
theSixtiesUSA,
15+
olive,
16+
tokyoDark,
17+
rose,
18+
plum,
19+
matrix,
20+
travel,
21+
...otherThemes
22+
} = themes;
23+
24+
const themeList = [
25+
original,
26+
rainyDay,
27+
vaporTeal,
28+
theSixtiesUSA,
29+
olive,
30+
tokyoDark,
31+
rose,
32+
plum,
33+
matrix,
34+
travel,
35+
...Object.values(otherThemes)
36+
];
37+
38+
type ThemesProps = {
39+
active?: boolean;
40+
};
41+
42+
const Wrapper = styled.div<{ theme: Theme }>`
43+
display: grid;
44+
padding: 1em;
45+
gap: 1em;
46+
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
47+
grid-template-rows: repeat(auto-fill, 40px);
48+
background-color: ${({ theme }) => theme.material};
49+
`;
50+
51+
export function ThemeList({ active }: ThemesProps) {
52+
const [themeName, setThemeName] = useAddonState(THEMES_ID, 'original');
53+
54+
const handleChoose = useCallback(
55+
(newThemeName: string) => {
56+
setThemeName(newThemeName);
57+
},
58+
[setThemeName]
59+
);
60+
61+
if (!active) {
62+
return null;
63+
}
64+
65+
return (
66+
<Wrapper theme={themes.original}>
67+
{themeList.map(theme => (
68+
<ThemeButton
69+
active={themeName === theme.name}
70+
key={theme.name}
71+
onChoose={handleChoose}
72+
theme={theme}
73+
/>
74+
))}
75+
</Wrapper>
76+
);
77+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { useAddonState } from '@storybook/client-api';
2+
import { DecoratorFn } from '@storybook/react';
3+
import React from 'react';
4+
import { ThemeProvider } from 'styled-components';
5+
6+
import themes from '../../src/common/themes/index';
7+
import { THEMES_ID } from './register';
8+
9+
export const withThemesProvider: DecoratorFn = story => {
10+
const [themeName] = useAddonState(THEMES_ID, 'original');
11+
12+
return (
13+
<ThemeProvider theme={themes[themeName] ?? themes.original}>
14+
{story()}
15+
</ThemeProvider>
16+
);
17+
};

0 commit comments

Comments
 (0)