diff --git a/.circleci/config.yml b/.circleci/config.yml index 25632227f0e6..c1939a556d6e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -151,7 +151,7 @@ jobs: executor: class: medium+ name: sb_node_14_browsers - parallelism: 15 + parallelism: 14 steps: - git-shallow-clone/checkout_advanced: clone_options: '--depth 1 --verbose' diff --git a/CONTRIBUTING.old.md b/CONTRIBUTING.old.md index a1a0242371de..f12a07c76a13 100644 --- a/CONTRIBUTING.old.md +++ b/CONTRIBUTING.old.md @@ -147,7 +147,7 @@ Then run `yarn cypress open` if you want to see the tests run in the UI, or `yar The best way to help figure out an issue you are having is to produce a minimal reproduction against the `main` branch. -A good way to do that is using the example `cra-kitchen-sink` app embedded in this repository: +A good way to do that is using the example `official-storybook` app embedded in this repository: ```sh # Download and build this repository: @@ -157,7 +157,7 @@ yarn yarn bootstrap --core # make changes to try and reproduce the problem, such as adding components + stories -cd examples/cra-kitchen-sink +cd examples/official-storybook yarn storybook # see if you can see the problem, if so, commit it: diff --git a/code/.gitignore b/code/.gitignore index 8e7366b01633..64fb7c9a05b5 100644 --- a/code/.gitignore +++ b/code/.gitignore @@ -21,7 +21,6 @@ package-lock.json storybook-static integration/__image_snapshots__/__diff_output__ .jest-test-results.json -/examples/cra-kitchen-sink/src/__image_snapshots__/__diff_output__/ lib/*.jar lib/**/dll /false diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index 84d13b577386..69ea9d01456e 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -58,7 +58,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index 4063bce0fca3..d8d90a6d9126 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -31,7 +31,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index 6d521913cb1f..e773055a24f4 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -58,7 +58,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index d55113cf8441..4e9cfaced906 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -53,7 +53,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index db2e772c1715..33e9152ae3cf 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -45,7 +45,7 @@ "!__testfixtures__" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index 424b3ff54386..e044b4f310e8 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -29,7 +29,7 @@ "README.md" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index cabe39285dd9..b9cbd0527806 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -33,7 +33,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 585a5900ea77..17121a40a389 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -54,7 +54,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 9f0188e43c2b..80e6f3052462 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -55,7 +55,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/links/package.json b/code/addons/links/package.json index d32cc79e72dc..80198ad0643b 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -59,7 +59,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index cbee33f4b230..cc20f79473f1 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -57,7 +57,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index c0387357e260..697c597a8afd 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -60,7 +60,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index 0fd76fff0120..884f8af9e3cd 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -31,7 +31,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index 19dcd531bd05..2f24269caed7 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -53,7 +53,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 937c9b4bd86e..227476666ed8 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -55,7 +55,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/examples/angular-cli/src/app/app.component.spec.ts b/code/examples/angular-cli/src/app/app.component.spec.ts index b16e28444678..fc39d934a589 100644 --- a/code/examples/angular-cli/src/app/app.component.spec.ts +++ b/code/examples/angular-cli/src/app/app.component.spec.ts @@ -4,40 +4,29 @@ import { BrowserTestingModule } from '@angular/platform-browser/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { - beforeEach( - waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [BrowserTestingModule], - declarations: [AppComponent], - }).compileComponents(); - }) - ); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [BrowserTestingModule], + declarations: [AppComponent], + }).compileComponents(); + })); - it( - 'should create the app', - waitForAsync(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app).toBeTruthy(); - }) - ); + it('should create the app', waitForAsync(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); - it( - `should have as title 'app'`, - waitForAsync(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app.title).toEqual('app'); - }) - ); + it(`should have as title 'app'`, waitForAsync(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('app'); + })); - it( - 'should render title in a h1 tag', - waitForAsync(() => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); - }) - ); + it('should render title in a h1 tag', waitForAsync(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); + })); }); diff --git a/code/examples/cra-kitchen-sink/.env b/code/examples/cra-kitchen-sink/.env deleted file mode 100644 index 7d104c48c82d..000000000000 --- a/code/examples/cra-kitchen-sink/.env +++ /dev/null @@ -1,3 +0,0 @@ -DISABLE_ESLINT_PLUGIN=true -SKIP_PREFLIGHT_CHECK=true -NODE_PATH=src \ No newline at end of file diff --git a/code/examples/cra-kitchen-sink/.storybook/main.ts b/code/examples/cra-kitchen-sink/.storybook/main.ts deleted file mode 100644 index 1d5e852f231e..000000000000 --- a/code/examples/cra-kitchen-sink/.storybook/main.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { StorybookConfig } from '@storybook/react-webpack5'; - -const path = require('path'); - -const mainConfig: StorybookConfig = { - stories: ['../src/stories/**/*.stories.@(ts|tsx|js|jsx|mdx)'], - logLevel: 'debug', - addons: [ - '@storybook/preset-create-react-app', - { - name: '@storybook/addon-docs/preset', - options: { - configureJSX: true, - }, - }, - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addon-backgrounds', - '@storybook/addon-a11y', - '@storybook/addon-jest', - '@storybook/addon-highlight', - ], - // add monorepo root as a valid directory to import modules from - webpackFinal: (config) => { - const resolvePlugins = config.resolve?.plugins; - if (Array.isArray(resolvePlugins)) { - resolvePlugins.forEach((p) => { - // @ts-expect-error (Converted from ts-ignore) - const appSrcs = p.appSrcs as unknown as string[]; - if (Array.isArray(appSrcs)) { - appSrcs.push(path.join(__dirname, '..', '..', '..')); - } - }); - } - return config; - }, - core: { - disableTelemetry: true, - channelOptions: { allowFunction: false, maxDepth: 10 }, - }, - staticDirs: ['../public'], - features: { - buildStoriesJson: true, - breakingChangesV7: true, - }, - framework: { - name: '@storybook/react-webpack5', - options: { fastRefresh: true }, - }, -}; - -module.exports = mainConfig; diff --git a/code/examples/cra-kitchen-sink/.storybook/manager.js b/code/examples/cra-kitchen-sink/.storybook/manager.js deleted file mode 100644 index 8b2c926cf5fe..000000000000 --- a/code/examples/cra-kitchen-sink/.storybook/manager.js +++ /dev/null @@ -1,14 +0,0 @@ -import { create } from '@storybook/theming/create'; -import { addons } from '@storybook/addons'; - -addons.setConfig({ - isFullscreen: false, - showAddonsPanel: true, - panelPosition: 'right', - theme: create({ - base: 'light', - brandTitle: 'CRA Kitchen Sink', - brandUrl: 'https://github.com/storybookjs/storybook/tree/master/examples/cra-kitchen-sink', - gridCellSize: 12, - }), -}); diff --git a/code/examples/cra-kitchen-sink/.storybook/preview.js b/code/examples/cra-kitchen-sink/.storybook/preview.js deleted file mode 100644 index a99b48398745..000000000000 --- a/code/examples/cra-kitchen-sink/.storybook/preview.js +++ /dev/null @@ -1,11 +0,0 @@ -export const parameters = { - options: { - storySort: (a, b) => - a.title === b.title ? 0 : a.id.localeCompare(b.id, undefined, { numeric: true }), - }, - docs: { - source: { - excludeDecorators: true, - }, - }, -}; diff --git a/code/examples/cra-kitchen-sink/package.json b/code/examples/cra-kitchen-sink/package.json deleted file mode 100644 index 862b7cfe6a66..000000000000 --- a/code/examples/cra-kitchen-sink/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "cra-kitchen-sink", - "version": "7.0.0-alpha.33", - "private": true, - "scripts": { - "build": "react-scripts build", - "build-storybook": "storybook build", - "eject": "react-scripts eject", - "start": "react-scripts start", - "storybook": "storybook dev -p 9010 --no-manager-cache", - "test": "react-scripts test --env=jsdom" - }, - "dependencies": { - "@storybook/client-logger": "7.0.0-alpha.33", - "global": "^4.4.0", - "prop-types": "^15.7.2", - "react": "16.14.0", - "react-dom": "16.14.0", - "react-lifecycles-compat": "^3.0.4", - "react-scripts": "^5.0.1" - }, - "devDependencies": { - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5", - "@storybook/addon-a11y": "7.0.0-alpha.33", - "@storybook/addon-actions": "7.0.0-alpha.33", - "@storybook/addon-backgrounds": "7.0.0-alpha.33", - "@storybook/addon-docs": "7.0.0-alpha.33", - "@storybook/addon-highlight": "7.0.0-alpha.33", - "@storybook/addon-jest": "7.0.0-alpha.33", - "@storybook/addon-links": "7.0.0-alpha.33", - "@storybook/addon-storyshots": "7.0.0-alpha.33", - "@storybook/addons": "7.0.0-alpha.33", - "@storybook/builder-webpack5": "7.0.0-alpha.33", - "@storybook/preset-create-react-app": "^4.1.0", - "@storybook/react": "7.0.0-alpha.33", - "@storybook/react-webpack5": "7.0.0-alpha.33", - "@storybook/theming": "7.0.0-alpha.33", - "storybook": "7.0.0-alpha.33", - "webpack": "5" - }, - "storybook": { - "chromatic": { - "projectToken": "tg55gajmdt" - } - } -} diff --git a/code/examples/cra-kitchen-sink/public/favicon.ico b/code/examples/cra-kitchen-sink/public/favicon.ico deleted file mode 100644 index 5c125de5d897..000000000000 Binary files a/code/examples/cra-kitchen-sink/public/favicon.ico and /dev/null differ diff --git a/code/examples/cra-kitchen-sink/public/index.html b/code/examples/cra-kitchen-sink/public/index.html deleted file mode 100644 index a916247feed4..000000000000 --- a/code/examples/cra-kitchen-sink/public/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - React App - - -
- - - diff --git a/code/examples/cra-kitchen-sink/src/App.css b/code/examples/cra-kitchen-sink/src/App.css deleted file mode 100644 index 51b2c56f85f6..000000000000 --- a/code/examples/cra-kitchen-sink/src/App.css +++ /dev/null @@ -1,30 +0,0 @@ -@import './base.css'; - -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 80px; -} - -.App-header { - background-color: #222; - height: 150px; - padding: 20px; - color: white; -} - -.App-intro { - font-size: large; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/code/examples/cra-kitchen-sink/src/App.js b/code/examples/cra-kitchen-sink/src/App.js deleted file mode 100644 index 2c49d780e9a9..000000000000 --- a/code/examples/cra-kitchen-sink/src/App.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import logo from './logo.svg'; -import './App.css'; - -const App = () => ( -
-
- logo -

Welcome to React

-
-

- To get started, edit src/App.js and save to reload. -

-
-); - -export default App; diff --git a/code/examples/cra-kitchen-sink/src/base.css b/code/examples/cra-kitchen-sink/src/base.css deleted file mode 100644 index 2374c9a9319a..000000000000 --- a/code/examples/cra-kitchen-sink/src/base.css +++ /dev/null @@ -1,9 +0,0 @@ -:root { - background: rgba(232, 232, 232, 1); - background: radial-gradient( - ellipse at center, - rgba(255, 255, 255, 1) 11%, - rgba(232, 232, 232, 1) 100% - ); - height: 100%; -} diff --git a/code/examples/cra-kitchen-sink/src/components/Container.js b/code/examples/cra-kitchen-sink/src/components/Container.js deleted file mode 100644 index bea4d9d5c421..000000000000 --- a/code/examples/cra-kitchen-sink/src/components/Container.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const Container = ({ children, title, age, isAmazing }) => ( -
- {children} - {isAmazing ? '!!!' : ''} - {age.isOld ?
age = {age.value}
: null} -
-); - -Container.propTypes = { - /** - * The nodes to be rendered in the button - * - * Example value: - * - * ``` - *

Node 1

- *

Node 2

- * ``` - */ - children: PropTypes.node.isRequired, - /** Show exclamation marks */ - isAmazing: PropTypes.bool, - /** Show age prop */ - age: PropTypes.shape({ - isOld: PropTypes.bool, - value: PropTypes.number, - }), - /** Main title */ - title: PropTypes.string, -}; -Container.defaultProps = { - isAmazing: false, - age: { isOld: false, value: 0 }, - title: 'the best container ever', -}; - -export default Container; diff --git a/code/examples/cra-kitchen-sink/src/components/FastRefreshExample.js b/code/examples/cra-kitchen-sink/src/components/FastRefreshExample.js deleted file mode 100644 index d9e382ffa97c..000000000000 --- a/code/examples/cra-kitchen-sink/src/components/FastRefreshExample.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -export const FastRefreshExample = () => { - const [value, setValue] = React.useState('abc'); - return ( - <> - setValue(event.target.value)} /> -

Change the input value then this text in the component file.

-

The state of the input should be kept.

- - ); -}; diff --git a/code/examples/cra-kitchen-sink/src/components/LifecycleLogger.js b/code/examples/cra-kitchen-sink/src/components/LifecycleLogger.js deleted file mode 100644 index a98a6585ab9a..000000000000 --- a/code/examples/cra-kitchen-sink/src/components/LifecycleLogger.js +++ /dev/null @@ -1,53 +0,0 @@ -import React, { Component } from 'react'; -import { polyfill } from 'react-lifecycles-compat'; -import { logger } from '@storybook/client-logger'; - -function log(name) { - logger.info(`LifecycleLogger: ${name}`); -} - -// A component that logs its lifecycle so we can check that things happen -// the right number of times (i.e. we are using React properly) -class LifecycleLogger extends Component { - constructor() { - super(); - log('constructor'); - this.state = {}; - } - - componentDidMount() { - log('componentDidMount'); - } - - // deepscan-disable-next-line - getSnapshotBeforeUpdate() { - // deepscan-disable-next-line - log('getSnapshotBeforeUpdate'); - } - - componentDidUpdate() { - log('componentDidUpdate'); - } - - componentDidCatch() { - log('componentDidCatch'); - } - - componentWillUnmount() { - log('componentWillUnmount'); - } - - render() { - log('render'); - return
Lifecycle methods are logged to the console
; - } -} - -LifecycleLogger.getDerivedStateFromProps = () => { - log('getDerivedStateFromProps'); - return null; -}; - -polyfill(LifecycleLogger); - -export default LifecycleLogger; diff --git a/code/examples/cra-kitchen-sink/src/components/react-demo.js b/code/examples/cra-kitchen-sink/src/components/react-demo.js deleted file mode 100644 index 5e9f62860144..000000000000 --- a/code/examples/cra-kitchen-sink/src/components/react-demo.js +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; - -const styles = { - border: '1px solid #eee', - borderRadius: 3, - backgroundColor: '#FFFFFF', - cursor: 'pointer', - fontSize: 15, - padding: '3px 10px', - margin: 10, -}; - -// eslint-disable-next-line react/prop-types -export const Button = ({ children, onClick }) => ( - -); - -Button.displayName = 'Button'; -Button.defaultProps = { - onClick: () => {}, -}; - -// eslint-disable-next-line react/prop-types -export const Welcome = ({ showApp }) => ( - -); -Welcome.displayName = 'Welcome'; -Welcome.defaultProps = { - showApp: () => {}, -}; diff --git a/code/examples/cra-kitchen-sink/src/index.css b/code/examples/cra-kitchen-sink/src/index.css deleted file mode 100644 index b4cc7250b98c..000000000000 --- a/code/examples/cra-kitchen-sink/src/index.css +++ /dev/null @@ -1,5 +0,0 @@ -body { - margin: 0; - padding: 0; - font-family: sans-serif; -} diff --git a/code/examples/cra-kitchen-sink/src/index.js b/code/examples/cra-kitchen-sink/src/index.js deleted file mode 100644 index be499d982d50..000000000000 --- a/code/examples/cra-kitchen-sink/src/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import global from 'global'; - -import App from './App'; -import './index.css'; - -const { document } = global; - -ReactDOM.render(, document.getElementById('root')); diff --git a/code/examples/cra-kitchen-sink/src/logo.svg b/code/examples/cra-kitchen-sink/src/logo.svg deleted file mode 100644 index 9dfc1c058ceb..000000000000 --- a/code/examples/cra-kitchen-sink/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/code/examples/cra-kitchen-sink/src/stories/App.stories.js b/code/examples/cra-kitchen-sink/src/stories/App.stories.js deleted file mode 100644 index 5902417523b9..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/App.stories.js +++ /dev/null @@ -1,16 +0,0 @@ -// FIXME: svgr issue @igor-dv - -import React from 'react'; - -import App from '../App'; - -export default { - title: 'App', - parameters: { - layout: 'fullscreen', - }, -}; - -export const FullApp = () => ; - -FullApp.storyName = 'full app'; diff --git a/code/examples/cra-kitchen-sink/src/stories/Lifecycle.stories.js b/code/examples/cra-kitchen-sink/src/stories/Lifecycle.stories.js deleted file mode 100644 index 0a8fbaceb3ff..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/Lifecycle.stories.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import LifecycleLogger from '../components/LifecycleLogger'; - -export default { - title: 'Lifecycle', -}; - -export const Logging = () => ; diff --git a/code/examples/cra-kitchen-sink/src/stories/button.stories.js b/code/examples/cra-kitchen-sink/src/stories/button.stories.js deleted file mode 100644 index 20d13f8770c1..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/button.stories.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -import { Button } from '../components/react-demo'; - -export default { - title: 'Button', - component: Button, -}; - -export const Story1 = () => ; -Story1.storyName = 'with text'; - -Story1.parameters = { - options: { selectedPanel: 'storybook/actions/panel' }, -}; - -export const Story2 = () => ( - -); -Story2.storyName = 'with some emoji'; - -Story2.parameters = { - options: { selectedPanel: 'storybook/actions/panel' }, -}; diff --git a/code/examples/cra-kitchen-sink/src/stories/fast-refresh.stories.js b/code/examples/cra-kitchen-sink/src/stories/fast-refresh.stories.js deleted file mode 100644 index f96f85877dcf..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/fast-refresh.stories.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { FastRefreshExample } from '../components/FastRefreshExample'; - -export default { - title: 'React Fast Refresh', - component: FastRefreshExample, -}; - -export const Default = () => ; diff --git a/code/examples/cra-kitchen-sink/src/stories/force-rerender.stories.js b/code/examples/cra-kitchen-sink/src/stories/force-rerender.stories.js deleted file mode 100644 index 7c99c18e4c73..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/force-rerender.stories.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { forceReRender } from '@storybook/react'; -import { Button } from '../components/react-demo'; - -let count = 0; -const increment = () => { - count += 1; - forceReRender(); -}; - -export default { - title: 'Force ReRender', -}; - -export const DefaultView = () => ( - -); diff --git a/code/examples/cra-kitchen-sink/src/stories/long-description.stories.js b/code/examples/cra-kitchen-sink/src/stories/long-description.stories.js deleted file mode 100644 index 7fd35cd5122f..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/long-description.stories.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { Button } from '../components/react-demo'; - -export default { - title: 'Some really long story kind description', -}; - -export const Story1 = () => ; -Story1.storyName = 'with text'; diff --git a/code/examples/cra-kitchen-sink/src/stories/test.stories.mdx b/code/examples/cra-kitchen-sink/src/stories/test.stories.mdx deleted file mode 100644 index cfc8715570a6..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/test.stories.mdx +++ /dev/null @@ -1,14 +0,0 @@ -import { Story, Meta, ArgsTable } from '@storybook/addon-docs'; -import Container from '../components/Container' - - - - - -

Hello

-
-
- -## Arguments - - diff --git a/code/examples/cra-kitchen-sink/src/stories/welcome.stories.js b/code/examples/cra-kitchen-sink/src/stories/welcome.stories.js deleted file mode 100644 index f954ada420af..000000000000 --- a/code/examples/cra-kitchen-sink/src/stories/welcome.stories.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import { Welcome } from '../components/react-demo'; - -export default { - title: 'Welcome', - component: Welcome, -}; - -export const Story1 = () => {}} />; -Story1.title = 'to Storybook'; diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index e40a1f30d07c..478bde8346e4 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/frameworks/angular/src/client/config.ts b/code/frameworks/angular/src/client/config.ts index 109dd3b09104..bdc5cdf797c0 100644 --- a/code/frameworks/angular/src/client/config.ts +++ b/code/frameworks/angular/src/client/config.ts @@ -1,6 +1,6 @@ import './globals'; export { render, renderToDOM } from './render'; -export { decorateStory } from './decorateStory'; +export { decorateStory as applyDecorators } from './decorateStory'; export const parameters = { framework: 'angular' as const }; diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index 80c3c27b3359..8eb268eea612 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -26,7 +26,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index 1767189537e8..9840f5a315cd 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index fc5f416e0a0e..a64ea3d92fe8 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index 225c86d73a84..e2df08912f5f 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -47,7 +47,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index 3a4320f6b865..fec812c3ba2e 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -47,7 +47,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index 3a578a86618d..98e80d54082c 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 67b549e87eb6..64e955f5d037 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -47,7 +47,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 7d693fba89ae..f680287cb725 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -47,7 +47,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/vue-webpack5/package.json b/code/frameworks/vue-webpack5/package.json index 8cc6b6e8defb..b9fd4324feea 100644 --- a/code/frameworks/vue-webpack5/package.json +++ b/code/frameworks/vue-webpack5/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index 97524bb06e78..bafbd75fa6d9 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -47,7 +47,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index a741b58220a7..735694b18936 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index 2624b37aebad..cdcf476708ed 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -48,7 +48,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/jest.config.js b/code/jest.config.js index 90cfabc15c2c..2257d0df76cf 100644 --- a/code/jest.config.js +++ b/code/jest.config.js @@ -27,7 +27,6 @@ module.exports = { projects: [ '', // '/app/angular', - // '/examples/cra-kitchen-sink', // '/examples/cra-ts-kitchen-sink', // '/examples/html-kitchen-sink', // '/examples/svelte-kitchen-sink', diff --git a/code/lib/addons/package.json b/code/lib/addons/package.json index 668ad5b238e8..3c392def7076 100644 --- a/code/lib/addons/package.json +++ b/code/lib/addons/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/api/package.json b/code/lib/api/package.json index b13e83cf2e26..93538016d0a1 100644 --- a/code/lib/api/package.json +++ b/code/lib/api/package.json @@ -28,7 +28,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/builder-manager/package.json b/code/lib/builder-manager/package.json index cdd9f3f6377e..8c0518c7977e 100644 --- a/code/lib/builder-manager/package.json +++ b/code/lib/builder-manager/package.json @@ -37,7 +37,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/builder-vite/package.json b/code/lib/builder-vite/package.json index 78f108cbdb03..d66a7fdbe63e 100644 --- a/code/lib/builder-vite/package.json +++ b/code/lib/builder-vite/package.json @@ -14,7 +14,7 @@ "module": "dist/esm/index.js", "types": "dist/types/index.d.ts", "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/builder-webpack5/package.json b/code/lib/builder-webpack5/package.json index ba002f662f94..1f81df4b2260 100644 --- a/code/lib/builder-webpack5/package.json +++ b/code/lib/builder-webpack5/package.json @@ -29,7 +29,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/channel-postmessage/package.json b/code/lib/channel-postmessage/package.json index 8b006946d663..c7f0b71ef7cf 100644 --- a/code/lib/channel-postmessage/package.json +++ b/code/lib/channel-postmessage/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/channel-websocket/package.json b/code/lib/channel-websocket/package.json index b2f6f08d0826..acf5b883fc0c 100644 --- a/code/lib/channel-websocket/package.json +++ b/code/lib/channel-websocket/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/channels/package.json b/code/lib/channels/package.json index 2d3fc834f139..00d8dba61bdd 100644 --- a/code/lib/channels/package.json +++ b/code/lib/channels/package.json @@ -38,7 +38,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index f1612e3ffd48..0c1ca1a1196d 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -21,7 +21,7 @@ "license": "MIT", "bin": "./index.js", "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index d3427c1b6034..9cfbac19659e 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -24,7 +24,7 @@ "storybook": "./index.js" }, "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json index fa38b7066210..a63fad61fe96 100644 --- a/code/lib/cli/package.json +++ b/code/lib/cli/package.json @@ -36,7 +36,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts", "test": "jest test/**/*.test.js" }, diff --git a/code/lib/client-api/package.json b/code/lib/client-api/package.json index f5ace815e846..1dc719423182 100644 --- a/code/lib/client-api/package.json +++ b/code/lib/client-api/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/client-logger/package.json b/code/lib/client-logger/package.json index 0920a10be0d3..0c43765682e1 100644 --- a/code/lib/client-logger/package.json +++ b/code/lib/client-logger/package.json @@ -38,7 +38,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index 3eb6e158ea6c..6007ce9068bd 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -31,7 +31,7 @@ "!__testfixtures__" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/components/package.json b/code/lib/components/package.json index dc935f04dafa..be872a0239c7 100644 --- a/code/lib/components/package.json +++ b/code/lib/components/package.json @@ -47,7 +47,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/components/src/Zoom/Zoom.tsx b/code/lib/components/src/Zoom/Zoom.tsx index 629e94ea6f54..ab8ff55f7722 100644 --- a/code/lib/components/src/Zoom/Zoom.tsx +++ b/code/lib/components/src/Zoom/Zoom.tsx @@ -1,19 +1,6 @@ -import global from 'global'; import { ZoomElement } from './ZoomElement'; import { ZoomIFrame } from './ZoomIFrame'; -const { window: globalWindow } = global; - -export const browserSupportsCssZoom = (): boolean => { - try { - return ( - globalWindow.document.implementation.createHTMLDocument('').body.style.zoom !== undefined - ); - } catch (error) { - return false; - } -}; - export const Zoom = { Element: ZoomElement, IFrame: ZoomIFrame, diff --git a/code/lib/components/src/Zoom/ZoomElement.tsx b/code/lib/components/src/Zoom/ZoomElement.tsx index 61c2478a3b66..ba2f4d981cf6 100644 --- a/code/lib/components/src/Zoom/ZoomElement.tsx +++ b/code/lib/components/src/Zoom/ZoomElement.tsx @@ -1,9 +1,20 @@ -import React, { ReactElement, useEffect, useRef, useState } from 'react'; +/* global MutationObserver */ +import React, { + ReactElement, + useEffect, + useRef, + useState, + useMemo, + RefObject, + useCallback, +} from 'react'; import { styled } from '@storybook/theming'; import { browserSupportsCssZoom } from './browserSupportsCssZoom'; +const hasBrowserSupportForCssZoom = browserSupportsCssZoom(); + const ZoomElementWrapper = styled.div<{ scale: number; height: number }>(({ scale = 1, height }) => - browserSupportsCssZoom() + hasBrowserSupportForCssZoom ? { '> *': { zoom: 1 / scale, @@ -15,6 +26,35 @@ const ZoomElementWrapper = styled.div<{ scale: number; height: number }>(({ scal transform: `scale(${1 / scale})`, } ); + +const useMutationObserver = ({ + element, + options = {}, + callback, +}: { + element: RefObject; + options: MutationObserverInit; + callback: MutationCallback; +}): void => { + const observer = useMemo( + () => + new MutationObserver((mutationRecord, mutationObserver) => { + callback(mutationRecord, mutationObserver); + }), + [callback] + ); + + useEffect(() => { + if (element?.current) { + observer.observe(element.current, options); + } + + return () => observer.disconnect(); + }, [element, observer, options]); +}; + +const mutationObserverOptions = { subtree: true, childList: true }; + type ZoomProps = { scale: number; children: ReactElement | ReactElement[]; @@ -24,15 +64,28 @@ export function ZoomElement({ scale, children }: ZoomProps) { const componentWrapperRef = useRef(null); const [height, setHeight] = useState(0); + const handleMutations = useCallback(() => { + setHeight(componentWrapperRef.current.getBoundingClientRect().height); + }, []); + useEffect(() => { if (componentWrapperRef.current) { setHeight(componentWrapperRef.current.getBoundingClientRect().height); } }, [scale, componentWrapperRef.current]); + useMutationObserver({ + element: componentWrapperRef, + options: mutationObserverOptions, + callback: handleMutations, + }); + return ( -
+
{children}
diff --git a/code/lib/core-client/package.json b/code/lib/core-client/package.json index 47ad8bc46abf..75cf456ceeae 100644 --- a/code/lib/core-client/package.json +++ b/code/lib/core-client/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json index 30b582160d52..a969a98e0450 100644 --- a/code/lib/core-common/package.json +++ b/code/lib/core-common/package.json @@ -42,7 +42,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/core-common/src/utils/progress-reporting.ts b/code/lib/core-common/src/utils/progress-reporting.ts index 0153b9eaa1ee..79fe34af05b2 100644 --- a/code/lib/core-common/src/utils/progress-reporting.ts +++ b/code/lib/core-common/src/utils/progress-reporting.ts @@ -8,8 +8,11 @@ export const useProgressReporting = async ( ): Promise<{ handler: any; modulesCount: number }> => { let value = 0; let totalModules: number; - let reportProgress: (progress?: { value?: number; message: string; modules?: any }) => void = - () => {}; + let reportProgress: (progress?: { + value?: number; + message: string; + modules?: any; + }) => void = () => {}; router.get('/progress', (request: Request, response: Response) => { let closed = false; diff --git a/code/lib/core-events/package.json b/code/lib/core-events/package.json index 45aba27f6a32..7b38af3479bb 100644 --- a/code/lib/core-events/package.json +++ b/code/lib/core-events/package.json @@ -38,7 +38,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "devDependencies": { diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index b27c1cc81883..2de60febfb33 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -29,7 +29,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index 0485f1582d6d..bc3c364cb691 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -38,7 +38,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/csf-tools/package.json b/code/lib/csf-tools/package.json index 4b57500429b4..94cfe3e552e7 100644 --- a/code/lib/csf-tools/package.json +++ b/code/lib/csf-tools/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/docs-tools/package.json b/code/lib/docs-tools/package.json index 41a93d4266aa..e0a4580a2b25 100644 --- a/code/lib/docs-tools/package.json +++ b/code/lib/docs-tools/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json index 10da61b9dd54..d810d4ba862d 100644 --- a/code/lib/instrumenter/package.json +++ b/code/lib/instrumenter/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/node-logger/package.json b/code/lib/node-logger/package.json index 7e79fa3604cf..6069b375cdaf 100644 --- a/code/lib/node-logger/package.json +++ b/code/lib/node-logger/package.json @@ -20,9 +20,17 @@ }, "license": "MIT", "sideEffects": false, - "main": "dist/cjs/index.js", - "module": "dist/esm/index.js", - "types": "dist/types/index.d.ts", + "exports": { + ".": { + "require": "./dist/index.js", + "import": "./dist/index.mjs", + "types": "./dist/index.d.ts" + }, + "./package.json": "./package.json" + }, + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", "files": [ "dist/**/*", "README.md", @@ -30,8 +38,8 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", - "prep": "node ../../../scripts/prepare.js" + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", + "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { "@types/npmlog": "^4.1.2", @@ -46,5 +54,10 @@ "publishConfig": { "access": "public" }, + "bundler": { + "entries": [ + "./src/index.ts" + ] + }, "gitHead": "5da5b0fabd04cc5cd5771e8242a960f05d03234a" } diff --git a/code/lib/postinstall/package.json b/code/lib/postinstall/package.json index b1f45c0a3595..8a6ecdd6a0b1 100644 --- a/code/lib/postinstall/package.json +++ b/code/lib/postinstall/package.json @@ -31,7 +31,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "devDependencies": { diff --git a/code/lib/preview-web/package.json b/code/lib/preview-web/package.json index bff2c63a31ed..05dfc840ecc5 100644 --- a/code/lib/preview-web/package.json +++ b/code/lib/preview-web/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/router/package.json b/code/lib/router/package.json index a8adcaaee3a1..80ff93498865 100644 --- a/code/lib/router/package.json +++ b/code/lib/router/package.json @@ -43,7 +43,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index ba3a2bac366c..6fb23223d015 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -31,7 +31,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/store/package.json b/code/lib/store/package.json index 6df5da61b723..1f16bd1823d7 100644 --- a/code/lib/store/package.json +++ b/code/lib/store/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/store/src/csf/testing-utils/types.ts b/code/lib/store/src/csf/testing-utils/types.ts index 498e091aedac..ad627ef7c618 100644 --- a/code/lib/store/src/csf/testing-utils/types.ts +++ b/code/lib/store/src/csf/testing-utils/types.ts @@ -17,8 +17,10 @@ export type ComposedStoryPlayContext = Partial & Pick Promise | void; -export type StoryFn = - AnnotatedStoryFn & { play: ComposedStoryPlayFn }; +export type StoryFn< + TFramework extends AnyFramework = AnyFramework, + TArgs = Args +> = AnnotatedStoryFn & { play: ComposedStoryPlayFn }; export type ComposedStory = | StoryFn diff --git a/code/lib/telemetry/package.json b/code/lib/telemetry/package.json index 6666c75271be..fdb9b49bbb6b 100644 --- a/code/lib/telemetry/package.json +++ b/code/lib/telemetry/package.json @@ -30,7 +30,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "node ../../../scripts/prepare.js" }, "dependencies": { diff --git a/code/lib/theming/package.json b/code/lib/theming/package.json index b31f398d5ffe..3750c5f070c9 100644 --- a/code/lib/theming/package.json +++ b/code/lib/theming/package.json @@ -43,7 +43,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/lib/ui/package.json b/code/lib/ui/package.json index fbcd3b2ea07a..4a47efecb8a0 100644 --- a/code/lib/ui/package.json +++ b/code/lib/ui/package.json @@ -48,7 +48,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "devDependencies": { diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json index 8254904d5ff5..174b88f16c35 100644 --- a/code/presets/html-webpack/package.json +++ b/code/presets/html-webpack/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json index 781bfc61c1ab..a2a22ad8b585 100644 --- a/code/presets/preact-webpack/package.json +++ b/code/presets/preact-webpack/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index 2a0d3244ec2b..23511bc5863c 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -67,7 +67,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json index 790e3b59dcec..87d92bbad444 100644 --- a/code/presets/server-webpack/package.json +++ b/code/presets/server-webpack/package.json @@ -51,7 +51,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index ce3b4cddaf03..1f78b94c9d5e 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -61,7 +61,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/presets/vue-webpack/package.json b/code/presets/vue-webpack/package.json index 61b8808c818d..a275be4113e6 100644 --- a/code/presets/vue-webpack/package.json +++ b/code/presets/vue-webpack/package.json @@ -56,7 +56,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json index bde6b5573678..34770c4444a3 100644 --- a/code/presets/vue3-webpack/package.json +++ b/code/presets/vue3-webpack/package.json @@ -56,7 +56,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/presets/web-components-webpack/package.json b/code/presets/web-components-webpack/package.json index 92feb1103543..139c55b10025 100644 --- a/code/presets/web-components-webpack/package.json +++ b/code/presets/web-components-webpack/package.json @@ -48,7 +48,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json index fb371903aaf6..e6ee5ee00edd 100644 --- a/code/renderers/html/package.json +++ b/code/renderers/html/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index c3da87513466..6727623d0d83 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index d536ddd226f7..3dda72ddfb16 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -47,7 +47,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/react/template/stories/errors.stories.tsx b/code/renderers/react/template/stories/errors.stories.tsx index 3792ecd11d0c..3a599df47f2a 100644 --- a/code/renderers/react/template/stories/errors.stories.tsx +++ b/code/renderers/react/template/stories/errors.stories.tsx @@ -26,6 +26,7 @@ export const StoryIsUnrenderable = { export const StoryContainsUnrenderable = { render: () => (
+ {/* @ts-expect-error */}
), diff --git a/code/renderers/server/package.json b/code/renderers/server/package.json index 3ed4433e7755..a3ea2c4d152c 100644 --- a/code/renderers/server/package.json +++ b/code/renderers/server/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index b44ac2169e60..11248120f1a7 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -50,7 +50,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/svelte/template/stories/README.md b/code/renderers/svelte/template/stories/README.md new file mode 100644 index 000000000000..37d8743baec7 --- /dev/null +++ b/code/renderers/svelte/template/stories/README.md @@ -0,0 +1 @@ +Placeholder until we write some render-specific stories diff --git a/code/renderers/vue/package.json b/code/renderers/vue/package.json index bbd7df617dc9..aa90f7d9f44e 100644 --- a/code/renderers/vue/package.json +++ b/code/renderers/vue/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/vue3/package.json b/code/renderers/vue3/package.json index 01c271e5b08c..8454d6d72942 100644 --- a/code/renderers/vue3/package.json +++ b/code/renderers/vue3/package.json @@ -46,7 +46,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/renderers/vue3/template/stories/README.md b/code/renderers/vue3/template/stories/README.md new file mode 100644 index 000000000000..37d8743baec7 --- /dev/null +++ b/code/renderers/vue3/template/stories/README.md @@ -0,0 +1 @@ +Placeholder until we write some render-specific stories diff --git a/code/renderers/web-components/package.json b/code/renderers/web-components/package.json index b66fff4294aa..1cc0768d77af 100644 --- a/code/renderers/web-components/package.json +++ b/code/renderers/web-components/package.json @@ -48,7 +48,7 @@ "*.d.ts" ], "scripts": { - "check": "tsc --noEmit", + "check": "../../../scripts/node_modules/.bin/tsc --noEmit", "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { diff --git a/code/workspace.json b/code/workspace.json index da1afc7921a1..a08ed1c6f24a 100644 --- a/code/workspace.json +++ b/code/workspace.json @@ -411,11 +411,6 @@ "type": "library", "implicitDependencies": [] }, - "cra-kitchen-sink": { - "root": "examples/cra-kitchen-sink", - "type": "library", - "implicitDependencies": [] - }, "cra-ts-kitchen-sink": { "root": "examples/cra-ts-kitchen-sink", "type": "library", diff --git a/code/yarn.lock b/code/yarn.lock index a36a8805ad67..a947e264336b 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -17458,37 +17458,6 @@ __metadata: languageName: node linkType: hard -"cra-kitchen-sink@workspace:examples/cra-kitchen-sink": - version: 0.0.0-use.local - resolution: "cra-kitchen-sink@workspace:examples/cra-kitchen-sink" - dependencies: - "@pmmmwh/react-refresh-webpack-plugin": ^0.5.5 - "@storybook/addon-a11y": 7.0.0-alpha.33 - "@storybook/addon-actions": 7.0.0-alpha.33 - "@storybook/addon-backgrounds": 7.0.0-alpha.33 - "@storybook/addon-docs": 7.0.0-alpha.33 - "@storybook/addon-highlight": 7.0.0-alpha.33 - "@storybook/addon-jest": 7.0.0-alpha.33 - "@storybook/addon-links": 7.0.0-alpha.33 - "@storybook/addon-storyshots": 7.0.0-alpha.33 - "@storybook/addons": 7.0.0-alpha.33 - "@storybook/builder-webpack5": 7.0.0-alpha.33 - "@storybook/client-logger": 7.0.0-alpha.33 - "@storybook/preset-create-react-app": ^4.1.0 - "@storybook/react": 7.0.0-alpha.33 - "@storybook/react-webpack5": 7.0.0-alpha.33 - "@storybook/theming": 7.0.0-alpha.33 - global: ^4.4.0 - prop-types: ^15.7.2 - react: 16.14.0 - react-dom: 16.14.0 - react-lifecycles-compat: ^3.0.4 - react-scripts: ^5.0.1 - storybook: 7.0.0-alpha.33 - webpack: 5 - languageName: unknown - linkType: soft - "cra-ts-kitchen-sink@workspace:examples/cra-ts-kitchen-sink": version: 0.0.0-use.local resolution: "cra-ts-kitchen-sink@workspace:examples/cra-ts-kitchen-sink" @@ -37452,7 +37421,7 @@ __metadata: languageName: node linkType: hard -"react-lifecycles-compat@npm:^3.0.0, react-lifecycles-compat@npm:^3.0.4": +"react-lifecycles-compat@npm:^3.0.0": version: 3.0.4 resolution: "react-lifecycles-compat@npm:3.0.4" checksum: 1d0df3c85af79df720524780f00c064d53a9dd1899d785eddb7264b378026979acbddb58a4b7e06e7d0d12aa1494fd5754562ee55d32907b15601068dae82c27 diff --git a/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx index 546d391f02db..0e7fd887e118 100644 --- a/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx @@ -17,20 +17,11 @@ import { MyComponent } from './MyComponent.component'; { + play={async () => { // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel await userEvent.click(screen.getByRole('button', { name: / button label/i })); }} render={(args) => ({ props: args, })} /> - { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }} - render={(args) => ({ - props: args, - })} /> ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx b/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx index 2a0ee07f7cfc..36f5458a3e27 100644 --- a/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx @@ -1,7 +1,7 @@ ```ts // MyComponent.stories.ts -import type { Meta, Story } from '@storybook/addon-docs'; +import type { Meta, Story } from '@storybook/angular'; import { screen, userEvent } from '@storybook/testing-library'; @@ -22,11 +22,4 @@ export const ExampleWithRole: Story = { await userEvent.click(screen.getByRole('button', { name: / button label/i })); }, }; - -export const ExampleWithText: Story = { - play: async () => { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }, -}; ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/angular/my-component-play-function-query-findby.mdx.mdx new file mode 100644 index 000000000000..cef66ae17b66 --- /dev/null +++ b/docs/snippets/angular/my-component-play-function-query-findby.mdx.mdx @@ -0,0 +1,29 @@ +```md + + +import { Meta, Story }Β from '@storybook/addon-docs'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import { MyComponent } from './MyComponent.component'; + + + + + + { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }} + render={(args) => ({ + props: args, + })} /> +``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-query-findby.ts.mdx b/docs/snippets/angular/my-component-play-function-query-findby.ts.mdx new file mode 100644 index 000000000000..ba9229b5c11e --- /dev/null +++ b/docs/snippets/angular/my-component-play-function-query-findby.ts.mdx @@ -0,0 +1,27 @@ +```ts +// MyComponent.stories.ts + +import type { Meta, Story } from '@storybook/angular'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import { MyComponent } from './MyComponent.component'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Async Query Methods', + component: MyComponent, +} as Meta; + +export const AsyncExample: Story = { + play: async () => { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-alt-queries.js.mdx b/docs/snippets/react/my-component-play-function-alt-queries.js.mdx index 2b1101f8e042..8017824f22fa 100644 --- a/docs/snippets/react/my-component-play-function-alt-queries.js.mdx +++ b/docs/snippets/react/my-component-play-function-alt-queries.js.mdx @@ -20,11 +20,4 @@ export const ExampleWithRole = { await userEvent.click(screen.getByRole('button', { name: / button label/i })); }, }; - -export const ExampleWithText = { - play: async () => { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }, -}; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx index 8ece56cb44a1..c4b5cf2f9d1e 100644 --- a/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx @@ -17,13 +17,4 @@ import { MyComponent } from './MyComponent'; }}> - - { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }}> - - ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx b/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx index 8233e7f6f030..2902b937a742 100644 --- a/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx +++ b/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx @@ -24,11 +24,4 @@ export const ExampleWithRole: ComponentStoryObj = { await userEvent.click(screen.getByRole('button', { name: / button label/i })); }, }; - -export const ExampleWithText: ComponentStoryObj = { - play: async () => { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }, -}; ``` diff --git a/docs/snippets/react/my-component-play-function-query-findby.js.mdx b/docs/snippets/react/my-component-play-function-query-findby.js.mdx new file mode 100644 index 000000000000..c133b906a64f --- /dev/null +++ b/docs/snippets/react/my-component-play-function-query-findby.js.mdx @@ -0,0 +1,25 @@ +```js +// MyComponent.stories.js|jsx + +import { screen, userEvent } from '@storybook/testing-library'; + +import { MyComponent } from './MyComponent'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Async Query Methods', + component: MyComponent, +}; + +export const AsyncExample = { + play: async () => { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/react/my-component-play-function-query-findby.mdx.mdx new file mode 100644 index 000000000000..dc3a28e2c841 --- /dev/null +++ b/docs/snippets/react/my-component-play-function-query-findby.mdx.mdx @@ -0,0 +1,22 @@ +```md + + +import { Meta, Story } from '@storybook/addon-docs'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import { MyComponent } from './MyComponent'; + + + + { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }}> + + +``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-query-findby.ts.mdx b/docs/snippets/react/my-component-play-function-query-findby.ts.mdx new file mode 100644 index 000000000000..6d8a48bb8e30 --- /dev/null +++ b/docs/snippets/react/my-component-play-function-query-findby.ts.mdx @@ -0,0 +1,29 @@ +```ts +// MyComponent.stories.ts|tsx + +import React from 'react'; + +import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import { MyComponent } from './MyComponent'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Async Query Methods', + component: MyComponent, +} as ComponentMeta; + +export const AsyncExample: ComponentStoryObj = { + play: async () => { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx b/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx index 1385646d5086..91175c94b285 100644 --- a/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx @@ -21,23 +21,12 @@ export default { */ export const ExampleWithRole = { render: (args) => ({ - Component: Button, + Component: MyComponent, props: args, }), play: async () => { - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel await userEvent.click(screen.getByRole('button', { name: / button label/i })); }, }; - -export const ExampleWithText = { - render: (args) => ({ - Component: Button, - props: args, - }), - play: async () => { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }, -}; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx index 01cd59c66709..c3994d606519 100644 --- a/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx @@ -25,14 +25,4 @@ import MyComponent from './MyComponent.svelte'; Component: MyComponent, props: args, })} /> - { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-query-findby.js.mdx b/docs/snippets/svelte/my-component-play-function-query-findby.js.mdx new file mode 100644 index 000000000000..ddcd1e605b52 --- /dev/null +++ b/docs/snippets/svelte/my-component-play-function-query-findby.js.mdx @@ -0,0 +1,34 @@ +```js +// MyComponent.stories.js + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.svelte'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Async Query Methods', + component: MyComponent, +}; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/svelte/api/csf + * to learn how to use render functions. + */ +export const AsyncExample = { + render: (args) => ({ + Component: MyComponent, + props: args, + }), + play: async () => { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/svelte/my-component-play-function-query-findby.mdx.mdx new file mode 100644 index 000000000000..af2acc4a66f3 --- /dev/null +++ b/docs/snippets/svelte/my-component-play-function-query-findby.mdx.mdx @@ -0,0 +1,30 @@ +```md + + +import { Meta, Story } from '@storybook/addon-docs'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.svelte'; + + + + + + { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }} + render={(args) => ({ + Component: MyComponent, + props: args, + })} /> +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx b/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx index e08ee1f538e0..ee1cbfc0fd60 100644 --- a/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx +++ b/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx @@ -29,15 +29,4 @@ export const ExampleWithRole = { await userEvent.click(screen.getByRole('button', { name: / button label/i })); }, }; - -export const ExampleWithText = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // The play function interacts with the component and looks for the text - await screen.findByText('example string'); - }, -}; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx index eb46c3de5a75..5db21a34f92a 100644 --- a/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx @@ -19,19 +19,10 @@ import MyComponent from './MyComponent.vue'; name="ExampleWithRole" play={ async () => { // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByRole('button', { name: / button label/i })); }} render={() => ({ components: { MyComponent }, - template: '', - })} /> - { - await screen.findByText('example string'); - }} - render={() => ({ - components: { MyComponent }, - template: '', + template: '', })} /> ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-alt-queries.ts.mdx b/docs/snippets/vue/my-component-play-function-alt-queries.ts.mdx new file mode 100644 index 000000000000..c177c34a853e --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-alt-queries.ts.mdx @@ -0,0 +1,36 @@ +```ts +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'QueryMethods', + component: MyComponent, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ + +export const ExampleWithRole: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(screen.getByRole('button', { name: / button label/i })); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-composition.ts.mdx b/docs/snippets/vue/my-component-play-function-composition.ts.mdx new file mode 100644 index 000000000000..a51e86d8905a --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-composition.ts.mdx @@ -0,0 +1,58 @@ +```ts +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'MyComponent', + component: MyComponent, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ + +export const FirstStory: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + userEvent.type(screen.getByTestId('an-element'), 'example-value'); + }, +}; + +export const SecondStory: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + await userEvent.type(screen.getByTestId('other-element'), 'another value'); + }, +}; + +export const CombinedStories: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + // Runs the FirstStory and Second story play function before running this story's play function + await FirstStory.play(); + await SecondStory.play(); + await userEvent.type(screen.getByTestId('another-element'), 'random value'); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-query-findby.js.mdx b/docs/snippets/vue/my-component-play-function-query-findby.js.mdx new file mode 100644 index 000000000000..3c2097674dc1 --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-query-findby.js.mdx @@ -0,0 +1,34 @@ +```js +// MyComponent.stories.js + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Async Query Methods', + component: MyComponent, +}; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ +export const AsyncExample = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/vue/my-component-play-function-query-findby.mdx.mdx new file mode 100644 index 000000000000..0109bc0d69b6 --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-query-findby.mdx.mdx @@ -0,0 +1,30 @@ +```md + + +import { Meta, Story } from '@storybook/addon-docs'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + + + + + + { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }} + render={() => ({ + components: { MyComponent }, + template: '', + })} /> +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-query-findby.ts.mdx b/docs/snippets/vue/my-component-play-function-query-findby.ts.mdx new file mode 100644 index 000000000000..4b880a8ed4fb --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-query-findby.ts.mdx @@ -0,0 +1,38 @@ +```js +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Async Query Methods', + component: MyComponent, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ + +export const AsyncExample: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + // Other steps + + // Waits for the component to be rendered before querying the element + await screen.findByRole('button', { name: / button label/i })); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-waitfor.js.mdx b/docs/snippets/vue/my-component-play-function-waitfor.js.mdx index afe123c71c7e..824a51ce6c38 100644 --- a/docs/snippets/vue/my-component-play-function-waitfor.js.mdx +++ b/docs/snippets/vue/my-component-play-function-waitfor.js.mdx @@ -25,7 +25,7 @@ export const ExampleAsyncStory = { template: '', }), play: async () => { - const exampleElement = screen.getByLabelText('example-element', { + const exampleElement = screen.getByLabelText('Username', { selector: 'input', }); diff --git a/docs/snippets/vue/my-component-play-function-waitfor.ts.mdx b/docs/snippets/vue/my-component-play-function-waitfor.ts.mdx new file mode 100644 index 000000000000..8fc40d53df67 --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-waitfor.ts.mdx @@ -0,0 +1,47 @@ +```ts +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { screen, userEvent, waitFor } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'WithAsync', + component: MyComponent, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ + +export const ExampleAsyncStory: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + const Input = screen.getByLabelText('Username', { + selector: 'input', + }); + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = screen.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(screen.getByTestId('error')); + }); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-canvas.js.mdx b/docs/snippets/vue/my-component-play-function-with-canvas.js.mdx index c1ecae5aabfa..5a972cb4d332 100644 --- a/docs/snippets/vue/my-component-play-function-with-canvas.js.mdx +++ b/docs/snippets/vue/my-component-play-function-with-canvas.js.mdx @@ -30,7 +30,7 @@ export const ExampleStory = { // Starts querying from the component's root element await userEvent.type(canvas.getByTestId('example-element'), 'something'); - await userEvent.type(canvas.getByTestId('another-element'), 'something else'); + await userEvent.click(canvas.getByRole('another-element')); }, }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-canvas.ts.mdx b/docs/snippets/vue/my-component-play-function-with-canvas.ts.mdx new file mode 100644 index 000000000000..88882b52ee0c --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-with-canvas.ts.mdx @@ -0,0 +1,40 @@ +```ts + +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { getByRole, userEvent, within } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'WithCanvasElement', + component: MyComponent, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ +export const ExampleStory: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async ({ canvasElement }) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + + // Starts querying from the component's root element + await userEvent.type(canvas.getByTestId('example-element'), 'something'); + await userEvent.click(canvas.getByRole('another-element')); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-clickevent.ts.mdx b/docs/snippets/vue/my-component-play-function-with-clickevent.ts.mdx new file mode 100644 index 000000000000..0c11379e6fec --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-with-clickevent.ts.mdx @@ -0,0 +1,47 @@ +```ts +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { fireEvent, screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'ClickExamples', + component: MyComponent, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ + +export const ClickExample: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(screen.getByRole('button')); + }, +}; + +export const FireEventExample: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(screen.getByTestId('data-testid')); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-delay.ts.mdx b/docs/snippets/vue/my-component-play-function-with-delay.ts.mdx new file mode 100644 index 000000000000..3c70bff040dd --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-with-delay.ts.mdx @@ -0,0 +1,44 @@ +```ts +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'WithDelay', + component: MyComponent, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ +export const DelayedStory: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + const exampleElement = screen.getByLabelText('example-element'); + + // The delay option set the ammount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = screen.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-selectevent.ts.mdx b/docs/snippets/vue/my-component-play-function-with-selectevent.ts.mdx new file mode 100644 index 000000000000..88728586349f --- /dev/null +++ b/docs/snippets/vue/my-component-play-function-with-selectevent.ts.mdx @@ -0,0 +1,48 @@ +```ts +// MyComponent.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import MyComponent from './MyComponent.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'WithSelectEvent', + component: WithSelectEvent, +} as Meta; + +// Custom function to emulate a pause +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ + +export const ExampleChangeEvent: Story = { + render: () => ({ + components: { MyComponent }, + template: '', + }), + play: async () => { + const select = screen.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); + }, +}; +``` \ No newline at end of file diff --git a/docs/snippets/vue/register-component-with-play-function.mdx.mdx b/docs/snippets/vue/register-component-with-play-function.mdx.mdx index d133cc0e8fbd..a77bf6f70344 100644 --- a/docs/snippets/vue/register-component-with-play-function.mdx.mdx +++ b/docs/snippets/vue/register-component-with-play-function.mdx.mdx @@ -35,8 +35,9 @@ import RegistrationForm from './RegistrationForm.vue'; }); // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - await userEvent.click(Submit); + const submitButton = screen.getByRole('button'); + + await userEvent.click(submitButton); }} render={() => ({ components: { RegistrationForm }, diff --git a/docs/snippets/vue/register-component-with-play-function.ts.mdx b/docs/snippets/vue/register-component-with-play-function.ts.mdx new file mode 100644 index 000000000000..4bb6bd2c4416 --- /dev/null +++ b/docs/snippets/vue/register-component-with-play-function.ts.mdx @@ -0,0 +1,52 @@ +```ts +// RegistrationForm.stories.ts + +// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 +import type { Meta, Story } from '@storybook/vue'; + +import { screen, userEvent } from '@storybook/testing-library'; + +import RegistrationForm from './RegistrationForm.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'RegistrationForm', + component: RegistrationForm, +} as Meta; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ +export const FilledForm: Story = { + render: () => ({ + components: { RegistrationForm }, + template: '', + }), + play: async () => { + const emailInput = screen.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = screen.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + + // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = screen.getByRole('button'); + await userEvent.click(submitButton); + }, +}; +``` \ No newline at end of file diff --git a/docs/why-storybook.md b/docs/why-storybook.md index 1f92e7c381cf..b640ff11699f 100644 --- a/docs/why-storybook.md +++ b/docs/why-storybook.md @@ -16,7 +16,7 @@ The breadth of modern frontends overwhelm existing workflows. Developers must co ## The solution -**Build UIs in isolation** +#### Build UIs in isolation Every piece of UI is now a [component](https://www.componentdriven.org/). The superpower of components is that you don't need to spin up the whole app just to see how they render. You can render a specific variation in isolation by passing in props, mocking data, or faking events. @@ -29,7 +29,7 @@ Storybook is packaged as a small, development-only, [workshop](https://bradfrost /> -**Capture UI variations as β€œstories”** +#### Capture UI variations as β€œstories” When developing a component variation in isolation, save it as a story. [Stories](https://github.com/ComponentDriven/csf) are a declarative syntax for supplying props and mock data to simulate component variations. Each component can have multiple stories. Each story allows you to demonstrate a specific variation of that component to verify appearance and behavior. @@ -62,7 +62,7 @@ You write stories for granular UI component variation and then use those stories -**Storybook keeps track of every story** +#### Storybook keeps track of every story Storybook is an interactive directory of your UI components and their stories. In the past, you'd have to spin up the app, navigate to a page, and contort the UI into the right state. This is a huge waste of time and bogs down frontend development. With Storybook, you can skip all those steps and jump straight to working on a UI component in a specific state. @@ -109,23 +109,23 @@ Most community members choose a [Component-Driven](https://www.componentdriven.o When you write stories for components, you get a bunch of additional benefits for free. -**πŸ“ Develop UIs that are more durable** +#### πŸ“ Develop UIs that are more durable Isolate components and pages and track their use cases as [stories](./writing-stories/introduction.md). Verify hard-to-reach edge cases of UI. Use addons to mock everything a component needsβ€”context, API requests, device features, etc. -**βœ… Test UIs with less effort and no flakes** +#### βœ… Test UIs with less effort and no flakes Stories are a pragmatic, reproducible way of tracking UI states. Use them to spot-test the UI during development. Storybook offers built-in workflows for automated [Accessibility](./writing-tests/accessibility-testing.md), [Interaction](./writing-tests/interaction-testing.md), and [Visual](./writing-tests/visual-testing.md) testing. Or use stories as test cases by importing them into other JavaScript testing tools. -**πŸ“š Document UI for your team to reuse** +#### πŸ“š Document UI for your team to reuse Storybook is the single source of truth for your UI. Stories index all your components and their various states, making it easy for your team to find and reuse existing UI patterns. Storybook also auto-generates [documentation](./writing-docs/introduction.md) from those stories. -**πŸ“€ Share how the UI actually works** +#### πŸ“€ Share how the UI actually works Stories show how UIs actually work, not just a picture of how they're supposed to work. That keeps everyone aligned on what's currently in production. [Publish Storybook](./sharing/publish-storybook.md) to get sign-off from teammates. Or [embed](./sharing/embed.md) them in wikis, Markdown, and Figma to streamline collaboration. -**🚦Automate UI workflows** +#### 🚦Automate UI workflows Storybook is compatible with your continuous integration workflow. Add it as a CI step to automate user interface testing, review implementation with teammates, and get signoff from stakeholders. diff --git a/docs/writing-stories/play-function.md b/docs/writing-stories/play-function.md index b95c7514ff0f..05a2a6ed768c 100644 --- a/docs/writing-stories/play-function.md +++ b/docs/writing-stories/play-function.md @@ -47,6 +47,7 @@ Storybook's `play` functions are small code snippets that run once the story fin 'angular/register-component-with-play-function.ts.mdx', 'angular/register-component-with-play-function.mdx.mdx', 'vue/register-component-with-play-function.js.mdx', + 'vue/register-component-with-play-function.ts.mdx', 'vue/register-component-with-play-function.mdx.mdx', 'svelte/register-component-with-play-function.js.mdx', 'svelte/register-component-with-play-function.mdx.mdx', @@ -75,6 +76,7 @@ Thanks to the [Component Story Format](../api/csf.md), an ES6 module based file 'react/my-component-play-function-composition.ts.mdx', 'angular/my-component-play-function-composition.ts.mdx', 'vue/my-component-play-function-composition.js.mdx', + 'vue/my-component-play-function-composition.ts.mdx', 'svelte/my-component-play-function-composition.js.mdx', ]} /> @@ -99,6 +101,7 @@ A common type of component interaction is a button click. If you need to reprodu 'angular/my-component-play-function-with-clickevent.ts.mdx', 'angular/my-component-play-function-with-clickevent.mdx.mdx', 'vue/my-component-play-function-with-clickevent.js.mdx', + 'vue/my-component-play-function-with-clickevent.ts.mdx', 'vue/my-component-play-function-with-clickevent.mdx.mdx', 'svelte/my-component-play-function-with-clickevent.js.mdx', 'svelte/my-component-play-function-with-clickevent.mdx.mdx', @@ -121,6 +124,7 @@ Asides from click events, you can also script additional events with the `play` 'angular/my-component-play-function-with-selectevent.ts.mdx', 'angular/my-component-play-function-with-selectevent.mdx.mdx', 'vue/my-component-play-function-with-selectevent.js.mdx', + 'vue/my-component-play-function-with-selectevent.ts.mdx', 'vue/my-component-play-function-with-selectevent.mdx.mdx', 'svelte/my-component-play-function-with-selectevent.js.mdx', 'svelte/my-component-play-function-with-selectevent.mdx.mdx', @@ -141,6 +145,7 @@ In addition to events, you can also create interactions with the `play` function 'angular/my-component-play-function-with-delay.ts.mdx', 'angular/my-component-play-function-with-delay.mdx.mdx', 'vue/my-component-play-function-with-delay.js.mdx', + 'vue/my-component-play-function-with-delay.ts.mdx', 'vue/my-component-play-function-with-delay.mdx.mdx', 'svelte/my-component-play-function-with-delay.js.mdx', 'svelte/my-component-play-function-with-delay.mdx.mdx', @@ -163,6 +168,7 @@ You can also use the `play` function to verify the existence of an element based 'angular/my-component-play-function-waitfor.ts.mdx', 'angular/my-component-play-function-waitfor.mdx.mdx', 'vue/my-component-play-function-waitfor.js.mdx', + 'vue/my-component-play-function-waitfor.ts.mdx', 'vue/my-component-play-function-waitfor.mdx.mdx', 'svelte/my-component-play-function-waitfor.js.mdx', 'svelte/my-component-play-function-waitfor.mdx.mdx', @@ -185,6 +191,7 @@ If you need, you can also adjust your `play` function to find elements based on 'angular/my-component-play-function-alt-queries.ts.mdx', 'angular/my-component-play-function-alt-queries.mdx.mdx', 'vue/my-component-play-function-alt-queries.js.mdx', + 'vue/my-component-play-function-alt-queries.ts.mdx', 'vue/my-component-play-function-alt-queries.mdx.mdx', 'svelte/my-component-play-function-alt-queries.js.mdx', 'svelte/my-component-play-function-alt-queries.mdx.mdx', @@ -197,6 +204,29 @@ If you need, you can also adjust your `play` function to find elements based on πŸ’‘ You can read more about the querying elements in the Testing library documentation.
+When Storybook loads the story, the `play` function starts its execution and queries the DOM tree expecting the element to be available when the story renders. In case there's a failure in your test, you'll be able to verify its root cause quickly. + +Otherwise, if the component is not immediately available, for instance, due to a previous step defined inside your `play` function or some asynchronous behavior, you can adjust your story and wait for the change to the DOM tree to happen before querying the element. For example: + + + + + + + ## Working with the Canvas By default, each interaction you write inside your `play` function will be executed starting from the top-level element of the Canvas. This is acceptable for smaller components (e.g., buttons, checkboxes, text inputs), but can be inefficient for complex components (e.g., forms, pages), or for multiple stories. To accommodate this, you can adjust your interactions to start execution from the component's root. For example: @@ -211,6 +241,7 @@ By default, each interaction you write inside your `play` function will be execu 'angular/my-component-play-function-with-canvas.ts.mdx', 'angular/my-component-play-function-with-canvas.mdx.mdx', 'vue/my-component-play-function-with-canvas.js.mdx', + 'vue/my-component-play-function-with-canvas.ts.mdx', 'vue/my-component-play-function-with-canvas.mdx.mdx', 'svelte/my-component-play-function-with-canvas.js.mdx', 'svelte/my-component-play-function-with-canvas.mdx.mdx', diff --git a/scripts/check-package.js b/scripts/check-package.js index 42fac6081ed7..dc675d9bff1a 100644 --- a/scripts/check-package.js +++ b/scripts/check-package.js @@ -97,8 +97,8 @@ async function run() { selection?.filter(Boolean).forEach(async (v) => { const commmand = (await readJSON(resolve(v.location, 'package.json'))).scripts.check; - const cwd = resolve(__dirname, '..', v.location); - const sub = require('execa').command(`yarn ${commmand}${watchMode ? ' --watch' : ''}`, { + const cwd = resolve(__dirname, '..', 'code', v.location); + const sub = require('execa').command(`${commmand}${watchMode ? ' --watch' : ''}`, { cwd, buffer: false, shell: true, diff --git a/scripts/sandbox.ts b/scripts/sandbox.ts index 36dc21bad97f..07e85b15cd5c 100644 --- a/scripts/sandbox.ts +++ b/scripts/sandbox.ts @@ -14,7 +14,6 @@ import prompts from 'prompts'; import type { AbortController } from 'node-abort-controller'; import command from 'execa'; -import dedent from 'ts-dedent'; import { createOptions, getOptionsOrPrompt, OptionValues } from './utils/options'; import { executeCLIStep } from './utils/cli-step'; import { installYarn2, configureYarn2ForVerdaccio, addPackageResolutions } from './utils/yarn'; @@ -23,6 +22,8 @@ import { getInterpretedFile } from '../code/lib/core-common'; import { ConfigFile, readConfig, writeConfig } from '../code/lib/csf-tools'; import { babelParse } from '../code/lib/csf-tools/src/babelParse'; import TEMPLATES from '../code/lib/cli/src/repro-templates'; +import { detectLanguage } from '../code/lib/cli/src/detect'; +import { SupportedLanguage } from '../code/lib/cli/src/project_types'; import { servePackages } from './utils/serve-packages'; import { filterExistsInCodeDir, codeDir } from './utils/filterExistsInCodeDir'; import { JsPackageManagerFactory } from '../code/lib/cli/src/js-package-manager'; @@ -267,43 +268,51 @@ function addPreviewAnnotations(mainConfig: ConfigFile, paths: string[]) { mainConfig.setFieldValue(['previewAnnotations'], [...(config || []), ...paths]); } -// paths are of the form 'renderers/react', 'addons/actions' -async function addStories( - packageDirs: string[], - { mainConfig, cwd }: { mainConfig: ConfigFile; cwd: string } +// packageDir is eg 'renderers/react', 'addons/actions' +async function linkPackageStories( + packageDir: string, + { mainConfig, cwd, linkInDir }: { mainConfig: ConfigFile; cwd: string; linkInDir?: string } ) { - // Link `stories` directories - // '../../../code/lib/store/template/stories' to 'src/templates/lib/store' + const source = path.join(codeDir, packageDir, 'template', 'stories'); + // By default we link `stories` directories + // e.g '../../../code/lib/store/template/stories' to 'template-stories/lib/store' // if the directory /lib/store/template/stories exists // - // We link rather than reference relative dir to avoid Running two versions - // of React in react-based projects - await Promise.all( - packageDirs.map(async (p) => { - const source = path.join(codeDir, p, 'template', 'stories'); - await ensureSymlink(source, path.resolve(cwd, 'template-stories', p)); - }) - ); + // The files must be linked in the cwd, in order to ensure that any dependencies they + // reference are resolved in the cwd. In particular 'react' resolved by MDX files. + const target = linkInDir + ? path.resolve(linkInDir, packageDir) + : path.resolve(cwd, 'template-stories', packageDir); + await ensureSymlink(source, target); + + // Add `previewAnnotation` entries of the form + // './template-stories/lib/store/preview.ts' + // if the file /lib/store/template/stories/preview.ts exists + const previewFile = path.join(codeDir, packageDir, 'template', 'stories', 'preview.ts'); + if (await pathExists(previewFile)) { + addPreviewAnnotations(mainConfig, [ + `./${path.join('template-stories', packageDir, 'preview.ts')}`, + ]); + } +} + +// Update the stories field to ensure that: +// a) no TS files that are linked from the renderer are picked up in non-TS projects +// b) files in ./template-stories are not matched by the default glob +async function updateStoriesField(mainConfig: ConfigFile, isJs: boolean) { const stories = mainConfig.getFieldValue(['stories']) as string[]; + + // If the project is a JS project, let's make sure any linked in TS stories from the + // renderer inside src|stories are simply ignored. + const updatedStories = isJs + ? stories.map((specifier) => specifier.replace('js|jsx|ts|tsx', 'js|jsx')) + : stories; + // FIXME: '*.@(mdx|stories.mdx|stories.tsx|stories.ts|stories.jsx|stories.js' const linkedStories = path.join('..', 'template-stories', '**', '*.stories.@(js|jsx|ts|tsx|mdx)'); - mainConfig.setFieldValue(['stories'], [...stories, linkedStories]); - // Add `config` entries of the form - // '../../code/lib/store/template/stories/preview.ts' - // if the file /lib/store/template/stories/preview.ts exists - const packageDirsWithPreview = await filterExistsInCodeDir( - packageDirs, - path.join('template', 'stories', 'preview.ts') - ); - - const config = mainConfig.getFieldValue(['config']) as string[]; - const extraConfig = packageDirsWithPreview.map((p) => { - const previewFile = path.join('template-stories', p, 'preview.ts'); - return `./${previewFile}`; - }); - mainConfig.setFieldValue(['config'], [...(config || []), ...extraConfig]); + mainConfig.setFieldValue(['stories'], [...updatedStories, linkedStories]); } type Workspace = { name: string; location: string }; @@ -408,10 +417,19 @@ export async function sandbox(optionValues: OptionValues) { ); addPreviewAnnotations(mainConfig, [`.${path.sep}${path.join(storiesPath, 'components')}`]); - // Link in the stories from the store, the renderer and the addons - const storiesToAdd = [] as string[]; - storiesToAdd.push(workspacePath('core package', '@storybook/store', workspaces)); - storiesToAdd.push(rendererPath); + // Add stories for the renderer. NOTE: these *do* need to be processed by the framework build system + await linkPackageStories(rendererPath, { + mainConfig, + cwd, + linkInDir: path.resolve(cwd, storiesPath), + }); + + // Add stories for lib/store (and addons below). NOTE: these stories will be in the + // template-stories folder and *not* processed by the framework build config (instead by esbuild-loader) + await linkPackageStories(workspacePath('core package', '@storybook/store', workspaces), { + mainConfig, + cwd, + }); // TODO -- sb add doesn't actually work properly: // - installs in `deps` not `devDeps` @@ -423,17 +441,23 @@ export async function sandbox(optionValues: OptionValues) { await executeCLIStep(steps.add, { argument: addonName, cwd, dryRun, debug }); } - for (const addon of [...defaultAddons, ...optionValues.addon]) { - storiesToAdd.push(workspacePath('addon', `@storybook/addon-${addon}`, workspaces)); - } + const addonDirs = [...defaultAddons, ...optionValues.addon].map((addon) => + workspacePath('addon', `@storybook/addon-${addon}`, workspaces) + ); const existingStories = await filterExistsInCodeDir( - storiesToAdd, + addonDirs, path.join('template', 'stories') ); - await addStories(existingStories, { + await Promise.all( + existingStories.map(async (packageDir) => linkPackageStories(packageDir, { mainConfig, cwd })) + ); + + // Ensure that we match stories from the template-stories dir + const packageJson = await import(path.join(cwd, 'package.json')); + await updateStoriesField( mainConfig, - cwd, - }); + detectLanguage(packageJson) === SupportedLanguage.JAVASCRIPT + ); // Add some extra settings (see above for what these do) mainConfig.setFieldValue(['core', 'disableTelemetry'], true); diff --git a/scripts/tasks/chromatic.ts b/scripts/tasks/chromatic.ts index 8e33d9baa23a..f30892fc28f9 100644 --- a/scripts/tasks/chromatic.ts +++ b/scripts/tasks/chromatic.ts @@ -18,7 +18,8 @@ export const chromatic: Task = { --storybook-build-dir=${builtSandboxDir} \ --junit-report=${junitFilename} \ --projectToken=${token}`, - { cwd: sandboxDir } + { cwd: sandboxDir }, + { debug: true } ); } finally { if (fs.existsSync(junitFilename)) {