Skip to content

Commit 6e99fc3

Browse files
committed
feat(addon-docs): add Reset story button to re-render stories in docs
1 parent 8dff441 commit 6e99fc3

4 files changed

Lines changed: 30 additions & 6 deletions

File tree

code/addons/docs/src/blocks/blocks/Canvas.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint-disable react/destructuring-assignment */
2-
import React, { useContext } from 'react';
2+
import React, { useCallback, useContext, useState } from 'react';
33
import type { FC } from 'react';
44

5+
import { RESET_STORY_ARGS } from 'storybook/internal/core-events';
56
import type { ModuleExport, ModuleExports } from 'storybook/internal/types';
67

78
import type { Layout, PreviewProps as PurePreviewProps } from '../components';
@@ -81,6 +82,12 @@ export const Canvas: FC<CanvasProps> = (props) => {
8182
// By default, stories will be iframed, but most frameworks support inline rendering and override that in a docs entry file
8283
const inline = props.story?.inline ?? story.parameters?.docs?.story?.inline ?? false;
8384

85+
const [resetKey, setResetKey] = useState(0);
86+
const handleResetStory = useCallback(() => {
87+
docsContext.channel.emit(RESET_STORY_ARGS, { storyId: story.id });
88+
setResetKey((prev) => prev + 1);
89+
}, [docsContext.channel, story.id]);
90+
8491
return (
8592
<PurePreview
8693
withSource={sourceState === 'none' ? undefined : sourceProps}
@@ -90,8 +97,9 @@ export const Canvas: FC<CanvasProps> = (props) => {
9097
className={className}
9198
layout={layout}
9299
inline={inline}
100+
onResetStory={inline ? handleResetStory : undefined}
93101
>
94-
<Story of={of || story.moduleExport} meta={props.meta} {...props.story} />
102+
<Story of={of || story.moduleExport} meta={props.meta} {...props.story} resetKey={resetKey} />
95103
</PurePreview>
96104
);
97105
};

code/addons/docs/src/blocks/blocks/Story.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ type StoryParameters = {
5454
__forceInitialArgs?: boolean;
5555
/** Internal prop if this story is the primary story */
5656
__primary?: boolean;
57+
/** Key to trigger story remount when changed */
58+
resetKey?: number;
5759
};
5860

5961
export type StoryProps = StoryRefProps & StoryParameters;
@@ -100,6 +102,7 @@ export const getStoryProps = <TFramework extends Renderer>(
100102
forceInitialArgs: !!props.__forceInitialArgs,
101103
primary: !!props.__primary,
102104
renderStoryToElement: context.renderStoryToElement as any,
105+
resetKey: props.resetKey,
103106
};
104107
}
105108

code/addons/docs/src/blocks/components/Preview.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { logger } from 'storybook/internal/client-logger';
55
import { Bar, Button, ToggleButton, Zoom } from 'storybook/internal/components';
66
import type { ActionItem } from 'storybook/internal/components';
77

8-
import { CopyIcon, MarkupIcon } from '@storybook/icons';
8+
import { CopyIcon, MarkupIcon, UndoIcon } from '@storybook/icons';
99

1010
import { useId } from '@react-aria/utils';
1111
import { darken } from 'polished';
@@ -31,6 +31,7 @@ export type PreviewProps = PropsWithChildren<{
3131
withToolbar?: boolean;
3232
className?: string;
3333
additionalActions?: ActionItem[];
34+
onResetStory?: () => void;
3435
}>;
3536

3637
export type Layout = 'padded' | 'fullscreen' | 'centered';
@@ -150,6 +151,7 @@ export const Preview: FC<PreviewProps> = ({
150151
className,
151152
layout = 'padded',
152153
inline = false,
154+
onResetStory,
153155
...props
154156
}) => {
155157
const [expanded, setExpanded] = useState(isExpanded);
@@ -225,7 +227,7 @@ export const Preview: FC<PreviewProps> = ({
225227
</div>
226228
)}
227229
</PreviewContainer>
228-
{(withSource || additionalActionItems.length > 0) && (
230+
{(withSource || onResetStory || additionalActionItems.length > 0) && (
229231
<ActionBar className="sbdocs sbdocs-preview-actions" innerStyle={{ paddingInline: 0 }}>
230232
{hasSourceError && (
231233
<Button
@@ -255,6 +257,16 @@ export const Preview: FC<PreviewProps> = ({
255257
</Button>
256258
</>
257259
)}
260+
{onResetStory && (
261+
<Button
262+
ariaLabel={false}
263+
variant="ghost"
264+
onClick={onResetStory}
265+
className="docblock-reset-story"
266+
>
267+
<UndoIcon /> Reset story
268+
</Button>
269+
)}
258270
{additionalActionItems.map(({ title, className, onClick, disabled }, index: number) => (
259271
<Button
260272
key={index}

code/addons/docs/src/blocks/components/Story.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ interface CommonProps {
1515
story: PreparedStory;
1616
inline: boolean;
1717
primary: boolean;
18+
resetKey?: number;
1819
}
1920

2021
interface InlineStoryProps extends CommonProps {
@@ -40,7 +41,7 @@ const InlineStory: FunctionComponent<InlineStoryProps> = (props) => {
4041
const [showLoader, setShowLoader] = useState(true);
4142
const [error, setError] = useState<Error>();
4243

43-
const { story, height, autoplay, forceInitialArgs, renderStoryToElement } = props;
44+
const { story, height, autoplay, forceInitialArgs, renderStoryToElement, resetKey } = props;
4445

4546
useEffect(() => {
4647
if (!(story && storyRef.current)) {
@@ -64,7 +65,7 @@ const InlineStory: FunctionComponent<InlineStoryProps> = (props) => {
6465
// https://github.com/facebook/react/issues/25675#issuecomment-1363957941
6566
Promise.resolve().then(() => cleanup());
6667
};
67-
}, [autoplay, renderStoryToElement, story]);
68+
}, [autoplay, renderStoryToElement, story, resetKey]);
6869

6970
if (error) {
7071
return (

0 commit comments

Comments
 (0)