Skip to content

Commit bb9f65f

Browse files
Enable strict mode toggle in storybook (#3870)
* add checkbox to enable strict mode on a story by story basis * checkbox for strict * getting rid of storybook globals in favor of state the globals are updating anymore for some reason... * me dumb, me forget to convert to boolean * removing style * fix storybook crash when saving changes in FocusScope file core issue is with react fast refresh in parcel, fix to be patched there eventually. For now this is a stopgap fix, see vitejs/vite#3301 for a similar issue Co-authored-by: Robert Snow <[email protected]>
1 parent 15e101b commit bb9f65f

File tree

7 files changed

+102
-9
lines changed

7 files changed

+102
-9
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {addons, makeDecorator} from '@storybook/addons';
2+
import {getQueryParams} from '@storybook/client-api';
3+
import React, {StrictMode, useEffect, useState} from 'react';
4+
5+
function StrictModeDecorator(props) {
6+
let {children} = props;
7+
let [isStrict, setStrict] = useState(getQueryParams()?.strict === 'true' || false);
8+
9+
useEffect(() => {
10+
let channel = addons.getChannel();
11+
let updateStrict = (val) => {
12+
setStrict(val);
13+
};
14+
channel.on('strict/updated', updateStrict);
15+
return () => {
16+
channel.removeListener('strict/updated', updateStrict);
17+
};
18+
}, []);
19+
20+
return isStrict ? (
21+
<StrictMode>
22+
{children}
23+
</StrictMode>
24+
) : children;
25+
}
26+
27+
export const withStrictModeSwitcher = makeDecorator({
28+
name: 'withStrictModeSwitcher',
29+
parameterName: 'strictModeSwitcher',
30+
wrapper: (getStory, context) => {
31+
return (
32+
<StrictModeDecorator>
33+
{getStory(context)}
34+
</StrictModeDecorator>
35+
);
36+
}
37+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {addons, types} from '@storybook/addons';
2+
import {getQueryParams} from '@storybook/client-api';
3+
import React, {useEffect, useState} from 'react';
4+
5+
const StrictModeToolBar = ({api}) => {
6+
let channel = addons.getChannel();
7+
let [isStrict, setStrict] = useState(getQueryParams()?.strict === 'true' || false);
8+
let onChange = () => {
9+
setStrict((old) => {
10+
channel.emit('strict/updated', !old);
11+
return !old;
12+
})
13+
};
14+
15+
useEffect(() => {
16+
api.setQueryParams({
17+
'strict': isStrict
18+
});
19+
});
20+
21+
return (
22+
<div style={{display: 'flex', alignItems: 'center', fontSize: '12px'}}>
23+
<div style={{marginRight: '10px'}}>
24+
<label htmlFor="strictmode">StrictMode:
25+
<input type="checkbox" id="strictmode" name="strictmode" checked={isStrict} onChange={onChange} />
26+
</label>
27+
</div>
28+
</div>
29+
);
30+
};
31+
32+
addons.register('StrictModeSwitcher', (api) => {
33+
addons.add('StrictModeSwitcher', {
34+
title: 'Strict mode switcher',
35+
type: types.TOOL,
36+
//👇 Shows the Toolbar UI element if either the Canvas or Docs tab is active
37+
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
38+
render: () => <StrictModeToolBar api={api} />
39+
});
40+
});

.storybook/main.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@ module.exports = {
1111
'storybook-dark-mode',
1212
'./custom-addons/provider/register',
1313
'./custom-addons/descriptions/register',
14-
'./custom-addons/theme/register'
14+
'./custom-addons/theme/register',
15+
'./custom-addons/strictmode/register'
1516
],
1617
typescript: {
1718
check: false,
1819
reactDocgen: false
19-
},
20-
reactOptions: {
21-
strictMode: process.env.STRICT_MODE
22-
},
20+
}
2321
};

.storybook/preview.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {configureActions} from '@storybook/addon-actions';
22
import React from 'react';
33
import {VerticalCenter} from './layout';
44
import {withProviderSwitcher} from './custom-addons/provider';
5+
import {withStrictModeSwitcher} from './custom-addons/strictmode';
56

67
// decorator order matters, the last one will be the outer most
78

@@ -29,5 +30,6 @@ export const decorators = [
2930
<Story />
3031
</VerticalCenter>
3132
),
33+
withStrictModeSwitcher,
3234
withProviderSwitcher
3335
];

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"install-16": "yarn add -W react@^16.8.0 react-dom@^16.8.0 @testing-library/react@^12 @testing-library/react-hooks@^8",
1313
"install-17": "yarn add -W react@^17 react-dom@^17 @testing-library/react@^12 @testing-library/react-hooks@^8",
1414
"start": "cross-env NODE_ENV=storybook start-storybook -p 9003 --ci -c '.storybook'",
15-
"start-strict": "cross-env NODE_ENV=storybook STRICT_MODE=1 start-storybook -p 9003 --ci -c '.storybook'",
1615
"build:storybook": "build-storybook -c .storybook -o dist/$(git rev-parse HEAD)/storybook",
1716
"build:storybook-16": "build-storybook -c .storybook -o dist/$(git rev-parse HEAD)/storybook-16",
1817
"build:storybook-17": "build-storybook -c .storybook -o dist/$(git rev-parse HEAD)/storybook-17",

packages/@react-spectrum/provider/src/Provider.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
useStyleProps
1919
} from '@react-spectrum/utils';
2020
import clsx from 'clsx';
21+
import {Context} from './context';
2122
import {DOMRef} from '@react-types/shared';
2223
import {filterDOMProps} from '@react-aria/utils';
2324
import {I18nProvider, useLocale} from '@react-aria/i18n';
@@ -30,9 +31,6 @@ import {useColorScheme, useScale} from './mediaQueries';
3031
// @ts-ignore
3132
import {version} from '../package.json';
3233

33-
const Context = React.createContext<ProviderContext | null>(null);
34-
Context.displayName = 'ProviderContext';
35-
3634
const DEFAULT_BREAKPOINTS = {S: 640, M: 768, L: 1024, XL: 1280, XXL: 1536};
3735

3836
function Provider(props: ProviderProps, ref: DOMRef<HTMLDivElement>) {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
import {ProviderContext} from '@react-types/provider';
14+
import React from 'react';
15+
16+
// Context is placed in a separate file to avoid fast refresh issue where the old provider context values
17+
// are immediately replaced with the null default. Stopgap solution until we fix this in parcel.
18+
export const Context = React.createContext<ProviderContext | null>(null);
19+
Context.displayName = 'ProviderContext';

0 commit comments

Comments
 (0)