Skip to content

Commit 12b6e7d

Browse files
committed
Upgrade to Storybook v7 with Vite
1 parent 3213735 commit 12b6e7d

File tree

15 files changed

+3370
-2504
lines changed

15 files changed

+3370
-2504
lines changed

.changeset/shiny-pans-sit.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/polaris': minor
3+
---
4+
5+
Upgrade to Storybook v7 with Vite
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import React from 'react';
2+
import {
3+
AddonPanel,
4+
Icons,
5+
IconButton,
6+
Placeholder,
7+
Link,
8+
} from '@storybook/components';
9+
import {PureArgsTable} from '@storybook/blocks';
10+
import {addons, types} from '@storybook/manager-api';
11+
import {styled} from '@storybook/theming';
12+
import {useGlobals} from '@storybook/api';
13+
14+
addons.register('global-controls', () => {
15+
addons.add('grid-options/panel', {
16+
type: types.PANEL,
17+
title: 'Grid',
18+
match: ({viewMode}) => viewMode === 'story',
19+
render: ({active, key}) => <GridPanel active={active} key={key} />,
20+
});
21+
addons.add('feature-flags/panel', {
22+
type: types.PANEL,
23+
title: 'Feature flags',
24+
match: ({viewMode}) => viewMode === 'story',
25+
render: ({active, key}) => <FeatureFlagPanel active={active} key={key} />,
26+
});
27+
addons.add('github/link', {
28+
type: types.TOOLEXTRA,
29+
title: 'GitHub',
30+
match: ({viewMode}) => viewMode === 'story' || viewMode === 'docs',
31+
render: GitHubToolbar,
32+
});
33+
});
34+
35+
export const featureFlagOptions = {
36+
// For example:
37+
// polarisSummerEditions2023: { // This name must match the name accepted by `AppProvider#features`
38+
// name: 'polarisSummerEditions2023',
39+
// description: 'Toggle the summer editions feature flag',
40+
// defaultValue: false,
41+
// control: {type: 'boolean'},
42+
// },
43+
};
44+
45+
export const gridOptions = {
46+
showGrid: {
47+
name: 'Show grid overlay',
48+
description: 'Show or hide a 4 / 12 column grid, overlaying components',
49+
defaultValue: false,
50+
control: {type: 'boolean'},
51+
},
52+
gridInFrame: {
53+
name: 'Grid in frame',
54+
description: 'Show grid within app frame context',
55+
defaultValue: false,
56+
control: {type: 'boolean'},
57+
},
58+
gridWidth: {
59+
name: 'Grid width',
60+
description: 'Set a max width for the grid overlay',
61+
default: '100%',
62+
control: {type: 'select'},
63+
options: ['560px', '768px', '1008px', '100%'],
64+
},
65+
gridLayer: {
66+
name: 'Grid layer',
67+
description: 'Set the grid layer above or below content',
68+
default: 'below',
69+
control: {type: 'select'},
70+
options: ['above', 'below'],
71+
},
72+
};
73+
74+
function GridPanel(props) {
75+
const [globals, updateGlobals] = useGlobals();
76+
77+
return (
78+
<AddonPanel {...props}>
79+
<PureArgsTable
80+
inAddonPanel
81+
rows={gridOptions}
82+
args={globals}
83+
updateArgs={updateGlobals}
84+
/>
85+
</AddonPanel>
86+
);
87+
}
88+
89+
function FeatureFlagPanel(props) {
90+
const [globals, updateGlobals] = useGlobals();
91+
return (
92+
<AddonPanel {...props}>
93+
{Object.keys(featureFlagOptions).length ? (
94+
<PureArgsTable
95+
inAddonPanel
96+
rows={featureFlagOptions}
97+
args={globals}
98+
updateArgs={updateGlobals}
99+
/>
100+
) : (
101+
<Placeholder>
102+
<p>No feature flags configured</p>
103+
<p>
104+
<Link
105+
withArrow
106+
href="https://github.com/search?q=repo%3AShopify%2Fpolaris+featureFlagOptions+path%3Apolaris-react%2F.storybook%2Faddons%2Fglobal-controls-panel%2Fmanager.jsx&type=code"
107+
>
108+
Edit configuration
109+
</Link>
110+
</p>
111+
</Placeholder>
112+
)}
113+
</AddonPanel>
114+
);
115+
}
116+
117+
const IconButtonLink = styled(IconButton)({
118+
textDecoration: 'none',
119+
});
120+
121+
function GitHubToolbar() {
122+
let link;
123+
let title;
124+
let buttonText;
125+
// All of the storybook manager leverages the `@storybook/builder-manager` package, which builds with esbuild under the hood, and not vite.
126+
// This means that we can't use the `import.meta.env` syntax to access environment variables.
127+
// See https://github.com/storybookjs/storybook/blob/d112cbac280f23530b366918b9d54818006db963/code/builders/builder-manager/src/index.ts#L103
128+
if (process.env.STORYBOOK_GITHUB_REPO_URL) {
129+
link = `${process.env.STORYBOOK_GITHUB_REPO_URL}`;
130+
title = 'View source on GitHub';
131+
buttonText = 'GitHub';
132+
if (process.env.STORYBOOK_GITHUB_PR) {
133+
link = `${link}/pull/${process.env.STORYBOOK_GITHUB_PR}`;
134+
title = `Built from PR #${process.env.STORYBOOK_GITHUB_PR}`;
135+
buttonText = `PR #${process.env.STORYBOOK_GITHUB_PR}`;
136+
} else if (process.env.STORYBOOK_GITHUB_SHA) {
137+
link = `${link}/commit/${process.env.STORYBOOK_GITHUB_SHA}`;
138+
title = `Built from commit ${process.env.STORYBOOK_GITHUB_SHA}`;
139+
buttonText = <code>{process.env.STORYBOOK_GITHUB_SHA.slice(0, 7)}</code>;
140+
}
141+
}
142+
143+
return link ? (
144+
<IconButtonLink as="a" href={link} title={title} target="_blank">
145+
<Icons icon="github" />
146+
&nbsp;{buttonText}
147+
</IconButtonLink>
148+
) : null;
149+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
function managerEntries(entry = []) {
2+
// Unfortunately have to do this dance for Storybook v7 to load our addon
3+
return [...entry, require.resolve('./manager')];
4+
}
5+
6+
export default {managerEntries};

polaris-react/.storybook/main.js

+44-48
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
const path = require('path');
2-
const spawn = require('child_process').spawn;
3-
const CreateFileWebpack = require('create-file-webpack');
4-
const postcssPlugins = require('../config/postcss-plugins');
5-
const {generateScopedName} = require('../config/rollup/namespaced-classname');
6-
7-
const moduleIdentCreator = generateScopedName({includeHash: true});
1+
import path from 'node:path';
2+
import {mergeConfig} from 'vite';
83

94
module.exports = {
5+
framework: '@storybook/react-vite',
106
core: {
11-
builder: 'webpack5',
7+
disableTelemetry: true,
128
},
139
stories: [
1410
{
@@ -25,47 +21,47 @@ module.exports = {
2521
'@storybook/addon-a11y',
2622
'@storybook/addon-toolbars',
2723
'@storybook/addon-viewport',
24+
'./addons/global-controls-panel/preset.js',
2825
],
29-
webpackFinal: (config) => {
30-
const extraRules = [
31-
{
32-
test: /\.scss$/,
33-
use: [
34-
{
35-
loader: 'style-loader',
36-
},
37-
{
38-
loader: 'css-loader',
39-
options: {
40-
importLoaders: 1,
41-
modules: {
42-
getLocalIdent: ({resourcePath}, _, localName) =>
43-
moduleIdentCreator(localName, resourcePath),
44-
auto: true,
45-
},
46-
},
47-
},
48-
{
49-
loader: 'postcss-loader',
50-
options: {
51-
postcssOptions: {
52-
plugins: postcssPlugins,
53-
},
54-
},
55-
},
56-
{
57-
loader: 'sass-loader',
58-
},
59-
],
60-
},
61-
];
62-
63-
config.module.rules = [...config.module.rules, ...extraRules];
26+
// This Vite config is only used by Storybook for building the preview iframe
27+
// (ie; the code in our stories and preview.jsx). This does not apply to the
28+
// add-ons and any other storybook UI code.
6429

65-
config.resolve.alias = {
66-
...config.resolve.alias,
67-
'@shopify/polaris': path.resolve(__dirname, '..', 'src'),
68-
};
69-
return config;
30+
// The config argument passed to viteFinal is a merge of the default storybook
31+
// vite config, and the config specified in our `polaris-react/vite.config.js`
32+
// file.
33+
async viteFinal(config) {
34+
return mergeConfig(config, {
35+
define: {
36+
// Set any environment variables here. At this point we're able to
37+
// access env vars used when Storybook was built / run. After this,
38+
// `process.env` becomes unavailable (ie; if we want to change the
39+
// behaviour of a storybook addon based on an environment variable).
40+
// Environment variables set here are available as `import.meta.env.*`
41+
// and will be a literal string replacement.
42+
// For example, to forcibly enable a feature flag, add this config:
43+
// 'process.env.FEATURE': JSON.stringify(process.env.FEATURE) ?? 'undefined',
44+
// Then edit `polaris-react/.storybook/preview.jsx` to read
45+
// `import.meta.env.FEATURE` and pass the value to `AppProvider`.
46+
},
47+
resolve: {
48+
alias: {
49+
// Stories import `@shopify/polaris` so they match the actual code
50+
// people will write. But when running in storybook, we want to use
51+
// the actual source code (not the built code) to avoid running build
52+
// twice (once to build Polaris, then again in storybook).
53+
'@shopify/polaris': path.resolve(__dirname, '..', 'src'),
54+
// Similarly, we want to link against the src version of
55+
// polaris-patterns
56+
'@shopify/polaris-patterns': path.resolve(
57+
__dirname,
58+
'..',
59+
'..',
60+
'polaris-patterns',
61+
'src',
62+
),
63+
},
64+
},
65+
});
7066
},
7167
};

0 commit comments

Comments
 (0)