diff --git a/lib/cli/src/frameworks/common/header.css b/lib/cli/src/frameworks/common/header.css
index acadc9ec8c7f..830610e6f2e9 100644
--- a/lib/cli/src/frameworks/common/header.css
+++ b/lib/cli/src/frameworks/common/header.css
@@ -24,3 +24,9 @@ h1 {
button + button {
margin-left: 10px;
}
+
+.welcome {
+ color: #333;
+ font-size: 14px;
+ margin-right: 10px;
+}
diff --git a/lib/cli/src/frameworks/react/js/Header.jsx b/lib/cli/src/frameworks/react/js/Header.jsx
index 30afca379c75..59787aed890e 100644
--- a/lib/cli/src/frameworks/react/js/Header.jsx
+++ b/lib/cli/src/frameworks/react/js/Header.jsx
@@ -28,7 +28,12 @@ export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => (
{user ? (
-
+ <>
+
+ Welcome, {user.name} !
+
+
+ >
) : (
<>
diff --git a/lib/cli/src/frameworks/react/js/Header.stories.jsx b/lib/cli/src/frameworks/react/js/Header.stories.jsx
index 16f41aa37c5a..e4850002cac5 100644
--- a/lib/cli/src/frameworks/react/js/Header.stories.jsx
+++ b/lib/cli/src/frameworks/react/js/Header.stories.jsx
@@ -5,13 +5,19 @@ import { Header } from './Header';
export default {
title: 'Example/Header',
component: Header,
+ parameters: {
+ // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout
+ layout: 'fullscreen',
+ },
};
const Template = (args) =>
;
export const LoggedIn = Template.bind({});
LoggedIn.args = {
- user: {},
+ user: {
+ name: 'Jane Doe',
+ },
};
export const LoggedOut = Template.bind({});
diff --git a/lib/cli/src/frameworks/react/js/Page.jsx b/lib/cli/src/frameworks/react/js/Page.jsx
index 1534d1c0b683..c5fffe953be5 100644
--- a/lib/cli/src/frameworks/react/js/Page.jsx
+++ b/lib/cli/src/frameworks/react/js/Page.jsx
@@ -1,71 +1,69 @@
import React from 'react';
-import PropTypes from 'prop-types';
import { Header } from './Header';
import './page.css';
-export const Page = ({ user, onLogin, onLogout, onCreateAccount }) => (
-
-
+export const Page = () => {
+ const [user, setUser] = React.useState();
-
- Pages in Storybook
-
- We recommend building UIs with a{' '}
-
- component-driven
- {' '}
- process starting with atomic components and ending with pages.
-
-
- Render pages with mock data. This makes it easy to build and review page states without
- needing to navigate to them in your app. Here are some handy patterns for managing page data
- in Storybook:
-
-
-
- Use a higher-level connected component. Storybook helps you compose such data from the
- "args" of child component stories
-
-
- Assemble data in the page component from your services. You can mock these services out
- using Storybook.
-
-
-
- Get a guided tutorial on component-driven development at{' '}
-
- Storybook tutorials
-
- . Read more in the{' '}
-
- docs
-
- .
-
-
-
Tip Adjust the width of the canvas with the{' '}
-
-
-
-
-
- Viewports addon in the toolbar
-
-
-
-);
-Page.propTypes = {
- user: PropTypes.shape({}),
- onLogin: PropTypes.func.isRequired,
- onLogout: PropTypes.func.isRequired,
- onCreateAccount: PropTypes.func.isRequired,
-};
+ return (
+
+ setUser({ name: 'Jane Doe' })}
+ onLogout={() => setUser(undefined)}
+ onCreateAccount={() => setUser({ name: 'Jane Doe' })}
+ />
-Page.defaultProps = {
- user: null,
+
+ Pages in Storybook
+
+ We recommend building UIs with a{' '}
+
+ component-driven
+ {' '}
+ process starting with atomic components and ending with pages.
+
+
+ Render pages with mock data. This makes it easy to build and review page states without
+ needing to navigate to them in your app. Here are some handy patterns for managing page
+ data in Storybook:
+
+
+
+ Use a higher-level connected component. Storybook helps you compose such data from the
+ "args" of child component stories
+
+
+ Assemble data in the page component from your services. You can mock these services out
+ using Storybook.
+
+
+
+ Get a guided tutorial on component-driven development at{' '}
+
+ Storybook tutorials
+
+ . Read more in the{' '}
+
+ docs
+
+ .
+
+
+
Tip Adjust the width of the canvas with the{' '}
+
+
+
+
+
+ Viewports addon in the toolbar
+
+
+
+ );
};
diff --git a/lib/cli/src/frameworks/react/js/Page.stories.jsx b/lib/cli/src/frameworks/react/js/Page.stories.jsx
index 948ad67aa31b..0174fdb881f9 100644
--- a/lib/cli/src/frameworks/react/js/Page.stories.jsx
+++ b/lib/cli/src/frameworks/react/js/Page.stories.jsx
@@ -1,22 +1,25 @@
import React from 'react';
+import { within, userEvent } from '@storybook/testing-library';
import { Page } from './Page';
-import * as HeaderStories from './Header.stories';
export default {
title: 'Example/Page',
component: Page,
+ parameters: {
+ // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout
+ layout: 'fullscreen',
+ },
};
const Template = (args) =>
;
-export const LoggedIn = Template.bind({});
-LoggedIn.args = {
- // More on composing args: https://storybook.js.org/docs/react/writing-stories/args#args-composition
- ...HeaderStories.LoggedIn.args,
-};
-
+// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing
export const LoggedOut = Template.bind({});
-LoggedOut.args = {
- ...HeaderStories.LoggedOut.args,
+
+export const LoggedIn = Template.bind({});
+LoggedIn.play = async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = await canvas.getByRole('button', { name: /Log in/i });
+ await userEvent.click(loginButton);
};
diff --git a/lib/cli/src/frameworks/react/ts/Header.stories.tsx b/lib/cli/src/frameworks/react/ts/Header.stories.tsx
index 4b11b34597dd..7e9283eaf66a 100644
--- a/lib/cli/src/frameworks/react/ts/Header.stories.tsx
+++ b/lib/cli/src/frameworks/react/ts/Header.stories.tsx
@@ -6,13 +6,19 @@ import { Header } from './Header';
export default {
title: 'Example/Header',
component: Header,
+ parameters: {
+ // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout
+ layout: 'fullscreen',
+ },
} as ComponentMeta
;
const Template: ComponentStory = (args) => ;
export const LoggedIn = Template.bind({});
LoggedIn.args = {
- user: {},
+ user: {
+ name: 'Jane Doe',
+ },
};
export const LoggedOut = Template.bind({});
diff --git a/lib/cli/src/frameworks/react/ts/Header.tsx b/lib/cli/src/frameworks/react/ts/Header.tsx
index 96250c598087..dc3f3c19c31a 100644
--- a/lib/cli/src/frameworks/react/ts/Header.tsx
+++ b/lib/cli/src/frameworks/react/ts/Header.tsx
@@ -3,8 +3,12 @@ import React from 'react';
import { Button } from './Button';
import './header.css';
+type User = {
+ name: string;
+};
+
interface HeaderProps {
- user?: {};
+ user?: User;
onLogin: () => void;
onLogout: () => void;
onCreateAccount: () => void;
@@ -34,7 +38,12 @@ export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps
{user ? (
-
+ <>
+
+ Welcome, {user.name} !
+
+
+ >
) : (
<>
diff --git a/lib/cli/src/frameworks/react/ts/Page.stories.tsx b/lib/cli/src/frameworks/react/ts/Page.stories.tsx
index 8c8cab27813a..a0ea79fd64e0 100644
--- a/lib/cli/src/frameworks/react/ts/Page.stories.tsx
+++ b/lib/cli/src/frameworks/react/ts/Page.stories.tsx
@@ -1,23 +1,26 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
-
+import { within, userEvent } from '@storybook/testing-library';
import { Page } from './Page';
-import * as HeaderStories from './Header.stories';
export default {
title: 'Example/Page',
component: Page,
+ parameters: {
+ // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout
+ layout: 'fullscreen',
+ },
} as ComponentMeta
;
const Template: ComponentStory = (args) => ;
+export const LoggedOut = Template.bind({});
+
export const LoggedIn = Template.bind({});
-LoggedIn.args = {
- // More on composing args: https://storybook.js.org/docs/react/writing-stories/args#args-composition
- ...HeaderStories.LoggedIn.args,
-};
-export const LoggedOut = Template.bind({});
-LoggedOut.args = {
- ...HeaderStories.LoggedOut.args,
+// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing
+LoggedIn.play = async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = await canvas.getByRole('button', { name: /Log in/i });
+ await userEvent.click(loginButton);
};
diff --git a/lib/cli/src/frameworks/react/ts/Page.tsx b/lib/cli/src/frameworks/react/ts/Page.tsx
index f35c4c8730a8..522d34294ae2 100644
--- a/lib/cli/src/frameworks/react/ts/Page.tsx
+++ b/lib/cli/src/frameworks/react/ts/Page.tsx
@@ -3,65 +3,71 @@ import React from 'react';
import { Header } from './Header';
import './page.css';
-interface PageProps {
- user?: {};
- onLogin: () => void;
- onLogout: () => void;
- onCreateAccount: () => void;
-}
+type User = {
+ name: string;
+};
-export const Page = ({ user, onLogin, onLogout, onCreateAccount }: PageProps) => (
-
-
+export const Page: React.VFC = () => {
+ const [user, setUser] = React.useState();
-
- Pages in Storybook
-
- We recommend building UIs with a{' '}
-
- component-driven
- {' '}
- process starting with atomic components and ending with pages.
-
-
- Render pages with mock data. This makes it easy to build and review page states without
- needing to navigate to them in your app. Here are some handy patterns for managing page data
- in Storybook:
-
-
-
- Use a higher-level connected component. Storybook helps you compose such data from the
- "args" of child component stories
-
-
- Assemble data in the page component from your services. You can mock these services out
- using Storybook.
-
-
-
- Get a guided tutorial on component-driven development at{' '}
-
- Storybook tutorials
-
- . Read more in the{' '}
-
- docs
-
- .
-
-
-
Tip Adjust the width of the canvas with the{' '}
-
-
-
-
-
- Viewports addon in the toolbar
-
-
-
-);
+ return (
+
+ setUser({ name: 'Jane Doe' })}
+ onLogout={() => setUser(undefined)}
+ onCreateAccount={() => setUser({ name: 'Jane Doe' })}
+ />
+
+
+ Pages in Storybook
+
+ We recommend building UIs with a{' '}
+
+ component-driven
+ {' '}
+ process starting with atomic components and ending with pages.
+
+
+ Render pages with mock data. This makes it easy to build and review page states without
+ needing to navigate to them in your app. Here are some handy patterns for managing page
+ data in Storybook:
+
+
+
+ Use a higher-level connected component. Storybook helps you compose such data from the
+ "args" of child component stories
+
+
+ Assemble data in the page component from your services. You can mock these services out
+ using Storybook.
+
+
+
+ Get a guided tutorial on component-driven development at{' '}
+
+ Storybook tutorials
+
+ . Read more in the{' '}
+
+ docs
+
+ .
+
+
+
Tip Adjust the width of the canvas with the{' '}
+
+
+
+
+
+ Viewports addon in the toolbar
+
+
+
+ );
+};
diff --git a/lib/cli/src/generators/baseGenerator.ts b/lib/cli/src/generators/baseGenerator.ts
index 67963bd1ab88..0a8f3dc379cd 100644
--- a/lib/cli/src/generators/baseGenerator.ts
+++ b/lib/cli/src/generators/baseGenerator.ts
@@ -58,6 +58,8 @@ const builderDependencies = (builder: Builder) => {
const stripVersions = (addons: string[]) => addons.map((addon) => getPackageDetails(addon)[0]);
+const hasInteractiveStories = (framework: SupportedFrameworks) => ['react'].includes(framework);
+
export async function baseGenerator(
packageManager: JsPackageManager,
npmOptions: NpmOptions,
@@ -86,6 +88,11 @@ export async function baseGenerator(
// added to package.json
const addonPackages = [...addons, '@storybook/addon-actions'];
+ if (hasInteractiveStories(framework)) {
+ addons.push('@storybook/addon-interactions');
+ addonPackages.push('@storybook/addon-interactions', '@storybook/testing-library');
+ }
+
const yarn2Dependencies =
packageManager.type === 'yarn2' ? ['@storybook/addon-docs', '@mdx-js/react@1.x.x'] : [];