Skip to content

Commit fe3c0a8

Browse files
siddharthkpmperrotti
authored andcommitted
Move theme decorator into helper util (primer#2044)
* Move theme decorator into helper util * fix height * is addons import the problem? * does this work better for consumer-tests? * yep, deep import doesn't work either * add option to disable theme decorator on a story level Co-authored-by: Mike Perrotti <mperrotti@github.com>
1 parent bb1681b commit fe3c0a8

File tree

3 files changed

+89
-117
lines changed

3 files changed

+89
-117
lines changed

.storybook/main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module.exports = {
33
addons: [
44
'@storybook/addon-a11y',
55
'@storybook/addon-links',
6-
'@storybook/addon-essentials',
6+
{name: '@storybook/addon-essentials', options: {backgrounds: false}},
77
'storybook-addon-performance/register',
88
...(process.env.NODE_ENV === 'production' && process.env.GITHUB_JOB !== 'chromatic'
99
? ['@whitespace/storybook-addon-html']
@@ -13,4 +13,4 @@ module.exports = {
1313
options.plugins.push(['open-source', {editor: process.env.NODE_ENV === 'production' ? 'github' : 'vscode'}])
1414
return options
1515
}
16-
}
16+
}

.storybook/preview.js

Lines changed: 2 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,8 @@
11
import {addons} from '@storybook/addons'
2-
import {ThemeProvider, themeGet, theme, BaseStyles} from '../src'
3-
import styled, {createGlobalStyle} from 'styled-components'
4-
import {addDecorator} from '@storybook/react'
52
import {withPerformance} from 'storybook-addon-performance'
3+
import {withThemeProvider, toolbarTypes} from '../src/utils/story-helpers'
64

7-
addDecorator(withPerformance)
8-
9-
// set global theme styles for each story
10-
const GlobalStyle = createGlobalStyle`
11-
body {
12-
background-color: ${themeGet('colors.canvas.default')};
13-
color: ${themeGet('colors.fg.default')};
14-
}
15-
`
16-
17-
// only remove padding for multi-theme view grid
18-
const GlobalStyleMultiTheme = createGlobalStyle`
19-
body {
20-
padding: 0 !important;
21-
}
22-
`
23-
24-
// duo theme view, this can be extended for more themes
25-
const Wrapper = styled.div`
26-
display: grid;
27-
grid-template-columns: 1fr 1fr;
28-
grid-template-rows: 100vh;
29-
`
30-
31-
// instead of global theme, only theme wrapper for each story
32-
const ThemedSectionStyle = styled.div`
33-
background-color: ${themeGet('colors.canvas.default')};
34-
color: ${themeGet('colors.fg.default')};
35-
padding: 1rem;
36-
`
37-
38-
export const globalTypes = {
39-
colorMode: {
40-
name: 'Color mode',
41-
description: 'Color mode (day, night, auto, all)',
42-
defaultValue: 'day',
43-
toolbar: {
44-
icon: 'paintbrush',
45-
// array of colorMode items
46-
items: ['day', 'night', 'auto', 'all'],
47-
showName: true
48-
}
49-
},
50-
dayScheme: {
51-
name: 'Day color scheme',
52-
description: 'Day color scheme',
53-
defaultValue: 'light',
54-
toolbar: {
55-
icon: 'circlehollow',
56-
items: Object.keys(theme.colorSchemes),
57-
showName: true
58-
}
59-
},
60-
nightScheme: {
61-
name: 'Night color scheme',
62-
description: 'Night color scheme',
63-
defaultValue: 'dark',
64-
toolbar: {
65-
icon: 'circle',
66-
items: Object.keys(theme.colorSchemes),
67-
showName: true
68-
}
69-
}
70-
}
71-
72-
// context.globals.X references items in globalTypes
73-
const withThemeProvider = (Story, context) => {
74-
// used for testing ThemeProvider.stories.tsx
75-
if (context.parameters.disableThemeDecorator) return <Story {...context} />
76-
77-
if (context.globals.colorMode === 'all') {
78-
return (
79-
<Wrapper>
80-
<GlobalStyleMultiTheme />
81-
<ThemeProvider colorMode="day" dayScheme={context.globals.dayScheme} nightScheme={context.globals.nightScheme}>
82-
<ThemedSectionStyle>
83-
<Story {...context} />
84-
</ThemedSectionStyle>
85-
</ThemeProvider>
86-
<ThemeProvider
87-
colorMode="night"
88-
dayScheme={context.globals.dayScheme}
89-
nightScheme={context.globals.nightScheme}
90-
>
91-
<ThemedSectionStyle>
92-
<BaseStyles>
93-
<div id="html-addon-root">
94-
<Story {...context} />
95-
</div>
96-
</BaseStyles>
97-
</ThemedSectionStyle>
98-
</ThemeProvider>
99-
</Wrapper>
100-
)
101-
}
102-
103-
return (
104-
<ThemeProvider
105-
colorMode={context.globals.colorMode}
106-
dayScheme={context.globals.dayScheme}
107-
nightScheme={context.globals.nightScheme}
108-
>
109-
<GlobalStyle />
110-
<BaseStyles>
111-
<div id="html-addon-root">
112-
<Story {...context} />
113-
</div>
114-
</BaseStyles>
115-
</ThemeProvider>
116-
)
117-
}
118-
5+
export const globalTypes = toolbarTypes
1196
export const decorators = [withThemeProvider, withPerformance]
1207

1218
addons.setConfig({

src/utils/story-helpers.tsx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import React from 'react'
2+
import {Box, ThemeProvider, theme, themeGet, BaseStyles} from '../index'
3+
import {createGlobalStyle} from 'styled-components'
4+
5+
// set global theme styles for each story
6+
const GlobalStyle = createGlobalStyle`
7+
body {
8+
background-color: ${themeGet('colors.canvas.default')};
9+
color: ${themeGet('colors.fg.default')};
10+
}
11+
`
12+
13+
// only remove padding for multi-theme view grid
14+
const GlobalStyleMultiTheme = createGlobalStyle`
15+
body {
16+
padding: 0 !important;
17+
}
18+
`
19+
20+
// we don't import StoryContext from storybook because of exports that conflict
21+
// with primer/react more: https://github.com/primer/react/runs/6129115026?check_suite_focus=true
22+
type StoryContext = Record<string, unknown> & {globals: {colorScheme: string}; parameters: Record<string, unknown>}
23+
24+
export const withThemeProvider = (Story: React.FC<StoryContext>, context: StoryContext) => {
25+
// used for testing ThemeProvider.stories.tsx
26+
if (context.parameters.disableThemeDecorator) return <Story {...context} />
27+
28+
const {colorScheme} = context.globals
29+
30+
if (colorScheme === 'all') {
31+
return (
32+
<Box
33+
sx={{
34+
display: 'grid',
35+
gridTemplateColumns: 'repeat(auto-fit, minmax(0, 1fr))',
36+
height: '100vh'
37+
}}
38+
>
39+
<GlobalStyleMultiTheme />
40+
{Object.keys(theme.colorSchemes).map(scheme => (
41+
<ThemeProvider key={scheme} colorMode="day" dayScheme={scheme}>
42+
<BaseStyles>
43+
<Box
44+
sx={{
45+
padding: '1rem',
46+
height: '100%',
47+
backgroundColor: 'canvas.default',
48+
color: 'fg.default'
49+
}}
50+
>
51+
<div id={`html-addon-root-${scheme}`}>
52+
<Story {...context} />
53+
</div>
54+
</Box>
55+
</BaseStyles>
56+
</ThemeProvider>
57+
))}
58+
</Box>
59+
)
60+
}
61+
62+
return (
63+
<ThemeProvider colorMode="day" dayScheme={colorScheme}>
64+
<GlobalStyle />
65+
<BaseStyles>
66+
<div id="html-addon-root">
67+
<Story {...context} />
68+
</div>
69+
</BaseStyles>
70+
</ThemeProvider>
71+
)
72+
}
73+
74+
export const toolbarTypes = {
75+
colorScheme: {
76+
name: 'Color scheme',
77+
description: 'Switch color scheme',
78+
defaultValue: 'light',
79+
toolbar: {
80+
icon: 'photo',
81+
items: [...Object.keys(theme.colorSchemes), 'all'],
82+
showName: true
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)