Skip to content

Commit 99c9adf

Browse files
committed
Upgrade to Storybook v7 with Vite
1 parent 84221f9 commit 99c9adf

15 files changed

+2089
-2181
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,58 @@
1+
import React from 'react';
2+
import {AddonPanel} from '@storybook/components';
3+
import {PureArgsTable} from '@storybook/blocks';
4+
import {addons, types} from '@storybook/manager-api';
5+
import {useGlobals} from '@storybook/api';
6+
7+
addons.register('global-controls', () => {
8+
addons.add('global-controls/panel', {
9+
type: types.PANEL,
10+
title: 'Grid',
11+
match: ({viewMode}) => viewMode === 'story',
12+
render: ({active, key}) => <GridPanel active={active} key={key} />,
13+
});
14+
});
15+
16+
export const gridOptions = {
17+
showGrid: {
18+
name: 'Show grid overlay',
19+
description: 'Show or hide a 4 / 12 column grid, overlaying components',
20+
defaultValue: false,
21+
control: {type: 'boolean'},
22+
},
23+
gridInFrame: {
24+
name: 'Grid in frame',
25+
description: 'Show grid within app frame context',
26+
defaultValue: false,
27+
control: {type: 'boolean'},
28+
},
29+
gridWidth: {
30+
name: 'Grid width',
31+
description: 'Set a max width for the grid overlay',
32+
default: '100%',
33+
control: {type: 'select'},
34+
options: ['560px', '768px', '1008px', '100%'],
35+
},
36+
gridLayer: {
37+
name: 'Grid layer',
38+
description: 'Set the grid layer above or below content',
39+
default: 'below',
40+
control: {type: 'select'},
41+
options: ['above', 'below'],
42+
},
43+
};
44+
45+
function GridPanel(props) {
46+
const [globals, updateGlobals] = useGlobals();
47+
48+
return (
49+
<AddonPanel {...props}>
50+
<PureArgsTable
51+
inAddonPanel
52+
rows={gridOptions}
53+
args={globals}
54+
updateArgs={updateGlobals}
55+
/>
56+
</AddonPanel>
57+
);
58+
}
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

+25-46
Original file line numberDiff line numberDiff line change
@@ -1,11 +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');
1+
import path from 'node:path';
2+
import {mergeConfig} from 'vite';
53

64
module.exports = {
5+
framework: '@storybook/react-vite',
76
core: {
8-
builder: 'webpack5',
7+
disableTelemetry: true,
98
},
109
stories: [
1110
{
@@ -22,48 +21,28 @@ module.exports = {
2221
'@storybook/addon-a11y',
2322
'@storybook/addon-toolbars',
2423
'@storybook/addon-viewport',
24+
'./addons/global-controls-panel/preset.js',
2525
],
26-
webpackFinal: (config) => {
27-
const extraRules = [
28-
{
29-
test: /\.scss$/,
30-
use: [
31-
{
32-
loader: 'style-loader',
33-
},
34-
{
35-
loader: 'css-loader',
36-
options: {
37-
importLoaders: 1,
38-
modules: {
39-
localIdentName: '[name]-[local]_[hash:base64:5]',
40-
auto: (resourcePath) => {
41-
return !resourcePath.includes('global');
42-
},
43-
},
44-
},
45-
},
46-
{
47-
loader: 'postcss-loader',
48-
options: {
49-
postcssOptions: {
50-
plugins: postcssPlugins,
51-
},
52-
},
53-
},
54-
{
55-
loader: 'sass-loader',
56-
},
57-
],
26+
async viteFinal(config) {
27+
return mergeConfig(config, {
28+
resolve: {
29+
alias: {
30+
// Stories import `@shopify/polaris` so they match the actual code
31+
// people will write. But when running in storybook, we want to use
32+
// the actual source code (not the built code) to avoid running build
33+
// twice (once to build Polaris, then again in storybook).
34+
'@shopify/polaris': path.resolve(__dirname, '..', 'src'),
35+
// Similarly, we want to link against the src version of
36+
// polaris-patterns
37+
'@shopify/polaris-patterns': path.resolve(
38+
__dirname,
39+
'..',
40+
'..',
41+
'polaris-patterns',
42+
'src',
43+
),
44+
},
5845
},
59-
];
60-
61-
config.module.rules = [...config.module.rules, ...extraRules];
62-
63-
config.resolve.alias = {
64-
...config.resolve.alias,
65-
'@shopify/polaris': path.resolve(__dirname, '..', 'src'),
66-
};
67-
return config;
46+
});
6847
},
6948
};

polaris-react/.storybook/manager.js

+1-57
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import React from 'react';
2-
import {AddonPanel, ArgsTable} from '@storybook/components';
3-
import {addons, types} from '@storybook/addons';
4-
import {useGlobals} from '@storybook/api';
1+
import {addons} from '@storybook/manager-api';
52
import {create} from '@storybook/theming';
63

74
const colors = {
@@ -49,56 +46,3 @@ addons.setConfig({
4946
inputBorderRadius: 4,
5047
}),
5148
});
52-
53-
addons.register('polaris/global-controls', () => {
54-
addons.add('grid/panel', {
55-
type: types.PANEL,
56-
title: 'Grid',
57-
match: ({viewMode}) => viewMode === 'story',
58-
render: ({active, key}) => <GridPanel active={active} key={key} />,
59-
});
60-
});
61-
62-
export const gridOptions = {
63-
showGrid: {
64-
name: 'Show grid overlay',
65-
description: 'Show or hide a 4 / 12 column grid, overlaying components',
66-
defaultValue: false,
67-
control: {type: 'boolean'},
68-
},
69-
gridInFrame: {
70-
name: 'Grid in frame',
71-
description: 'Show grid within app frame context',
72-
defaultValue: false,
73-
control: {type: 'boolean'},
74-
},
75-
gridWidth: {
76-
name: 'Grid width',
77-
description: 'Set a max width for the grid overlay',
78-
default: '100%',
79-
control: {type: 'select'},
80-
options: ['560px', '768px', '1008px', '100%'],
81-
},
82-
gridLayer: {
83-
name: 'Grid layer',
84-
description: 'Set the grid layer above or below content',
85-
default: 'below',
86-
control: {type: 'select'},
87-
options: ['above', 'below'],
88-
},
89-
};
90-
91-
function GridPanel(props) {
92-
const [globals, updateGlobals] = useGlobals();
93-
94-
return (
95-
<AddonPanel {...props}>
96-
<ArgsTable
97-
inAddonPanel
98-
rows={gridOptions}
99-
args={globals}
100-
updateArgs={updateGlobals}
101-
/>
102-
</AddonPanel>
103-
);
104-
}

polaris-react/.storybook/preview.js polaris-react/.storybook/preview.jsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {AppProvider} from '../src';
44
import enTranslations from '../locales/en.json';
55
import {GridOverlay} from './GridOverlay';
66
import {RenderPerformanceProfiler} from './RenderPerformanceProfiler';
7-
import {gridOptions} from './manager';
7+
import {gridOptions} from './addons/global-controls-panel/manager';
88
import {breakpoints} from '@shopify/polaris-tokens';
99

1010
function StrictModeDecorator(Story, context) {
@@ -64,7 +64,7 @@ export const globalTypes = {
6464
{title: 'Disabled', value: false},
6565
{title: 'Enabled', value: true},
6666
],
67-
showName: true,
67+
title: 'React.StrictMode',
6868
},
6969
},
7070
profiler: {
@@ -75,7 +75,7 @@ export const globalTypes = {
7575
{title: 'Disabled', value: false},
7676
{title: 'Enabled', value: true},
7777
],
78-
showName: true,
78+
title: 'React.Profiler',
7979
},
8080
},
8181
...gridOptions,

polaris-react/config/rollup/namespaced-classname.js polaris-react/config/rollup/namespaced-classname.mjs

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
const {basename} = require('path');
1+
import {basename} from 'path';
22

3-
const {camelCase} = require('change-case');
3+
import {camelCase} from 'change-case';
44

55
const COMPONENT_REGEX = /^[A-Z]\w+$/;
66
const SUBCOMPONENT_VARIATION_SELECTOR = /^\w+-\w+$/;
77
const NESTED_COMPONENT_PATH_REGEX = /.*\/components\/(.*)\/components/;
88

9-
module.exports.generateScopedName = function generateScopedName({
9+
export const generateScopedName = function generateScopedName({
1010
includeHash = false,
1111
} = {}) {
1212
return (name, filename) => {
13-
const componentName = basename(filename, '.scss');
14-
const nestedComponentMatch = NESTED_COMPONENT_PATH_REGEX.exec(filename);
13+
// Vite's esbuild appends query params to files under certain circumstances,
14+
// so we clean those off in order to get the actual file name.
15+
const cleanedFilename = filename.replace(/\?.*$/, '');
16+
const componentName = basename(cleanedFilename, '.module.scss');
17+
const nestedComponentMatch =
18+
NESTED_COMPONENT_PATH_REGEX.exec(cleanedFilename);
1519

1620
const polarisComponentName =
1721
nestedComponentMatch && nestedComponentMatch.length > 1

polaris-react/config/rollup/plugin-styles.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ module.exports.styles = function styles({
5252
function transformEsNext(rollup, id, postCssOutput) {
5353
const relativePath = `./${path.relative(
5454
path.dirname(id),
55-
id.replace(/\.scss$/, processedExt),
55+
id.replace(/(\.module)?.scss$/, processedExt),
5656
)}`;
5757

5858
rollup.emitFile({
5959
type: 'asset',
6060
fileName: id
6161
.replace(`${inputRoot}/`, '')
62-
.replace(/\.scss$/, processedExt),
62+
.replace(/(\.module)?.scss$/, processedExt),
6363
source: postCssOutput.css,
6464
});
6565

polaris-react/package.json

+15-10
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
"test": "jest",
5858
"clean": "rm -rf .turbo node_modules build build-internal",
5959
"start": "serve ./build-internal/storybook/static -l ${PORT:=6006}",
60-
"storybook": "start-storybook -p 6006 --quiet",
61-
"storybook:build": "build-storybook -o build-internal/storybook/static",
60+
"storybook": "storybook dev -p 6006 --quiet",
61+
"storybook:build": "storybook build -o build-internal/storybook/static",
6262
"preversion": "node ./scripts/readme-update-version"
6363
},
6464
"dependencies": {
@@ -83,20 +83,24 @@
8383
"@shopify/postcss-plugin": "^5.0.1",
8484
"@shopify/react-testing": "^4.1.0",
8585
"@shopify/storybook-a11y-test": "1.0.1",
86-
"@storybook/addon-a11y": "^6.5.12",
87-
"@storybook/addon-toolbars": "^6.5.12",
88-
"@storybook/addon-viewport": "^6.5.12",
89-
"@storybook/builder-webpack5": "^6.5.12",
90-
"@storybook/manager-webpack5": "^6.5.12",
91-
"@storybook/react": "^6.5.12",
86+
"@storybook/addon-a11y": "^7.1.0-alpha.0",
87+
"@storybook/addon-toolbars": "^7.1.0-alpha.0",
88+
"@storybook/addon-viewport": "^7.1.0-alpha.0",
89+
"@storybook/api": "^7.1.0-alpha.0",
90+
"@storybook/preview-api": "^7.1.0-alpha.0",
91+
"@storybook/manager-api": "^7.1.0-alpha.0",
92+
"@storybook/blocks": "^7.1.0-alpha.0",
93+
"@storybook/components": "^7.1.0-alpha.0",
94+
"@storybook/react": "^7.1.0-alpha.0",
95+
"@storybook/react-vite": "^7.1.0-alpha.0",
9296
"@types/node": "^16.11.11",
9397
"@types/react": "^18.0.15",
9498
"@types/react-dom": "^18.0.6",
99+
"@types/react-transition-group": "^4.4.2",
95100
"babel-core": "7.0.0-bridge.0",
96101
"babel-loader": "^8.1.0",
97102
"change-case": "^3.1.0",
98103
"chromatic": "^6.5.4",
99-
"create-file-webpack": "^1.0.2",
100104
"globby": "^11.1.0",
101105
"node-sass": "^7.0.1",
102106
"postcss": "^8.3.1",
@@ -108,7 +112,8 @@
108112
"react-dom": "^18.2.0",
109113
"rimraf": "^3.0.0",
110114
"sass-loader": "^12.4.0",
111-
"webpack": "5"
115+
"storybook": "^7.1.0-alpha.0",
116+
"vite": "^4.2.1"
112117
},
113118
"browserslist": [
114119
"last 3 chrome versions",

polaris-react/playground/KitchenSink.tsx

+14-6
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@ interface Stories {
77
}
88

99
const stories: Stories = {};
10-
const req = require.context('../src/components', true, /.stories.tsx$/);
11-
req.keys().forEach((filePath) =>
12-
req(filePath).__namedExportsOrder.forEach((namedExport: string) => {
13-
const componentName = `${filePath.split('/')[1]}:${namedExport}`;
14-
stories[componentName] = req(filePath)[namedExport];
15-
}),
10+
// @ts-expect-error import.meta.glob is a Vite-only equivalent of
11+
// require.context
12+
const modules = import.meta.glob('../src/components/**/*.stories.tsx', {
13+
eager: true,
14+
});
15+
Object.entries(modules).forEach(
16+
([filePath, mod]: [string, {[key: string]: any}]) => {
17+
mod.__namedExportsOrder.forEach((name: string) => {
18+
const componentName = `${
19+
filePath.replace('../src/components/', '').split('/')[0]
20+
}:${name}`;
21+
stories[componentName] = mod[name];
22+
});
23+
},
1624
);
1725

1826
export function KitchenSink() {

polaris-react/playground/stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ export default {
1111
},
1212
};
1313

14-
export {Playground, KitchenSink, DetailsPage};
14+
export {DetailsPage, KitchenSink, Playground};

polaris-react/postcss.config.mjs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import postcssPlugins from './config/postcss-plugins.js';
2+
3+
const config = {
4+
plugins: postcssPlugins,
5+
};
6+
7+
// eslint-disable-next-line import/no-default-export
8+
export default config;

0 commit comments

Comments
 (0)