Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addon Test: Add demo mode #29492

Draft
wants to merge 4 commits into
base: next
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions code/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const config: StorybookConfig = {
directory: '../lib/blocks/src',
titlePrefix: 'blocks',
},
{
directory: '../lib/test/src',
titlePrefix: 'test',
},
{
directory: '../addons/a11y/template/stories',
titlePrefix: 'addons/a11y',
Expand Down
10 changes: 7 additions & 3 deletions code/.storybook/storybook.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ import * as projectAnnotations from './preview';
vi.spyOn(console, 'warn').mockImplementation((...args) => console.log(...args));

const annotations = setProjectAnnotations([
// @ts-expect-error check type errors later
projectAnnotations,
// @ts-expect-error check type errors later
componentAnnotations,
coreAnnotations,
testAnnotations,
Expand All @@ -29,7 +27,13 @@ const annotations = setProjectAnnotations([
if (globalThis.__vitest_browser__) {
const vitest = await import('@vitest/browser/context');
const { userEvent: browserEvent } = vitest;
context.userEvent = browserEvent.setup();
// @ts-expect-error check type errors later
context.userEvent = {
// we add storybook user event here as browserEvent is limited
// and does not have a few methods like pointer so we fallback to Storybook's userEvent
...storybookEvent.setup(),
...browserEvent.setup(),
};
context.expect = vitestExpect;
} else {
context.userEvent = storybookEvent.setup();
Expand Down
1 change: 1 addition & 0 deletions code/.storybook/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default mergeConfig(
test: {
name: 'storybook-ui',
include: [
'../lib/**/*.{story,stories}.?(c|m)[jt]s?(x)',
'../addons/**/*.{story,stories}.?(c|m)[jt]s?(x)',
// '../core/template/stories/**/*.{story,stories}.?(c|m)[jt]s?(x)',
'../core/src/manager/**/*.{story,stories}.?(c|m)[jt]s?(x)',
Expand Down
18 changes: 14 additions & 4 deletions code/addons/test/src/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import {
useAddonState,
useChannel,
useGlobals,
useParameter,
useStorybookState,
} from 'storybook/internal/manager-api';
Expand All @@ -19,7 +20,7 @@ import { global } from '@storybook/global';
import { type Call, CallStates, EVENTS, type LogItem } from '@storybook/instrumenter';
import type { API_StatusValue } from '@storybook/types';

import { InteractionsPanel } from './components/InteractionsPanel';
import { type Controls, InteractionsPanel } from './components/InteractionsPanel';
import { ADDON_ID, TEST_PROVIDER_ID } from './constants';

interface Interaction extends Call {
Expand Down Expand Up @@ -98,6 +99,8 @@ export const getInteractions = ({
export const Panel = memo<{ storyId: string }>(function PanelMemoized({ storyId }) {
const { status: storyStatuses } = useStorybookState();

const [globals, updateGlobals] = useGlobals();

// shared state
const [addonState, set] = useAddonState(ADDON_ID, {
controlStates: INITIAL_CONTROL_STATES,
Expand Down Expand Up @@ -226,9 +229,9 @@ export const Panel = memo<{ storyId: string }>(function PanelMemoized({ storyId
interactionsCount: list.filter(({ method }) => method !== 'step').length,
};
});
}, [collapsed]);
}, [collapsed, set]);

const controls = useMemo(
const controls: Controls = useMemo(
() => ({
start: () => emit(EVENTS.START, { storyId }),
back: () => emit(EVENTS.BACK, { storyId }),
Expand All @@ -238,8 +241,14 @@ export const Panel = memo<{ storyId: string }>(function PanelMemoized({ storyId
rerun: () => {
emit(FORCE_REMOUNT, { storyId });
},
toggleDemoMode: () => {
updateGlobals({
...globals,
interactionsDemoMode: globals.interactionsDemoMode === true ? null : true,
});
},
}),
[storyId]
[storyId, globals, updateGlobals, emit]
);

const storyFilePath = useParameter('fileName', '');
Expand Down Expand Up @@ -287,6 +296,7 @@ export const Panel = memo<{ storyId: string }>(function PanelMemoized({ storyId
caughtException={caughtException}
unhandledErrors={unhandledErrors}
isPlaying={isPlaying}
isDemoMode={globals.interactionsDemoMode}
pausedAt={pausedAt}
endRef={endRef}
onScrollToEnd={scrollTarget && scrollToTarget}
Expand Down
4 changes: 4 additions & 0 deletions code/addons/test/src/components/InteractionsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface Controls {
next: (args: any) => void;
end: (args: any) => void;
rerun: (args: any) => void;
toggleDemoMode: (args: any) => void;
}

interface InteractionsPanelProps {
Expand All @@ -38,6 +39,7 @@ interface InteractionsPanelProps {
caughtException?: Error;
unhandledErrors?: SerializedError[];
isPlaying?: boolean;
isDemoMode?: boolean;
pausedAt?: Call['id'];
calls: Map<string, any>;
endRef?: React.Ref<HTMLDivElement>;
Expand Down Expand Up @@ -100,6 +102,7 @@ export const InteractionsPanel: React.FC<InteractionsPanelProps> = React.memo(
caughtException,
unhandledErrors,
isPlaying,
isDemoMode,
pausedAt,
onScrollToEnd,
endRef,
Expand All @@ -123,6 +126,7 @@ export const InteractionsPanel: React.FC<InteractionsPanelProps> = React.memo(
<Subnav
controls={controls}
controlStates={controlStates}
isDemoMode={isDemoMode}
status={browserTestStatus}
storyFileName={fileName}
onScrollToEnd={onScrollToEnd}
Expand Down
15 changes: 15 additions & 0 deletions code/addons/test/src/components/Subnav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
FastForwardIcon,
PlayBackIcon,
PlayNextIcon,
PointerHandIcon,
RewindIcon,
SyncIcon,
} from '@storybook/icons';
Expand Down Expand Up @@ -43,6 +44,7 @@ const StyledSubnav = styled.nav(({ theme }) => ({

export interface SubnavProps {
controls: Controls;
isDemoMode: boolean;
controlStates: ControlStates;
status: Call['status'];
storyFileName?: string;
Expand Down Expand Up @@ -118,6 +120,7 @@ export const Subnav: React.FC<SubnavProps> = ({
controlStates,
status,
storyFileName,
isDemoMode,
onScrollToEnd,
}) => {
const buttonText = status === CallStates.ERROR ? 'Scroll to error' : 'Scroll to end';
Expand Down Expand Up @@ -180,6 +183,18 @@ export const Subnav: React.FC<SubnavProps> = ({
<SyncIcon />
</RerunButton>
</WithTooltip>

<WithTooltip trigger="hover" hasChrome={false} tooltip={<Note note="Demo mode" />}>
<IconButton
key="outline"
active={isDemoMode}
aria-label="Demo mode"
title="Toggle demo mode"
onClick={controls.toggleDemoMode}
>
<PointerHandIcon />
</IconButton>
</WithTooltip>
</Group>
{storyFileName && (
<Group>
Expand Down
11 changes: 11 additions & 0 deletions code/addons/test/src/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,14 @@ export const { step: runStep } = instrument(
export const parameters = {
throwPlayFunctionExceptions: false,
};

export const initialGlobals = {
interactionsDemoMode: null as any,
};

export const beforeEach = () => {
return () => {
// remove demo mode cursor
document.getElementById('sb-demo-cursor')?.remove();
};
};
70 changes: 70 additions & 0 deletions code/core/assets/server/base-preview-head.html
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,76 @@
margin-bottom: 4px;
padding: 2px 5px;
}

/* storybook interactions demo mode */
#sb-demo-cursor {
z-index: 9999;
transition-duration: 1000ms;
transition-timing-function: cubic-bezier(0.2, 1, 0.2, 1);
transition-property: top, left;
position: fixed;
width: 30px;
height: 30px;
border-radius: 20px;
margin: -20px 0 0 -20px;
background: rgba(0, 0, 0, 0);
top: 50%;
left: 50%;
pointer-events: none;
}

#sb-demo-cursor[data-type='circle'].sb-cursor-moving {
background: rgba(0, 0, 0, 0.5);
border: 2px solid rgba(255, 255, 255, 0.5);
}

#sb-demo-cursor[data-type='circle'].sb-cursor-hide {
animation:
fadeCursor 1000ms linear,
press 300ms ease-in;
}

#sb-demo-cursor[data-type='hand'].sb-cursor-hide {
animation:
hideCursor 1000ms linear forwards,
press 300ms ease-in;
}

@keyframes fadeCursor {
0% {
background: rgba(0, 0, 0, 0.8);
opacity: 1;
}

100% {
background: rgba(0, 0, 0, 0);
opacity: 0;
}
}

@keyframes hideCursor {
0% {
opacity: 1;
}

100% {
opacity: 0;
}
}

@keyframes press {
0% {
transform: scale(1);
}

50% {
transform: scale(0.45);
}

100% {
transform: scale(1);
}
}
</style>

<script>
Expand Down
1 change: 1 addition & 0 deletions code/core/src/builder-manager/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const renderHTML = async (
files: { js: jsFiles, css: cssFiles },
favicon: await favicon,
globals: {
STORYBOOK_ENV: 'true',
FEATURES: JSON.stringify(await features, null, 2),
REFS: JSON.stringify(await refs, null, 2),
LOGLEVEL: JSON.stringify(await logLevel, null, 2),
Expand Down
Loading
Loading