diff --git a/.circleci/config.yml b/.circleci/config.yml index 849cf28105a5..b384479d14ed 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -457,6 +457,114 @@ jobs: cd code yarn coverage + ## new workflow + create-sandboxes: + executor: + class: medium+ + name: sb_node_14_browsers + parallelism: 2 + steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Creating Sandboxes + command: yarn task --task create --template $(yarn get-template ci) --force --no-before --junit + working_directory: code + - persist_to_workspace: + root: . + paths: + - sandbox + - store_test_results: + path: code/test-results + smoke-test-sandboxes: + executor: + class: medium+ + name: sb_node_14_browsers + parallelism: 2 + steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Smoke Testing Sandboxes + command: yarn task --task smoke-test --template $(yarn get-template ci) --force --no-before --junit + working_directory: code + - store_test_results: + path: code/test-results + build-sandboxes: + executor: + class: medium+ + name: sb_node_14_browsers + parallelism: 2 + steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Building Sandboxes + command: yarn task --task build --template $(yarn get-template ci) --force --no-before --junit + working_directory: code + - store_test_results: + path: code/test-results + - persist_to_workspace: + root: . + paths: + - sandbox + test-runner-sandboxes: + executor: + class: medium+ + name: sb_node_14_browsers + parallelism: 2 + steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Running Test Runner + command: yarn task --task test-runner --template $(yarn get-template ci) --force --no-before --junit + working_directory: code + - store_test_results: + path: code/test-results + chromatic-sandboxes: + executor: + class: medium+ + name: sb_node_14_browsers + parallelism: 2 + steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Running Chromatic + command: yarn task --task chromatic --template $(yarn get-template ci) --force --no-before --junit + working_directory: code + - store_test_results: + path: code/test-results + e2e-sandboxes: + docker: + - image: mcr.microsoft.com/playwright:v1.24.0-focal + parallelism: 2 + steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Running E2E Tests + command: yarn task --task e2e-tests --template $(yarn get-template ci) --force --no-before --junit + working_directory: code + - store_test_results: + path: code/test-results + - store_artifacts: # this is where playwright puts more complex stuff + path: code/playwright-results/ + destination: playwright + workflows: test: jobs: @@ -500,3 +608,23 @@ workflows: - cra-bench: requires: - publish + + ## new workflow + - create-sandboxes: + requires: + - publish + - smoke-test-sandboxes: + requires: + - create-sandboxes + - build-sandboxes: + requires: + - create-sandboxes + - test-runner-sandboxes: + requires: + - build-sandboxes + - chromatic-sandboxes: + requires: + - build-sandboxes + - e2e-sandboxes: + requires: + - build-sandboxes diff --git a/.github/workflows/generate-repros-next.yml b/.github/workflows/generate-repros-next.yml index fcfd6f56ac04..278c7c131def 100644 --- a/.github/workflows/generate-repros-next.yml +++ b/.github/workflows/generate-repros-next.yml @@ -2,7 +2,12 @@ name: Generate and push repros to the next branch on: schedule: - - cron: '2 2 */1 * *' + - cron: "2 2 */1 * *" + workflow_dispatch: + # To remove when the branch will be merged + push: + branches: + - shilman/add-angular-repro-template jobs: generate: @@ -21,7 +26,7 @@ jobs: run: yarn bootstrap --prep working-directory: ./code - name: Generate repros - run: yarn next-repro + run: yarn generate-repros-next working-directory: ./code - name: Publish repros to GitHub run: yarn publish-repros --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/repro-templates-temp.git --push diff --git a/.gitignore b/.gitignore index 540895b90ed1..c58cf821130c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ dist junit.xml /repros /sandbox +/built-sandboxes .verdaccio-cache # Yarn stuff diff --git a/CHANGELOG.md b/CHANGELOG.md index 05cb669cfbed..4089eebcf3af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,75 @@ +## 7.0.0-alpha.23 (August 18, 2022) + +#### Features + +- UI: Polish canvas and sidebar for 7.0 [#18894](https://github.com/storybooks/storybook/pull/18894) + +#### Maintenance + +- Sandbox: Add ability to run from local repro [#18950](https://github.com/storybooks/storybook/pull/18950) +- Repros: Add ability to generate repros using local registry [#18948](https://github.com/storybooks/storybook/pull/18948) +- CLI: Move write/read package json into JsPackageManager [#18942](https://github.com/storybooks/storybook/pull/18942) + + +## 7.0.0-alpha.22 (August 18, 2022) + +Failed publish to npm + +## 7.0.0-alpha.21 (August 17, 2022) + +#### Maintenance + +- UI: Update every icon for v7 design [#18809](https://github.com/storybooks/storybook/pull/18809) + +## 7.0.0-alpha.20 (August 16, 2022) + +#### Features + +- CLI: Automigration for new frameworks [#18919](https://github.com/storybooks/storybook/pull/18919) + +#### Bug Fixes + +- UI: Fix the order of addons appearing in prebuilt manager [#18918](https://github.com/storybooks/storybook/pull/18918) + +#### Maintenance + +- Exit sandbox gracefully on cancel [#18936](https://github.com/storybooks/storybook/pull/18936) +- Disable telemetry in monorepo and CI [#18935](https://github.com/storybooks/storybook/pull/18935) +- Convert cypress e2e tests to playwright [#18932](https://github.com/storybooks/storybook/pull/18932) +- CI: Refactor to use tasks [#18922](https://github.com/storybooks/storybook/pull/18922) +- Angular: Add renderer components / stories [#18934](https://github.com/storybooks/storybook/pull/18934) +- Examples: Add angular repro template and refactor [#18931](https://github.com/storybooks/storybook/pull/18931) + +## 7.0.0-alpha.19 (August 12, 2022) + +#### Features + +- CLI: add "storybook scripts 7.0" automigrate command [#18769](https://github.com/storybooks/storybook/pull/18769) +- Interactions: Run conditionally based on query param [#18706](https://github.com/storybooks/storybook/pull/18706) + +#### Bug Fixes + +- API: Return defaultValue in useParameter if story is not prepared [#18887](https://github.com/storybooks/storybook/pull/18887) +- Store: always call composeConfigs in setProjectAnnotations [#18916](https://github.com/storybooks/storybook/pull/18916) +- CLI: install the same version as the user in sb-scripts automigration [#18917](https://github.com/storybooks/storybook/pull/18917) +- Theming: Add `create` export for lib/theming [#18906](https://github.com/storybooks/storybook/pull/18906) +- Telemetry: Improve addon extraction logic [#18868](https://github.com/storybooks/storybook/pull/18868) +- UI: Add image support to builder-manager [#18857](https://github.com/storybooks/storybook/pull/18857) +- ArgTypes: Fix check for undefined before [#18710](https://github.com/storybooks/storybook/pull/18710) + +#### Maintenance + +- Build: use ts-up to build addon-toolbars [#18847](https://github.com/storybooks/storybook/pull/18847) +- Build: Use ts-up to build channels [#18882](https://github.com/storybooks/storybook/pull/18882) +- Build: Use ts-up to build addon-links [#18908](https://github.com/storybooks/storybook/pull/18908) +- CLI: Fix remove dependencies logic [#18905](https://github.com/storybooks/storybook/pull/18905) +- CLI: Add uninstall deps to jsPackageManager [#18900](https://github.com/storybooks/storybook/pull/18900) +- Examples: Improve sandbox command error handling and debugging [#18869](https://github.com/storybooks/storybook/pull/18869) +- Examples: Change to self-hosted placeholder images [#18878](https://github.com/storybooks/storybook/pull/18878) +- CLI: add --no-init to repro-next command [#18866](https://github.com/storybooks/storybook/pull/18866) +- Build: Got verdaccio working, borrowing heavily from the old repro command [#18844](https://github.com/storybooks/storybook/pull/18844) +- Core-server: Move webpack to be a devDependency [#18856](https://github.com/storybooks/storybook/pull/18856) + ## 7.0.0-alpha.18 (August 2, 2022) #### Features diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ff1cd848c883..81e6f6ceec71 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,10 +7,10 @@ # Generating reproductions -The monorepo has a script that generates Storybook reproductions based on configurations set in the `scripts/next-repro-generators/repro-config.yml` file. This makes it possible to quickly bootstrap examples with and without Storybook, for given configurations (e.g. CRA, Angular, Vue, etc.) +The monorepo has a script that generates Storybook reproductions based on configurations set in the `code/lib/cli/src/repro-templates.ts` file. This makes it possible to quickly bootstrap examples with and without Storybook, for given configurations (e.g. CRA, Angular, Vue, etc.) To do so: -- Check the `scripts/next-repro-generators/repro-config.yml` if you want to see what will be generated +- Check the `code/lib/cli/src/repro-templates.ts` if you want to see what will be generated - Run `./generate-repros.sh` - Check the result in the `repros` directory diff --git a/MIGRATION.md b/MIGRATION.md index 1c8684f7ba2f..1f6e3c9c4409 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -3,6 +3,9 @@ - [From version 6.5.x to 7.0.0](#from-version-65x-to-700) - [Alpha release notes](#alpha-release-notes) - [Breaking changes](#breaking-changes) + - [No more default export from `@storybook/addons`](#no-more-default-export-from-storybookaddons) + - [Modern browser support](#modern-browser-support) + - [No more configuration for manager](#no-more-configuration-for-manager) - [start-storybook / build-storybook binaries removed](#start-storybook--build-storybook-binaries-removed) - [storyStoreV7 enabled by default](#storystorev7-enabled-by-default) - [Webpack4 support discontinued](#webpack4-support-discontinued) @@ -13,7 +16,14 @@ - [Docs modern inline rendering by default](#docs-modern-inline-rendering-by-default) - [Babel mode v7 by default](#babel-mode-v7-by-default) - [7.0 feature flags removed](#70-feature-flags-removed) - - [Removed docs.getContainer and getPage parameters](#removed-docs-getcontainer-and-getpage-parameters) + - [Removed docs.getContainer and getPage parameters](#removed-docsgetcontainer-and-getpage-parameters) + - [Icons API changed](#icons-api-changed) + - [Docs Changes](#docs-changes) + - [Standalone docs files](#standalone-docs-files) + - [Referencing stories in docs files](#referencing-stories-in-docs-files) + - [Docs Page](#docs-page) + - [Configuring the Docs Container](#configuring-the-docs-container) + - [External Docs](#external-docs) - [From version 6.4.x to 6.5.0](#from-version-64x-to-650) - [Vue 3 upgrade](#vue-3-upgrade) - [React18 new root API](#react18-new-root-api) @@ -225,6 +235,70 @@ In the meantime, these migration notes are the best available documentation on t ### Breaking changes +#### No more default export from `@storybook/addons` + +The default export from `@storybook/addons` has been removed. Please use the named exports instead: + +```js +import { addons } from '@storybook/addons'; +``` + +The named export has been available since 6.0 or earlier, so your updated code will be backwards-compatible with older versions of Storybook. + +#### Modern browser support + +Starting in storybook 7.0, storybook will no longer support IE11, amongst other legacy browser versions. +We now transpile our code with a target of `chrome >= 100` and node code is transpiled with a target of `node >= 14`. + +This means code-features such as (but not limited to) `async/await`, arrow-functions, `const`,`let`, etc will exists in the code at runtime, and thus the runtime environment must support it. +Not just the runtime needs to support it, but some legacy loaders for webpack or other transpilation tools might need to be updated as well. For example certain versions of webpack 4 had parsers that could not parse the new syntax (e.g. optional chaining). + +Some addons or libraries might depended on this legacy browser support, and thus might break. You might get an error like: + +``` +regeneratorRuntime is not defined +``` + +To fix these errors, the addon will have to be re-released with a newer browser-target for transpilation. This often looks something like this (but it's dependent on the build system the addon uses): + +```js +// babel.config.js +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + shippedProposals: true, + useBuiltIns: 'usage', + corejs: '3', + modules: false, + targets: { chrome: '100' }, + }, + ], + ], +}; +``` + +Here's an example PR to one of the storybook addons: https://github.com/storybookjs/addon-coverage/pull/3 doing just that. + +#### No more configuration for manager + +The storybook manager is no longer built with webpack. Now it's built with esbuild. +Therefore, it's no longer possible to configure the manager. Esbuild comes preconfigured to handle importing CSS, and images. + +If you're currently loading files other than CSS or images into the manager, you'll need to make changes so the files get converted to JS before publishing your addon. + +This means the preset value `managerWebpack` is no longer respected, and should be removed from presets and `main.js` files. + +Addons that run in the manager can depend on `react` and `@storybook/*` packages directly. They do not need to be peerDependencies. +But very importantly, the build system ensures there will only be 1 version of these packages at runtime. The version will come from the `@storybook/ui` package, and not from the addon. +For this reason it's recommended to have these dependencies as `devDependencies` in your addon's `package.json`. + +The full list of packages that Storybook's manager bundler makes available for addons is here: https://github.com/storybookjs/storybook/blob/next/code/lib/ui/src/globals/types.ts + +Addons in the manager will no longer be bundled together anymore, which means that if 1 fails, it doesn't break the whole manager. +Each addon is imported into the manager as an ESM module that's bundled separately. + #### start-storybook / build-storybook binaries removed SB6.x framework packages shipped binaries called `start-storybook` and `build-storybook`. @@ -398,6 +472,159 @@ In 7.0 we've removed the following feature flags: It is no longer possible to set `parameters.docs.getContainer()` and `getPage()`. Instead use `parameters.docs.container` or `parameters.docs.page` directly. +#### Icons API changed + +For addon authors who use the `Icons` component, its API has been udpated in Storybook 7. + +```diff +export interface IconsProps extends ComponentProps { +- icon?: IconKey; +- symbol?: IconKey; ++ icon: IconType; ++ useSymbol?: boolean; +} +``` + +Full change here: https://github.com/storybookjs/storybook/pull/18809 + +### Docs Changes + +The information hierarchy of docs in Storybook has changed in 7.0. The main difference is that each docs is listed in the sidebar as a separate entry, rather than attached to individual stories. + +These changes are encapsulated in the following: + +#### Standalone docs files + +In Storybook 6.x, to create a standalone docs MDX file, you'd have to create a `.stories.mdx` file, and describe its location with the `Meta` doc block: + +```mdx +import { Meta } from '@storybook/addon-docs'; + + +``` + +In 7.0, things are a little simpler -- you should call the file `.mdx` (drop the `.stories`). This will mean behind the scenes there is no story attached to this entry. You may also drop the `title` and use autotitle (and leave the `Meta` component out entirely). + +Additionally, you can attach a standalone docs entry to a component, using the new `of={}` syntax on the `Meta` component: + +```mdx +import { Meta } from '@storybook/blocks'; +import * as ComponentStories from './some-component.stories'; + + +``` + +You can create as many docs entries as you like for a given component. Note that if you attach a docs entry to a component it will replace the automatically generated entry from `DocsPage` (See below). + +By default docs entries are listed first for the component. You can sort them using story sorting. + +#### Referencing stories in docs files + +To reference a story in a MDX file, you should reference it with `of`: + +```mdx +import { Meta, Story } from '@storybook/blocks'; +import * as ComponentStories from './some-component.stories'; + + + + +``` + +You can also reference a story from a different component: + +```mdx +import { Meta, Story } from '@storybook/blocks'; +import * as ComponentStories from './some-component.stories'; +import * as SecondComponentStories from './second-component.stories'; + + + + +``` + +#### Docs Page + +In 7.0, rather than rendering each story in "docs view mode", Docs Page operates by adding additional sidebar entries for each component. By default it uses the same template as was used in 6.x, and the entries are entitled `Docs`. + +You can configure Docs Page in `main.js`: + +```js +module.exports = { + docs: { + docsPage: true, // set to false to disable docs page entirely + defaultTitle: 'Docs', // set to change the title of generated docs entries + }, +}; +``` + +You can change the default template in the same way as in 6.x, using the `docs.page` parameter. + +#### Configuring the Docs Container + +As in 6.x, you can override the docs container to configure docs further. This the container that each docs entry is rendered inside: + +```js +// in preview.js + +export const parameters = { + docs: { + container: // your container + } +} +``` + +You likely want to use the `DocsContainer` component exported by `@storybook/blocks` and consider the following examples: + +**Overriding theme**: + +To override the theme, you can continue to use the `docs.theme` parameter. + +**Overriding MDX components** + +If you want to override the MDX components supplied to your docs page, use the `MDXProvider` from `@mdx-js/react`: + +```js +import { MDXProvider } from '@mdx-js/react'; +import { DocsContainer } from '@storybook/blocks'; +import * as DesignSystem from 'your-design-system'; + +export const MyDocsContainer = (props) => ( + + + +); +``` + +#### External Docs + +Storybook 7.0 can be used in the above way in externally created projects (i.e. custom docs sites). Your `.mdx` files defined as above should be portable to other contexts. You simply need to render them in an `ExternalDocs` component: + +```js +// In your project somewhere: +import { ExternalDocs } from '@storybook/blocks'; + +// Import all the preview entries from addons that need to operate in your external docs, +// at a minimum likely your project's and your renderer's. +import * as reactAnnotations from '@storybook/react/preview'; +import * as previewAnnotations from '../.storybook/preview'; + +export default function App({ Component, pageProps }) { + return ( + + + + ); +} +``` + ## From version 6.4.x to 6.5.0 ### Vue 3 upgrade @@ -515,7 +742,8 @@ import startCase from 'lodash/startCase'; addons.setConfig({ sidebar: { - renderLabel: ({ name, type }) => (type === 'story' ? name : startCase(name)), + renderLabel: ({ name, type }) => + type === 'story' ? name : startCase(name), }, }); ``` @@ -942,7 +1170,11 @@ After: ```js // .storybook/main.js module.exports = { - staticDirs: ['../public', '../static', { from: '../foo/assets', to: '/assets' }], + staticDirs: [ + '../public', + '../static', + { from: '../foo/assets', to: '/assets' }, + ], }; ``` @@ -1490,13 +1722,17 @@ This breaking change only affects you if your stories actually use the context, Consider the following story that uses the context: ```js -export const Dummy = ({ parameters }) =>
{JSON.stringify(parameters)}
; +export const Dummy = ({ parameters }) => ( +
{JSON.stringify(parameters)}
+); ``` Here's an updated story for 6.0 that ignores the args object: ```js -export const Dummy = (_args, { parameters }) =>
{JSON.stringify(parameters)}
; +export const Dummy = (_args, { parameters }) => ( +
{JSON.stringify(parameters)}
+); ``` Alternatively, if you want to opt out of the new behavior, you can add the following to your `.storybook/preview.js` config: @@ -2286,7 +2522,9 @@ For example, here's how to sort by story ID using `storySort`: addParameters({ options: { storySort: (a, b) => - a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id, undefined, { numeric: true }), + a[1].kind === b[1].kind + ? 0 + : a[1].id.localeCompare(b[1].id, undefined, { numeric: true }), }, }); ``` @@ -2332,7 +2570,9 @@ Storybook 5.1 relies on `core-js@^3.0.0` and therefore causes a conflict with An { "compilerOptions": { "paths": { - "core-js/es7/reflect": ["node_modules/core-js/proposals/reflect-metadata"], + "core-js/es7/reflect": [ + "node_modules/core-js/proposals/reflect-metadata" + ], "core-js/es6/*": ["node_modules/core-js/es"] } } diff --git a/README.md b/README.md index 1ff40b65251e..ffd1395b161d 100644 --- a/README.md +++ b/README.md @@ -93,46 +93,46 @@ For additional help, join us in the [Storybook Discord](https://discord.gg/story ### Supported Frameworks -| Framework | Demo | | -| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| [React](app/react) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/react/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/official-storybook/?path=/story/*) | [![React](https://img.shields.io/npm/dm/@storybook/react?style=flat-square&color=eee)](app/react) | -| [Vue](app/vue) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/vue/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/vue-kitchen-sink/) | [![Vue](https://img.shields.io/npm/dm/@storybook/vue?style=flat-square&color=eee)](app/vue) | -| [Angular](app/angular) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/angular/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/angular-cli/) | [![Angular](https://img.shields.io/npm/dm/@storybook/angular?style=flat-square&color=eee)](app/angular) | -| [Web components](app/web-components) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/web-components/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/web-components-kitchen-sink/) | [![Svelte](https://img.shields.io/npm/dm/@storybook/web-components?style=flat-square&color=eee)](app/web-components) | +| Renderer | Demo | | +|----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| [React](code/renderers/react) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/react/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/official-storybook/?path=/story/*) | [![React](https://img.shields.io/npm/dm/@storybook/react?style=flat-square&color=eee)](code/renderers/react) | +| [Vue](code/renderers/vue) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/vue/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/vue-kitchen-sink/) | [![Vue](https://img.shields.io/npm/dm/@storybook/vue?style=flat-square&color=eee)](code/renderers/vue) | +| [Angular](code/frameworks/angular/) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/angular/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/angular-cli/) | [![Angular](https://img.shields.io/npm/dm/@storybook/angular?style=flat-square&color=eee)](code/frameworks/angular/) | +| [Web components](code/renderers/web-components) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/web-components/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/web-components-kitchen-sink/) | [![Svelte](https://img.shields.io/npm/dm/@storybook/web-components?style=flat-square&color=eee)](code/renderers/web-components) | | [React Native](https://github.com/storybookjs/react-native) | - | [![React Native](https://img.shields.io/npm/dm/@storybook/react-native?style=flat-square&color=eee)](https://github.com/storybookjs/react-native) | -| [HTML](app/html) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/html/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/html-kitchen-sink/) | [![HTML](https://img.shields.io/npm/dm/@storybook/html?style=flat-square&color=eee)](app/html) | -| [Ember](app/ember) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/ember/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/ember-cli/) | [![Ember](https://img.shields.io/npm/dm/@storybook/ember?style=flat-square&color=eee)](app/ember) | -| [Svelte](app/svelte) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/svelte/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/svelte-kitchen-sink/) | [![Svelte](https://img.shields.io/npm/dm/@storybook/svelte?style=flat-square&color=eee)](app/svelte) | -| [Preact](app/preact) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/preact/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/preact-kitchen-sink/) | [![Preact](https://img.shields.io/npm/dm/@storybook/preact?style=flat-square&color=eee)](app/preact) | +| [HTML](code/renderers/html) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/html/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/html-kitchen-sink/) | [![HTML](https://img.shields.io/npm/dm/@storybook/html?style=flat-square&color=eee)](code/renderers/html) | +| [Ember](code/frameworks/ember/) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/ember/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/ember-cli/) | [![Ember](https://img.shields.io/npm/dm/@storybook/ember?style=flat-square&color=eee)](code/frameworks/ember/) | +| [Svelte](code/renderers/svelte) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/svelte/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/svelte-kitchen-sink/) | [![Svelte](https://img.shields.io/npm/dm/@storybook/svelte?style=flat-square&color=eee)](code/renderers/svelte) | +| [Preact](code/renderers/preact) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/preact/latest?style=flat-square&color=blue&label)](https://storybookjs.netlify.com/preact-kitchen-sink/) | [![Preact](https://img.shields.io/npm/dm/@storybook/preact?style=flat-square&color=eee)](code/renderers/preact) | | [Marionette.js](https://github.com/storybookjs/marionette) | - | [![Marionette.js](https://img.shields.io/npm/dm/@storybook/marionette?style=flat-square&color=eee)](https://github.com/storybookjs/marionette) | | [Android, iOS, Flutter](https://github.com/storybookjs/native) | [![Storybook demo](https://img.shields.io/npm/v/@storybook/native/latest?style=flat-square&color=blue&label)](https://storybookjs.github.io/native/@storybook/native-flutter-example/index.html) | [![Native](https://img.shields.io/npm/dm/@storybook/native?style=flat-square&color=eee)](https://github.com/storybookjs/native) | ### Sub Projects -- [CLI](lib/cli) - Streamlined installation for a variety of app types -- [examples](examples) - Code examples to illustrate different Storybook use cases +- [CLI](code/lib/cli) - Streamlined installation for a variety of app types +- [examples](code/examples) - Code examples to illustrate different Storybook use cases ### Addons | Addons | | | ------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -| [a11y](addons/a11y/) | Test components for user accessibility in Storybook | -| [actions](addons/actions/) | Log actions as users interact with components in the Storybook UI | -| [backgrounds](addons/backgrounds/) | Let users choose backgrounds in the Storybook UI | +| [a11y](code/addons/a11y/) | Test components for user accessibility in Storybook | +| [actions](code/addons/actions/) | Log actions as users interact with components in the Storybook UI | +| [backgrounds](code/addons/backgrounds/) | Let users choose backgrounds in the Storybook UI | | [cssresources](https://github.com/storybookjs/addon-cssresources) | Dynamically add/remove css resources to the component iframe | | [design assets](https://github.com/storybookjs/addon-design-assets) | View images, videos, weblinks alongside your story | -| [docs](addons/docs/) | Add high quality documentation to your components | +| [docs](code/addons/docs/) | Add high quality documentation to your components | | [events](https://github.com/storybookjs/addon-events) | Interactively fire events to components that respond to EventEmitter | | [google-analytics](https://github.com/storybookjs/addon-google-analytics) | Reports google analytics on stories | | [graphql](https://github.com/storybookjs/addon-graphql) | Query a GraphQL server within Storybook stories | -| [jest](addons/jest/) | View the results of components' unit tests in Storybook | -| [links](addons/links/) | Create links between stories | +| [jest](code/addons/jest/) | View the results of components' unit tests in Storybook | +| [links](code/addons/links/) | Create links between stories | | [query params](https://github.com/storybookjs/addon-queryparams) | Mock query params | -| [storyshots](addons/storyshots/) | Snapshot testing for components in Storybook | -| [storysource](addons/storysource/) | View the code of your stories within the Storybook UI | -| [viewport](addons/viewport/) | Change display sizes and layouts for responsive components using Storybook | -| [outline](addons/outline/) | Visuallly debug the CSS layout and alignment within the Storybook UI | -| [measure](addons/measure/) | Visually inspect the layout and box model within the Storybook UI | +| [storyshots](code/addons/storyshots/) | Snapshot testing for components in Storybook | +| [storysource](code/addons/storysource/) | View the code of your stories within the Storybook UI | +| [viewport](code/addons/viewport/) | Change display sizes and layouts for responsive components using Storybook | +| [outline](code/addons/outline/) | Visuallly debug the CSS layout and alignment within the Storybook UI | +| [measure](code/addons/measure/) | Visually inspect the layout and box model within the Storybook UI | See [Addon / Framework Support Table](https://storybook.js.org/docs/react/api/frameworks-feature-support) @@ -148,9 +148,9 @@ See [Addon / Framework Support Table](https://storybook.js.org/docs/react/api/fr In order to continue improving your experience, we have to eventually deprecate certain addons in favor of new, better tools. -If you're using info/notes, we highly recommend you to migrate to [docs](addons/docs/) instead, and [here is a guide](addons/docs/docs/recipes.md#migrating-from-notesinfo-addons) to help you. +If you're using info/notes, we highly recommend you to migrate to [docs](code/addons/docs/) instead, and [here is a guide](code/addons/docs/docs/recipes.md#migrating-from-notesinfo-addons) to help you. -If you're using contexts, we highly recommend you to migrate to [toolbars](https://github.com/storybookjs/storybook/tree/next/addons/toolbars) and [here is a guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-addon-contexts) to help you. +If you're using contexts, we highly recommend you to migrate to [toolbars](https://github.com/storybookjs/storybook/tree/next/code/addons/toolbars) and [here is a guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-addon-contexts) to help you. ## Badges & Presentation materials diff --git a/code/.eslintrc.js b/code/.eslintrc.js index 80316f0a5e7d..1129908e7eb0 100644 --- a/code/.eslintrc.js +++ b/code/.eslintrc.js @@ -95,5 +95,11 @@ module.exports = { 'react/no-unknown-property': 'off', // Need to deactivate otherwise eslint replaces some unknown properties with React ones }, }, + { + files: ['**/e2e-tests/**/*'], + rules: { + 'jest/no-test-callback': 'off', // These aren't jest tests + }, + }, ], }; diff --git a/code/.gitignore b/code/.gitignore index 193ada9a92e3..8e7366b01633 100644 --- a/code/.gitignore +++ b/code/.gitignore @@ -36,6 +36,12 @@ examples/angular-cli/addon-jest.testresults.json junit.xml .next +/test-results/ +/playwright-results/ +/playwright-report/ +/playwright/.cache/ + + # Yarn stuff /**/.yarn/* !/**/.yarn/releases diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index 778afeb98f73..a2c3e076e0bc 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", @@ -62,15 +62,15 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/api": "7.0.0-alpha.18", - "@storybook/channels": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/channels": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", "@storybook/csf": "0.0.2--canary.0899bb7.0", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/theming": "7.0.0-alpha.23", "axe-core": "^4.2.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -105,7 +105,7 @@ "./src/preview.tsx" ] }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53", + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a", "storybook": { "displayName": "Accessibility", "icon": "https://user-images.githubusercontent.com/263385/101991665-47042f80-3c7c-11eb-8f00-64b5a18f498a.png", diff --git a/code/addons/a11y/src/components/Report/Item.tsx b/code/addons/a11y/src/components/Report/Item.tsx index 3861e9465409..48ae0ec3ded4 100644 --- a/code/addons/a11y/src/components/Report/Item.tsx +++ b/code/addons/a11y/src/components/Report/Item.tsx @@ -75,7 +75,7 @@ export const Item = (props: ItemProps) => { onToggle(!open)} role="button"> -); - -Demo.play = async ({ args, canvasElement }) => { - await userEvent.click(within(canvasElement).getByRole('button')); - await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi)); - await expect([{ name: 'John', age: 42 }]).toEqual( - expect.arrayContaining([ - expect.objectContaining({ name: 'John' }), - expect.objectContaining({ age: 42 }), - ]) - ); -}; - -export const Exception = Demo.bind({}); -Exception.play = () => Demo.play(undefined as any); // deepscan-disable-line -Exception.parameters = { chromatic: { disableSnapshot: true } }; - -export const FindBy: CSF2Story = (args) => { - const [isLoading, setIsLoading] = React.useState(true); - React.useEffect(() => { - setTimeout(() => setIsLoading(false), 500); - }, []); - return isLoading ?
Loading...
: ; -}; -FindBy.play = async ({ canvasElement }) => { - const canvas = within(canvasElement); - await canvas.findByRole('button'); - await expect(true).toBe(true); -}; - -export const WaitFor: CSF2Story = (args) => ( - -); -WaitFor.play = async ({ args, canvasElement }) => { - await userEvent.click(await within(canvasElement).findByText('Click')); - await waitFor(async () => { - await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi)); - await expect(true).toBe(true); - }); -}; - -export const WaitForElementToBeRemoved: CSF2Story = () => { - const [isLoading, setIsLoading] = React.useState(true); - React.useEffect(() => { - setTimeout(() => setIsLoading(false), 1500); - }, []); - return isLoading ?
Loading...
: ; -}; -WaitForElementToBeRemoved.play = async ({ canvasElement }) => { - const canvas = within(canvasElement); - await waitForElementToBeRemoved(await canvas.findByText('Loading...'), { timeout: 2000 }); - const button = await canvas.findByText('Loaded!'); - await expect(button).toBeInTheDocument(); -}; - -export const WithLoaders: CSF2Story = (args, { loaded: { todo } }) => { - return ( - - ); -}; -WithLoaders.loaders = [ - async () => { - // long fake timeout - await new Promise((resolve) => setTimeout(resolve, 2000)); - - return { - todo: { - userId: 1, - id: 1, - title: 'delectus aut autem', - completed: false, - }, - }; - }, -]; -WithLoaders.play = async ({ args, canvasElement }) => { - const canvas = within(canvasElement); - const todoItem = await canvas.findByText('Todo: delectus aut autem'); - await userEvent.click(todoItem); - await expect(args.onSubmit).toHaveBeenCalledWith('delectus aut autem'); -}; - -export const Standard: CSF3Story = { - args: { passwordVerification: false }, -}; - -export const StandardEmailFilled: CSF3Story = { - ...Standard, - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - await fireEvent.change(canvas.getByTestId('email'), { - target: { - value: 'michael@chromatic.com', - }, - }); - }, -}; - -export const StandardEmailFailed: CSF3Story = { - ...Standard, - play: async ({ args, canvasElement }) => { - const canvas = within(canvasElement); - await userEvent.type(canvas.getByTestId('email'), 'gert@chromatic'); - await userEvent.type(canvas.getByTestId('password1'), 'supersecret'); - await userEvent.click(canvas.getByRole('button', { name: /create account/i })); - - await canvas.findByText('Please enter a correctly formatted email address'); - await expect(args.onSubmit).not.toHaveBeenCalled(); - }, -}; - -export const StandardEmailSuccess: CSF3Story = { - ...Standard, - play: async ({ args, canvasElement }) => { - const canvas = within(canvasElement); - await userEvent.type(canvas.getByTestId('email'), 'michael@chromatic.com'); - await userEvent.type(canvas.getByTestId('password1'), 'testpasswordthatwontfail'); - await userEvent.click(canvas.getByTestId('submit')); - - await waitFor(async () => { - await expect(args.onSubmit).toHaveBeenCalledTimes(1); - await expect(args.onSubmit).toHaveBeenCalledWith({ - email: 'michael@chromatic.com', - password: 'testpasswordthatwontfail', - }); - }); - }, -}; - -export const StandardPasswordFailed: CSF3Story = { - ...Standard, - play: async (context) => { - const canvas = within(context.canvasElement); - await StandardEmailFilled.play(context); - await userEvent.type(canvas.getByTestId('password1'), 'asdf'); - await userEvent.click(canvas.getByTestId('submit')); - }, -}; - -export const StandardFailHover: CSF3Story = { - ...StandardPasswordFailed, - play: async (context) => { - const canvas = within(context.canvasElement); - await StandardPasswordFailed.play(context); - await waitFor(async () => { - await userEvent.hover(canvas.getByTestId('password-error-info')); - }); - }, -}; - -export const Verification: CSF3Story = { - args: { passwordVerification: true }, - argTypes: { onSubmit: { action: 'clicked' } }, -}; - -export const VerificationPassword: CSF3Story = { - ...Verification, - play: async (context) => { - const canvas = within(context.canvasElement); - await StandardEmailFilled.play(context); - await userEvent.type(canvas.getByTestId('password1'), 'asdfasdf'); - await userEvent.click(canvas.getByTestId('submit')); - }, -}; - -export const VerificationPasswordMismatch: CSF3Story = { - ...Verification, - play: async (context) => { - const canvas = within(context.canvasElement); - await StandardEmailFilled.play(context); - await userEvent.type(canvas.getByTestId('password1'), 'asdfasdf'); - await userEvent.type(canvas.getByTestId('password2'), 'asdf1234'); - await userEvent.click(canvas.getByTestId('submit')); - }, -}; - -export const VerificationSuccess: CSF3Story = { - ...Verification, - play: async (context) => { - const canvas = within(context.canvasElement); - await StandardEmailFilled.play(context); - await new Promise((resolve) => setTimeout(resolve, 1000)); - await userEvent.type(canvas.getByTestId('password1'), 'helloyou', { delay: 50 }); - await new Promise((resolve) => setTimeout(resolve, 1000)); - await userEvent.type(canvas.getByTestId('password2'), 'helloyou', { delay: 50 }); - await new Promise((resolve) => setTimeout(resolve, 1000)); - await userEvent.click(canvas.getByTestId('submit')); - }, -}; diff --git a/code/addons/interactions/src/components/Interaction.stories.tsx b/code/addons/interactions/src/components/Interaction.stories.tsx index 06aaaba5f5b4..c1b38cafd63e 100644 --- a/code/addons/interactions/src/components/Interaction.stories.tsx +++ b/code/addons/interactions/src/components/Interaction.stories.tsx @@ -45,7 +45,7 @@ export const Done: Story = { export const WithParent: Story = { args: { - call: { ...getCalls(CallStates.DONE).slice(-1)[0], parentId: 'parent-id' }, + call: { ...getCalls(CallStates.DONE).slice(-1)[0], ancestors: ['parent-id'] }, }, }; diff --git a/code/addons/interactions/src/components/Interaction.tsx b/code/addons/interactions/src/components/Interaction.tsx index 92a60d4fa998..a982ad3d6fc3 100644 --- a/code/addons/interactions/src/components/Interaction.tsx +++ b/code/addons/interactions/src/components/Interaction.tsx @@ -32,7 +32,7 @@ const RowContainer = styled('div', { ? transparentize(0.93, theme.color.negative) : theme.background.warning, }), - paddingLeft: call.parentId ? 20 : 0, + paddingLeft: call.ancestors.length * 20, }), ({ theme, call, pausedAt }) => pausedAt === call.id && { @@ -56,9 +56,9 @@ const RowContainer = styled('div', { } ); -const RowHeader = styled.div<{ disabled: boolean }>(({ theme, disabled }) => ({ +const RowHeader = styled.div<{ isInteractive: boolean }>(({ theme, isInteractive }) => ({ display: 'flex', - '&:hover': disabled ? {} : { background: theme.background.hoverable }, + '&:hover': isInteractive ? {} : { background: theme.background.hoverable }, })); const RowLabel = styled('button', { @@ -130,6 +130,7 @@ export const Interaction = ({ controls, controlStates, childCallIds, + isHidden, isCollapsed, toggleCollapsed, pausedAt, @@ -139,18 +140,23 @@ export const Interaction = ({ controls: Controls; controlStates: ControlStates; childCallIds?: Call['id'][]; + isHidden: boolean; isCollapsed: boolean; toggleCollapsed: () => void; pausedAt?: Call['id']; }) => { const [isHovered, setIsHovered] = React.useState(false); + const isInteractive = !controlStates.goto || !call.interceptable || !!call.ancestors.length; + + if (isHidden) return null; + return ( - + controls.goto(call.id)} - disabled={!controlStates.goto || !call.interceptable || !!call.parentId} + disabled={isInteractive} onMouseEnter={() => controlStates.goto && setIsHovered(true)} onMouseLeave={() => controlStates.goto && setIsHovered(false)} > @@ -163,11 +169,7 @@ export const Interaction = ({ {childCallIds?.length > 0 && ( - } + tooltip={} > diff --git a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx index 606f2cf22bf3..3c618898578e 100644 --- a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx +++ b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx @@ -122,7 +122,7 @@ export const Failed: Story = { }, }; -export const WithDebuggingDisabled: Story = { +export const NoDebugger: Story = { args: { controlStates: { ...SubnavStories.args.controlStates, debugger: false } }, }; diff --git a/code/addons/interactions/src/components/InteractionsPanel.tsx b/code/addons/interactions/src/components/InteractionsPanel.tsx index dee82be36ef4..71f8b83d882d 100644 --- a/code/addons/interactions/src/components/InteractionsPanel.tsx +++ b/code/addons/interactions/src/components/InteractionsPanel.tsx @@ -23,6 +23,7 @@ interface InteractionsPanelProps { interactions: (Call & { status?: CallStates; childCallIds: Call['id'][]; + isHidden: boolean; isCollapsed: boolean; toggleCollapsed: () => void; })[]; @@ -118,6 +119,7 @@ export const InteractionsPanel: React.FC = React.memo( controls={controls} controlStates={controlStates} childCallIds={call.childCallIds} + isHidden={call.isHidden} isCollapsed={call.isCollapsed} toggleCollapsed={call.toggleCollapsed} pausedAt={pausedAt} diff --git a/code/addons/interactions/src/components/List.tsx b/code/addons/interactions/src/components/List.tsx index d2b365fdeb93..af6005e13a86 100644 --- a/code/addons/interactions/src/components/List.tsx +++ b/code/addons/interactions/src/components/List.tsx @@ -68,7 +68,7 @@ export const ListItem: React.FC = ({ item }) => { onToggle(!open)} role="button"> ( /> + @@ -99,6 +100,7 @@ const calls: Call[] = [ { cursor: 0, id: '1', + ancestors: [], path: ['screen'], method: 'getByText', storyId: 'kind--story', @@ -109,6 +111,7 @@ const calls: Call[] = [ { cursor: 1, id: '2', + ancestors: [], path: ['userEvent'], method: 'click', storyId: 'kind--story', @@ -119,6 +122,7 @@ const calls: Call[] = [ { cursor: 2, id: '3', + ancestors: [], path: [], method: 'expect', storyId: 'kind--story', @@ -129,6 +133,7 @@ const calls: Call[] = [ { cursor: 3, id: '4', + ancestors: [], path: [{ __callId__: '3' }, 'not'], method: 'toBe', storyId: 'kind--story', @@ -139,6 +144,7 @@ const calls: Call[] = [ { cursor: 4, id: '5', + ancestors: [], path: ['jest'], method: 'fn', storyId: 'kind--story', @@ -149,6 +155,7 @@ const calls: Call[] = [ { cursor: 5, id: '6', + ancestors: [], path: [], method: 'expect', storyId: 'kind--story', @@ -159,6 +166,7 @@ const calls: Call[] = [ { cursor: 6, id: '7', + ancestors: [], path: ['expect'], method: 'stringMatching', storyId: 'kind--story', @@ -169,6 +177,7 @@ const calls: Call[] = [ { cursor: 7, id: '8', + ancestors: [], path: [{ __callId__: '6' }, 'not'], method: 'toHaveBeenCalledWith', storyId: 'kind--story', @@ -182,6 +191,17 @@ const calls: Call[] = [ interceptable: false, retain: false, }, + { + cursor: 8, + id: '9', + ancestors: [], + path: [], + method: 'step', + storyId: 'kind--story', + args: ['Custom step label', { __function__: { name: '' } }], + interceptable: true, + retain: false, + }, ]; const callsById = calls.reduce((acc, call) => { @@ -189,6 +209,7 @@ const callsById = calls.reduce((acc, call) => { return acc; }, new Map()); +export const Step = () => ; export const Simple = () => ; export const Nested = () => ; export const Chained = () => ; diff --git a/code/addons/interactions/src/components/MethodCall.tsx b/code/addons/interactions/src/components/MethodCall.tsx index e9a98602e783..c5e62c0caf69 100644 --- a/code/addons/interactions/src/components/MethodCall.tsx +++ b/code/addons/interactions/src/components/MethodCall.tsx @@ -383,6 +383,22 @@ export const OtherNode = ({ value }: { value: any }) => { return {stringify(value)}; }; +export const StepNode = ({ label }: { label: string }) => { + const colors = useThemeColors(); + const { typography } = useTheme(); + return ( + + {label} + + ); +}; + export const MethodCall = ({ call, callsById, @@ -393,7 +409,9 @@ export const MethodCall = ({ // Call might be undefined during initial render, can be safely ignored. if (!call) return null; - const colors = useThemeColors(); + if (call.method === 'step' && call.path.length === 0) { + return ; + } const path = call.path.flatMap((elem, index) => { // eslint-disable-next-line no-underscore-dangle @@ -416,6 +434,7 @@ export const MethodCall = ({ : [node]; }); + const colors = useThemeColors(); return ( <> {path} diff --git a/code/addons/interactions/src/components/StatusIcon.tsx b/code/addons/interactions/src/components/StatusIcon.tsx index 6a3f6d629f14..b223a3960521 100644 --- a/code/addons/interactions/src/components/StatusIcon.tsx +++ b/code/addons/interactions/src/components/StatusIcon.tsx @@ -6,8 +6,10 @@ import { styled } from '@storybook/theming'; import { transparentize } from 'polished'; import localTheme from '../theme'; -export interface StatusIconProps extends IconsProps { +export interface StatusIconProps { status: Call['status']; + useSymbol?: IconsProps['useSymbol']; + className?: string; } const { diff --git a/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.stories.mdx b/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.stories.mdx new file mode 100644 index 000000000000..4c97235008e3 --- /dev/null +++ b/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.stories.mdx @@ -0,0 +1,31 @@ +import { Meta, Canvas, Story } from '@storybook/addon-docs'; +import { expect } from '@storybook/jest'; +import { within, waitFor, fireEvent, userEvent, screen } from '@storybook/testing-library'; + +import { AccountForm } from './AccountFormInteractions'; + + + +## AccountForm + + + { + await userEvent.type(screen.getByTestId('email'), 'username@email.com'); + await userEvent.type(screen.getByTestId('password1'), 'thepassword'); + await userEvent.click(screen.getByRole('button', { name: /create account/i })); + await expect(args.onSubmit).not.toHaveBeenCalled(); + }} + /> + diff --git a/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.stories.tsx b/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.stories.tsx new file mode 100644 index 000000000000..34f84115113c --- /dev/null +++ b/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.stories.tsx @@ -0,0 +1,162 @@ +/* eslint-disable jest/no-standalone-expect */ +import { Meta, ComponentStoryObj } from '@storybook/react'; +import { expect } from '@storybook/jest'; +import { within, waitFor, fireEvent, userEvent } from '@storybook/testing-library'; + +import { AccountForm } from './AccountFormInteractions'; + +export default { + title: 'Addons/Interactions/Examples/AccountForm', + component: AccountForm, + parameters: { + layout: 'centered', + theme: 'light', + options: { selectedPanel: 'storybook/interactions/panel' }, + }, + argTypes: { + onSubmit: { action: true }, + }, +} as Meta; + +type CSF3Story = ComponentStoryObj; + +export const Standard: CSF3Story = { + args: { passwordVerification: false }, +}; + +export const StandardEmailFilled = { + ...Standard, + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + + await step('Enter email', async () => { + await fireEvent.change(canvas.getByTestId('email'), { + target: { value: 'michael@chromatic.com' }, + }); + }); + }, +}; + +export const StandardEmailFailed = { + ...Standard, + play: async ({ args, canvasElement, step }) => { + const canvas = within(canvasElement); + + await step('Enter email and password', async () => { + await userEvent.type(canvas.getByTestId('email'), 'gert@chromatic'); + await userEvent.type(canvas.getByTestId('password1'), 'supersecret'); + }); + + await step('Submit form', async () => { + await userEvent.click(canvas.getByRole('button', { name: /create account/i })); + }); + + await canvas.findByText('Please enter a correctly formatted email address'); + await expect(args.onSubmit).not.toHaveBeenCalled(); + }, +}; + +export const StandardEmailSuccess = { + ...Standard, + play: async ({ args, canvasElement, step }) => { + const canvas = within(canvasElement); + + await step('Enter email and password', async () => { + await userEvent.type(canvas.getByTestId('email'), 'michael@chromatic.com'); + await userEvent.type(canvas.getByTestId('password1'), 'testpasswordthatwontfail'); + }); + + await step('Submit form', async () => { + await userEvent.click(canvas.getByTestId('submit')); + }); + + await waitFor(async () => { + await expect(args.onSubmit).toHaveBeenCalledTimes(1); + await expect(args.onSubmit).toHaveBeenCalledWith({ + email: 'michael@chromatic.com', + password: 'testpasswordthatwontfail', + }); + }); + }, +}; + +export const StandardPasswordFailed = { + ...Standard, + play: async (context) => { + const canvas = within(context.canvasElement); + await StandardEmailFilled.play(context); + + await context.step('Enter password', async () => { + await userEvent.type(canvas.getByTestId('password1'), 'asdf'); + }); + + await context.step('Submit form', async () => { + await userEvent.click(canvas.getByTestId('submit')); + }); + }, +}; + +export const StandardFailHover = { + ...StandardPasswordFailed, + play: async (context) => { + const canvas = within(context.canvasElement); + await StandardPasswordFailed.play(context); + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('password-error-info')); + }); + }, +}; + +export const Verification = { + args: { passwordVerification: true }, + argTypes: { onSubmit: { action: 'clicked' } }, +}; + +export const VerificationPassword = { + ...Verification, + play: async (context) => { + const canvas = within(context.canvasElement); + await StandardEmailFilled.play(context); + await context.step('Enter password', async () => { + await userEvent.type(canvas.getByTestId('password1'), 'asdfasdf'); + }); + await context.step('Submit form', async () => { + await userEvent.click(canvas.getByTestId('submit')); + }); + }, +}; + +export const VerificationPasswordMismatch = { + ...Verification, + play: async (context) => { + const canvas = within(context.canvasElement); + await StandardEmailFilled.play(context); + await context.step('Enter passwords', async () => { + await userEvent.type(canvas.getByTestId('password1'), 'asdfasdf'); + await userEvent.type(canvas.getByTestId('password2'), 'asdf1234'); + }); + await context.step('Submit form', async () => { + await userEvent.click(canvas.getByTestId('submit')); + }); + }, +}; + +export const VerificationSuccess = { + ...Verification, + play: async (context) => { + const canvas = within(context.canvasElement); + await StandardEmailFilled.play(context); + + await context.step('Enter passwords', async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + await userEvent.type(canvas.getByTestId('password1'), 'helloyou', { delay: 50 }); + await new Promise((resolve) => setTimeout(resolve, 1000)); + await userEvent.type(canvas.getByTestId('password2'), 'helloyou', { delay: 50 }); + }); + + await context.step('Submit form', async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + await userEvent.click(canvas.getByTestId('submit')); + }); + }, +}; diff --git a/code/addons/interactions/src/components/AccountForm/AccountForm.tsx b/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.tsx similarity index 99% rename from code/addons/interactions/src/components/AccountForm/AccountForm.tsx rename to code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.tsx index 683f711178e7..1e40d5bacb82 100644 --- a/code/addons/interactions/src/components/AccountForm/AccountForm.tsx +++ b/code/addons/interactions/src/examples/AccountFormInteractions/AccountFormInteractions.tsx @@ -490,7 +490,7 @@ const ErrorIcon = styled(Icons)(({ theme }) => ({ opacity: 0.8, marginRight: 6, marginLeft: 2, - marginTop: 1, + marginTop: 4, })); const ErrorTooltip = styled.div(({ theme }) => ({ diff --git a/code/addons/interactions/src/examples/Examples.stories.tsx b/code/addons/interactions/src/examples/Examples.stories.tsx new file mode 100644 index 000000000000..d16c086e61ee --- /dev/null +++ b/code/addons/interactions/src/examples/Examples.stories.tsx @@ -0,0 +1,126 @@ +/* eslint-disable jest/no-standalone-expect */ +import { Story, Meta } from '@storybook/react'; +import { expect } from '@storybook/jest'; +import { within, waitFor, userEvent, waitForElementToBeRemoved } from '@storybook/testing-library'; +import React from 'react'; + +export default { + title: 'Addons/Interactions/Examples', + parameters: { + layout: 'centered', + theme: 'light', + options: { selectedPanel: 'storybook/interactions/panel' }, + }, + argTypes: { + onSubmit: { action: true }, + }, +} as Meta; + +export const Assertions: Story = ({ onSubmit }) => ( + +); +Assertions.play = async ({ args, canvasElement }) => { + await userEvent.click(within(canvasElement).getByRole('button')); + await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi)); + await expect([{ name: 'John', age: 42 }]).toEqual( + expect.arrayContaining([ + expect.objectContaining({ name: 'John' }), + expect.objectContaining({ age: 42 }), + ]) + ); +}; + +export const FindBy: Story = () => { + const [isLoading, setIsLoading] = React.useState(true); + React.useEffect(() => { + setTimeout(() => setIsLoading(false), 500); + }, []); + return isLoading ?
Loading...
: ; +}; +FindBy.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + await canvas.findByRole('button'); + await expect(true).toBe(true); +}; + +export const WaitFor: Story = ({ onSubmit }) => ( + +); +WaitFor.play = async ({ args, canvasElement }) => { + await userEvent.click(await within(canvasElement).findByText('Click')); + await waitFor(async () => { + await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi)); + await expect(true).toBe(true); + }); +}; + +export const WaitForElementToBeRemoved: Story = () => { + const [isLoading, setIsLoading] = React.useState(true); + React.useEffect(() => { + setTimeout(() => setIsLoading(false), 1500); + }, []); + return isLoading ?
Loading...
: ; +}; +WaitForElementToBeRemoved.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + await waitForElementToBeRemoved(await canvas.findByText('Loading...'), { timeout: 2000 }); + const button = await canvas.findByText('Loaded!'); + await expect(button).not.toBeNull(); +}; + +export const WithLoaders: Story = ({ onSubmit }, { loaded: { todo } }) => { + return ( + + ); +}; +WithLoaders.loaders = [ + async () => { + // long fake timeout + await new Promise((resolve) => setTimeout(resolve, 2000)); + + return { + todo: { + userId: 1, + id: 1, + title: 'delectus aut autem', + completed: false, + }, + }; + }, +]; +WithLoaders.play = async ({ args, canvasElement }) => { + const canvas = within(canvasElement); + const todoItem = await canvas.findByText('Todo: delectus aut autem'); + await userEvent.click(todoItem); + await expect(args.onSubmit).toHaveBeenCalledWith('delectus aut autem'); +}; + +export const WithSteps: Story = ({ onSubmit }) => ( + +); +WithSteps.play = async ({ args, canvasElement, step }) => { + await step('Click button', async () => { + await userEvent.click(within(canvasElement).getByRole('button')); + + await step('Verify submit', async () => { + await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi)); + }); + + await step('Verify result', async () => { + await expect([{ name: 'John', age: 42 }]).toEqual( + expect.arrayContaining([ + expect.objectContaining({ name: 'John' }), + expect.objectContaining({ age: 42 }), + ]) + ); + }); + }); +}; diff --git a/code/addons/interactions/src/mocks/index.ts b/code/addons/interactions/src/mocks/index.ts index d42507545332..14066c7a0149 100644 --- a/code/addons/interactions/src/mocks/index.ts +++ b/code/addons/interactions/src/mocks/index.ts @@ -3,9 +3,22 @@ import { CallStates, Call } from '@storybook/instrumenter'; export const getCalls = (finalStatus: CallStates) => { const calls: Call[] = [ { - id: 'story--id [3] within', + id: 'story--id [3] step', + storyId: 'story--id', + cursor: 1, + ancestors: [], + path: [], + method: 'step', + args: ['Click button', { __function__: { name: '' } }], + interceptable: true, + retain: false, + status: CallStates.DONE, + }, + { + id: 'story--id [3] step [1] within', storyId: 'story--id', cursor: 3, + ancestors: ['story--id [3] step'], path: [], method: 'within', args: [{ __element__: { localName: 'div', id: 'root' } }], @@ -14,10 +27,11 @@ export const getCalls = (finalStatus: CallStates) => { status: CallStates.DONE, }, { - id: 'story--id [4] findByText', + id: 'story--id [3] step [2] findByText', storyId: 'story--id', cursor: 4, - path: [{ __callId__: 'story--id [3] within' }], + ancestors: ['story--id [3] step'], + path: [{ __callId__: 'story--id [3] step [1] within' }], method: 'findByText', args: ['Click'], interceptable: true, @@ -25,9 +39,10 @@ export const getCalls = (finalStatus: CallStates) => { status: CallStates.DONE, }, { - id: 'story--id [5] click', + id: 'story--id [3] step [3] click', storyId: 'story--id', cursor: 5, + ancestors: ['story--id [3] step'], path: ['userEvent'], method: 'click', args: [{ __element__: { localName: 'button', innerText: 'Click' } }], @@ -39,6 +54,7 @@ export const getCalls = (finalStatus: CallStates) => { id: 'story--id [6] waitFor', storyId: 'story--id', cursor: 6, + ancestors: [], path: [], method: 'waitFor', args: [{ __function__: { name: '' } }], @@ -48,9 +64,9 @@ export const getCalls = (finalStatus: CallStates) => { }, { id: 'story--id [6] waitFor [0] expect', - parentId: 'story--id [6] waitFor', storyId: 'story--id', cursor: 1, + ancestors: ['story--id [6] waitFor'], path: [], method: 'expect', args: [{ __function__: { name: 'handleSubmit' } }], @@ -60,9 +76,9 @@ export const getCalls = (finalStatus: CallStates) => { }, { id: 'story--id [6] waitFor [1] stringMatching', - parentId: 'story--id [6] waitFor', storyId: 'story--id', cursor: 2, + ancestors: ['story--id [6] waitFor'], path: ['expect'], method: 'stringMatching', args: [{ __regexp__: { flags: 'gi', source: '([A-Z])w+' } }], @@ -72,9 +88,9 @@ export const getCalls = (finalStatus: CallStates) => { }, { id: 'story--id [6] waitFor [2] toHaveBeenCalledWith', - parentId: 'story--id [6] waitFor', storyId: 'story--id', cursor: 3, + ancestors: ['story--id [6] waitFor'], path: [{ __callId__: 'story--id [6] waitFor [0] expect' }], method: 'toHaveBeenCalledWith', args: [{ __callId__: 'story--id [6] waitFor [1] stringMatching', retain: false }], @@ -86,6 +102,7 @@ export const getCalls = (finalStatus: CallStates) => { id: 'story--id [7] expect', storyId: 'story--id', cursor: 7, + ancestors: [], path: [], method: 'expect', args: [{ __function__: { name: 'handleReset' } }], @@ -97,6 +114,7 @@ export const getCalls = (finalStatus: CallStates) => { id: 'story--id [8] toHaveBeenCalled', storyId: 'story--id', cursor: 8, + ancestors: [], path: [{ __callId__: 'story--id [7] expect' }, 'not'], method: 'toHaveBeenCalled', args: [], @@ -121,9 +139,4 @@ export const getCalls = (finalStatus: CallStates) => { export const getInteractions = (finalStatus: CallStates) => getCalls(finalStatus) .filter((call) => call.interceptable) - .map((call, _, calls) => ({ - ...call, - childCallIds: calls.filter((c) => c.parentId === call.id).map((c) => c.id), - isCollapsed: false, - toggleCollapsed: () => {}, - })); + .map((call) => ({ ...call, childCallIds: [], isCollapsed: false, toggleCollapsed: () => {} })); diff --git a/code/addons/interactions/src/preset/preview.ts b/code/addons/interactions/src/preset/preview.ts index 662b4f4e5af2..41eadcf626f5 100644 --- a/code/addons/interactions/src/preset/preview.ts +++ b/code/addons/interactions/src/preset/preview.ts @@ -1,6 +1,12 @@ import { addons } from '@storybook/addons'; import { FORCE_REMOUNT, STORY_RENDER_PHASE_CHANGED } from '@storybook/core-events'; -import type { AnyFramework, ArgsEnhancer } from '@storybook/csf'; +import type { + AnyFramework, + ArgsEnhancer, + PlayFunction, + PlayFunctionContext, + StepLabel, +} from '@storybook/csf'; import { instrument } from '@storybook/instrumenter'; import { ModuleMocker } from 'jest-mock'; @@ -48,3 +54,8 @@ const addActionsFromArgTypes: ArgsEnhancer = ({ id, initialArgs }) addSpies(id, initialArgs); export const argsEnhancers = [addActionsFromArgTypes]; + +export const { step: runStep } = instrument( + { step: (label: StepLabel, play: PlayFunction, context: PlayFunctionContext) => play(context) }, + { intercept: true } +); diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 3f93dae279d9..df0006d8a35b 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "React storybook addon that show component jest report", "keywords": [ "addon", @@ -59,12 +59,12 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/api": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "core-js": "^3.8.2", "global": "^4.4.0", "react-sizeme": "^3.0.1", @@ -95,7 +95,7 @@ ], "platform": "browser" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53", + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a", "storybook": { "displayName": "Jest", "icon": "https://pbs.twimg.com/profile_images/821713465245102080/mMtKIMax_400x400.jpg", diff --git a/code/addons/jest/src/components/Result.tsx b/code/addons/jest/src/components/Result.tsx index 1a82ed14b16e..3a53fad6b21c 100644 --- a/code/addons/jest/src/components/Result.tsx +++ b/code/addons/jest/src/components/Result.tsx @@ -65,7 +65,7 @@ export function Result(props: ResultProps) { {status === `failed` ? ( setAddon: ClientApiClass['setAddon']; addArgsEnhancer: ClientApiClass['addArgsEnhancer']; addArgTypesEnhancer: ClientApiClass['addArgTypesEnhancer']; + addStepRunner: ClientApiClass['addStepRunner']; raw: ClientApiClass['raw']; } diff --git a/code/addons/storyshots/storyshots-core/src/frameworks/configure.ts b/code/addons/storyshots/storyshots-core/src/frameworks/configure.ts index 670ecdfd63e6..ad64cdd91d69 100644 --- a/code/addons/storyshots/storyshots-core/src/frameworks/configure.ts +++ b/code/addons/storyshots/storyshots-core/src/frameworks/configure.ts @@ -113,8 +113,15 @@ function configure( if (preview) { // This is essentially the same code as lib/core/src/server/preview/virtualModuleEntry.template - const { parameters, decorators, globals, globalTypes, argsEnhancers, argTypesEnhancers } = - jest.requireActual(preview); + const { + parameters, + decorators, + globals, + globalTypes, + argsEnhancers, + argTypesEnhancers, + runStep, + } = jest.requireActual(preview); if (decorators) { decorators.forEach((decorator: DecoratorFunction) => @@ -124,6 +131,9 @@ function configure( if (parameters || globals || globalTypes) { storybook.addParameters({ ...parameters, globals, globalTypes }); } + if (runStep) { + storybook.addStepRunner(runStep); + } if (argsEnhancers) { argsEnhancers.forEach((enhancer: ArgsEnhancer) => storybook.addArgsEnhancer(enhancer as any) diff --git a/code/addons/storyshots/storyshots-puppeteer/package.json b/code/addons/storyshots/storyshots-puppeteer/package.json index 934f244406f9..0d07b8325d56 100644 --- a/code/addons/storyshots/storyshots-puppeteer/package.json +++ b/code/addons/storyshots/storyshots-puppeteer/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storyshots-puppeteer", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Image snapshots addition to StoryShots based on puppeteer", "keywords": [ "addon", @@ -35,7 +35,7 @@ "dependencies": { "@axe-core/puppeteer": "^4.2.0", "@storybook/csf": "0.0.2--canary.0899bb7.0", - "@storybook/node-logger": "7.0.0-alpha.18", + "@storybook/node-logger": "7.0.0-alpha.23", "@types/jest-image-snapshot": "^4.1.3", "core-js": "^3.8.2", "jest-image-snapshot": "^4.3.0" @@ -45,7 +45,7 @@ "puppeteer": "^2.0.0 || ^3.0.0" }, "peerDependencies": { - "@storybook/addon-storyshots": "7.0.0-alpha.18", + "@storybook/addon-storyshots": "7.0.0-alpha.23", "puppeteer": ">=2.0.0" }, "peerDependenciesMeta": { @@ -56,5 +56,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index ae06102e602b..3958eda9ff43 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "View a storyโ€™s source code to see how it works and paste into your app", "keywords": [ "addon", @@ -35,13 +35,13 @@ "prepare": "node ../../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/api": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/router": "7.0.0-alpha.18", - "@storybook/source-loader": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/router": "7.0.0-alpha.23", + "@storybook/source-loader": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "core-js": "^3.8.2", "estraverse": "^5.2.0", "prop-types": "^15.7.2", @@ -67,7 +67,7 @@ "publishConfig": { "access": "public" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53", + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a", "storybook": { "displayName": "Storysource", "icon": "https://user-images.githubusercontent.com/263385/101991675-48cdf300-3c7c-11eb-9400-58de5ac6daa7.png", diff --git a/code/addons/toolbars/manager.js b/code/addons/toolbars/manager.js index 4e287d25b151..8a2eae4ffce1 100644 --- a/code/addons/toolbars/manager.js +++ b/code/addons/toolbars/manager.js @@ -1 +1 @@ -import './dist/esm/manager'; +import './dist/manager'; diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index 8dc9e22de58b..abd624753148 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", @@ -25,9 +25,27 @@ "url": "https://opencollective.com/storybook" }, "license": "MIT", - "main": "dist/cjs/manager.js", - "module": "dist/esm/manager.js", - "types": "dist/types/manager.d.ts", + "exports": { + ".": { + "require": "./dist/index.js", + "import": "./dist/index.mjs", + "types": "./dist/index.d.ts" + }, + "./manager": { + "require": "./dist/manager.js", + "import": "./dist/manager.mjs", + "types": "./dist/manager.d.ts" + }, + "./register.js": { + "require": "./dist/manager.js", + "import": "./dist/manager.mjs", + "types": "./dist/manager.d.ts" + }, + "./package.json": "./package.json" + }, + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", "files": [ "dist/**/*", "README.md", @@ -36,14 +54,14 @@ ], "scripts": { "check": "tsc --noEmit", - "prepare": "node ../../../scripts/prepare.js" + "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/api": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "core-js": "^3.8.2" }, "devDependencies": { @@ -64,7 +82,14 @@ "publishConfig": { "access": "public" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53", + "bundler": { + "entries": [ + "./src/index.ts", + "./src/manager.tsx" + ], + "platform": "browser" + }, + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a", "storybook": { "displayName": "Toolbars", "icon": "https://user-images.githubusercontent.com/263385/101991677-48cdf300-3c7c-11eb-93b4-19b0e3366959.png", diff --git a/code/addons/toolbars/src/components/ToolbarMenuButton.tsx b/code/addons/toolbars/src/components/ToolbarMenuButton.tsx index 038985bac859..abeefe06cdf6 100644 --- a/code/addons/toolbars/src/components/ToolbarMenuButton.tsx +++ b/code/addons/toolbars/src/components/ToolbarMenuButton.tsx @@ -4,7 +4,7 @@ import { Icons, IconButton, IconsProps } from '@storybook/components'; interface ToolbarMenuButtonProps { active: boolean; title: string; - icon: IconsProps['icon'] | ''; + icon?: IconsProps['icon']; description: string; onClick?: () => void; } diff --git a/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx b/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx index 5107df73a06c..e80b2897068a 100644 --- a/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx +++ b/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx @@ -26,7 +26,7 @@ export const ToolbarMenuListItem = ({ onClick, currentValue, }: ToolbarMenuListItemProps) => { - const Icon = ; + const Icon = icon && ; const hasContent = left || right || title; const Item: ListItem = { diff --git a/code/addons/toolbars/src/index.ts b/code/addons/toolbars/src/index.ts new file mode 100644 index 000000000000..cb0ff5c3b541 --- /dev/null +++ b/code/addons/toolbars/src/index.ts @@ -0,0 +1 @@ +export {}; diff --git a/code/addons/toolbars/src/types.ts b/code/addons/toolbars/src/types.ts index 078e007e6220..4b6d18aa54d3 100644 --- a/code/addons/toolbars/src/types.ts +++ b/code/addons/toolbars/src/types.ts @@ -26,7 +26,7 @@ export interface NormalizedToolbarConfig { /** The label to show for this toolbar item */ title?: string; /** Choose an icon to show for this toolbar item */ - icon?: IconsProps['icon']; + icon: IconsProps['icon']; /** Set to true to prevent default update of icon to match any present selected items icon */ preventDynamicIcon?: boolean; items: ToolbarItem[]; diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 1c2f410de2b2..494790baf732 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Build responsive components by adjusting Storybookโ€™s viewport size and orientation", "keywords": [ "addon", @@ -36,12 +36,12 @@ "prepare": "node ../../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/api": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "core-js": "^3.8.2", "global": "^4.4.0", "memoizerific": "^1.11.3", @@ -65,7 +65,7 @@ "publishConfig": { "access": "public" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53", + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a", "storybook": { "displayName": "Viewport", "icon": "https://user-images.githubusercontent.com/263385/101991678-48cdf300-3c7c-11eb-9764-f8af293c1b28.png", diff --git a/code/e2e-tests/addon-actions.spec.ts b/code/e2e-tests/addon-actions.spec.ts new file mode 100644 index 000000000000..efdfa76ce324 --- /dev/null +++ b/code/e2e-tests/addon-actions.spec.ts @@ -0,0 +1,26 @@ +import { test, expect } from '@playwright/test'; +import process from 'process'; +import { SbPage } from './util'; + +const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; + +test.describe('addon-actions', () => { + test.beforeEach(async ({ page }) => { + await page.goto(storybookUrl); + }); + + test('should trigger an action', async ({ page }) => { + const sbPage = new SbPage(page); + + await sbPage.navigateToStory('example-button', 'primary'); + const root = sbPage.previewRoot(); + const button = root.locator('button', { hasText: 'Button' }); + await button.click(); + + await sbPage.viewAddonPanel('Actions'); + const logItem = await page.locator('#storybook-panel-root #panel-tab-content', { + hasText: 'onClick', + }); + await expect(logItem).toBeVisible(); + }); +}); diff --git a/code/e2e-tests/addon-backgrounds.spec.ts b/code/e2e-tests/addon-backgrounds.spec.ts new file mode 100644 index 000000000000..3cb70f8031a2 --- /dev/null +++ b/code/e2e-tests/addon-backgrounds.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '@playwright/test'; +import process from 'process'; +import { SbPage } from './util'; + +const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; + +test.describe('addon-backgrounds', () => { + test.beforeEach(async ({ page }) => { + await page.goto(storybookUrl); + }); + + test('should have a dark background', async ({ page }) => { + const sbPage = new SbPage(page); + + await sbPage.navigateToStory('example-button', 'primary'); + await sbPage.selectToolbar('[title="Change the background of the preview"]', '#dark'); + + await expect(sbPage.getCanvasBodyElement()).toHaveCSS('background-color', 'rgb(51, 51, 51)'); + }); + + test('should apply a grid', async ({ page }) => { + const sbPage = new SbPage(page); + + await sbPage.navigateToStory('example-button', 'primary'); + await sbPage.selectToolbar('[title="Apply a grid to the preview"]'); + + await expect(sbPage.getCanvasBodyElement()).toHaveCSS('background-image', /linear-gradient/); + }); +}); diff --git a/code/e2e-tests/addon-controls.spec.ts b/code/e2e-tests/addon-controls.spec.ts new file mode 100644 index 000000000000..a49f7cbeb489 --- /dev/null +++ b/code/e2e-tests/addon-controls.spec.ts @@ -0,0 +1,71 @@ +import { test, expect } from '@playwright/test'; +import process from 'process'; +import { SbPage } from './util'; + +const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; + +test.describe('addon-controls', () => { + test('should change component when changing controls', async ({ page }) => { + await page.goto(storybookUrl); + const sbPage = new SbPage(page); + + await sbPage.navigateToStory('example-button', 'primary'); + await sbPage.viewAddonPanel('Controls'); + + // Text input: Label + await expect(sbPage.previewRoot().locator('button')).toContainText('Button'); + const label = sbPage.panelContent().locator('textarea[name=label]'); + await label.fill('Hello world'); + await expect(sbPage.previewRoot().locator('button')).toContainText('Hello world'); + + // Args in URL + await page.waitForTimeout(300); + const url = await page.url(); + await expect(url).toContain('args=label:Hello+world'); + + // Boolean toggle: Primary/secondary + await expect(sbPage.previewRoot().locator('button')).toHaveCSS( + 'background-color', + 'rgb(30, 167, 253)' + ); + const toggle = sbPage.panelContent().locator('input[name=primary]'); + await toggle.click(); + await expect(sbPage.previewRoot().locator('button')).toHaveCSS( + 'background-color', + 'rgba(0, 0, 0, 0)' + ); + + // Color picker: Background color + const color = sbPage.panelContent().locator('input[placeholder="Choose color..."]'); + await color.fill('red'); + await expect(sbPage.previewRoot().locator('button')).toHaveCSS( + 'background-color', + 'rgb(255, 0, 0)' + ); + + // TODO: enable this once the controls for size are aligned in all CLI templates. + // Radio buttons: Size + // cy.getStoryElement().find('button').should('have.css', 'font-size', '14px'); + // cy.get('label[for="size-large"]').click(); + // cy.getStoryElement().find('button').should('have.css', 'font-size', '16px'); + + // Reset controls: assert that the component is back to original state + const reset = sbPage.panelContent().locator('button[title="Reset controls"]'); + await reset.click(); + const button = sbPage.previewRoot().locator('button'); + await expect(button).toHaveCSS('font-size', '14px'); + await expect(button).toHaveCSS('background-color', 'rgb(30, 167, 253)'); + await expect(button).toContainText('Button'); + }); + + test('should apply controls automatically when passed via url', async ({ page }) => { + await page.goto(`${storybookUrl}?path=/story/example-button--primary&args=label:Hello+world`); + + const sbPage = new SbPage(page); + await expect(sbPage.previewRoot().locator('button')).toContainText('Hello world'); + + await sbPage.viewAddonPanel('Controls'); + const label = await sbPage.panelContent().locator('textarea[name=label]').inputValue(); + await expect(label).toEqual('Hello world'); + }); +}); diff --git a/code/e2e-tests/addon-docs.spec.ts b/code/e2e-tests/addon-docs.spec.ts new file mode 100644 index 000000000000..2be60673da1b --- /dev/null +++ b/code/e2e-tests/addon-docs.spec.ts @@ -0,0 +1,40 @@ +/* eslint-disable jest/no-disabled-tests */ +/* eslint-disable no-await-in-loop */ +import { test, expect } from '@playwright/test'; +import process from 'process'; +import { SbPage } from './util'; + +const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; +const templateName = process.env.STORYBOOK_TEMPLATE_NAME || ''; + +test.describe('addon-docs', () => { + test.beforeEach(async ({ page }) => { + await page.goto(storybookUrl); + }); + + test('should provide source snippet', async ({ page }) => { + test.skip( + /^vue3/.test(templateName), + `Skipping ${templateName}, which does not support dynamic source snippets` + ); + + const sbPage = new SbPage(page); + await sbPage.navigateToStory('example-button', 'docs'); + const root = sbPage.previewRoot(); + const toggles = root.locator('.docblock-code-toggle'); + + const toggleCount = await toggles.count(); + for (let i = 0; i < toggleCount; i += 1) { + const toggle = await toggles.nth(i); + await toggle.click({ force: true }); + } + + const codes = root.locator('pre.prismjs'); + const codeCount = await codes.count(); + for (let i = 0; i < codeCount; i += 1) { + const code = await codes.nth(i); + const text = await code.innerText(); + await expect(text).not.toMatch(/^\(args\) => /); + } + }); +}); diff --git a/code/e2e-tests/addon-interactions.spec.ts b/code/e2e-tests/addon-interactions.spec.ts new file mode 100644 index 000000000000..52a517ce6790 --- /dev/null +++ b/code/e2e-tests/addon-interactions.spec.ts @@ -0,0 +1,33 @@ +import { test, expect } from '@playwright/test'; +import process from 'process'; +import { SbPage } from './util'; + +const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; + +test.describe('addon-interactions', () => { + test.beforeEach(async ({ page }) => { + await page.goto(storybookUrl); + }); + + // FIXME: skip xxx + test('should have interactions', async ({ page }) => { + const sbPage = new SbPage(page); + + await sbPage.navigateToStory('example-page', 'logged-in'); + await sbPage.viewAddonPanel('Interactions'); + + const welcome = await sbPage.previewRoot().locator('.welcome'); + await expect(welcome).toContainText('Welcome, Jane Doe!'); + + const interactionsTab = await page.locator('#tabbutton-interactions'); + await expect(interactionsTab).toContainText(/(1)/); + await expect(interactionsTab).toBeVisible(); + + const panel = sbPage.panelContent(); + await expect(panel).toContainText(/userEvent.click/); + await expect(panel).toBeVisible(); + + const done = await panel.locator('[data-testid=icon-done]'); + await expect(done).toBeVisible(); + }); +}); diff --git a/code/e2e-tests/addon-viewport.spec.ts b/code/e2e-tests/addon-viewport.spec.ts new file mode 100644 index 000000000000..a5935b4db2cd --- /dev/null +++ b/code/e2e-tests/addon-viewport.spec.ts @@ -0,0 +1,22 @@ +import { test, expect } from '@playwright/test'; +import process from 'process'; +import { SbPage } from './util'; + +const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; + +test.describe('addon-viewport', () => { + test.beforeEach(async ({ page }) => { + await page.goto(storybookUrl); + }); + + test('should have viewport button in the toolbar', async ({ page }) => { + const sbPage = new SbPage(page); + + // Click on viewport button and select small mobile + await sbPage.navigateToStory('example-button', 'primary'); + await sbPage.selectToolbar('[title="Change the size of the preview"]', '#mobile1'); + + // Check that Button story is still displayed + await expect(sbPage.previewRoot()).toContainText('Button'); + }); +}); diff --git a/code/e2e-tests/example.spec.ts b/code/e2e-tests/example.spec.ts new file mode 100644 index 000000000000..6caeddd4077b --- /dev/null +++ b/code/e2e-tests/example.spec.ts @@ -0,0 +1,14 @@ +import { test, expect } from '@playwright/test'; +import process from 'process'; + +const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; + +test('Basic story test', async ({ page }) => { + await page.goto(storybookUrl); + + const preview = page.frameLocator('#storybook-preview-iframe'); + const root = preview.locator('#root:visible, #docs-root:visible'); + + // Specific check for introduction story + await expect(root).toContainText('Welcome'); +}); diff --git a/code/e2e-tests/util.ts b/code/e2e-tests/util.ts new file mode 100644 index 000000000000..e9aef15095cf --- /dev/null +++ b/code/e2e-tests/util.ts @@ -0,0 +1,64 @@ +/* eslint-disable jest/no-standalone-expect */ +import { expect, Page } from '@playwright/test'; + +export class SbPage { + readonly page: Page; + + constructor(page: Page) { + this.page = page; + } + + async navigateToStory(title: string, name: string) { + const titleId = title.replace(/ /g, '-').toLowerCase(); + const storyId = name.replace(/ /g, '-').toLowerCase(); + + const titleLink = this.page.locator(`#${titleId}`); + if ((await titleLink.getAttribute('aria-expanded')) === 'false') { + await titleLink.click(); + } + + const storyLinkId = `#${titleId}--${storyId}`; + await this.page.waitForSelector(storyLinkId); + const storyLink = this.page.locator(storyLinkId); + await storyLink.click({ force: true }); + + // assert url changes + const viewMode = name === 'docs' ? 'docs' : 'story'; + + const url = this.page.url(); + await expect(url).toContain(`path=/${viewMode}/${titleId}--${storyId}`); + + const selected = await storyLink.getAttribute('data-selected'); + await expect(selected).toBe('true'); + } + + previewIframe() { + return this.page.frameLocator('#storybook-preview-iframe'); + } + + previewRoot() { + const preview = this.previewIframe(); + return preview.locator('#root:visible, #docs-root:visible'); + } + + panelContent() { + return this.page.locator('#storybook-panel-root #panel-tab-content'); + } + + async viewAddonPanel(name: string) { + const tabs = await this.page.locator('[role=tablist] button[role=tab]'); + const tab = tabs.locator(`text=/^${name}/`); + await tab.click(); + } + + async selectToolbar(toolbarSelector: string, itemSelector?: string) { + await this.page.locator(toolbarSelector).click(); + if (itemSelector) { + await this.page.locator(itemSelector).click(); + } + } + + getCanvasBodyElement() { + return this.previewIframe().locator('body'); + } +} diff --git a/code/examples/angular-cli/package.json b/code/examples/angular-cli/package.json index 63f533024e20..5ca23e990b49 100644 --- a/code/examples/angular-cli/package.json +++ b/code/examples/angular-cli/package.json @@ -1,6 +1,6 @@ { "name": "angular-cli", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "license": "MIT", "workspaces": { @@ -44,22 +44,22 @@ "@angular/compiler-cli": "^13.3.6", "@angular/elements": "^13.3.6", "@compodoc/compodoc": "^1.1.18", - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-interactions": "7.0.0-alpha.18", - "@storybook/addon-jest": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/angular": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-interactions": "7.0.0-alpha.23", + "@storybook/addon-jest": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/angular": "7.0.0-alpha.23", "@storybook/babel-plugin-require-context-hook": "1.0.1", "@storybook/jest": "^0.0.10", - "@storybook/source-loader": "7.0.0-alpha.18", + "@storybook/source-loader": "7.0.0-alpha.23", "@storybook/testing-library": "0.0.14-next.0", "@types/core-js": "^2.5.4", "@types/jest": "^26.0.16", @@ -72,7 +72,7 @@ "jest": "^26.6.3", "jest-preset-angular": "^8.3.2", "protractor": "~7.0.0", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "storybook-addon-angular-ivy": "^0.0.1", "ts-jest": "^26.4.4", "ts-node": "^10.4.0", diff --git a/code/examples/angular-cli/src/stories/legacy/README.stories.mdx b/code/examples/angular-cli/src/stories/legacy/README.stories.mdx index 2bc92c455138..f1a838261aef 100644 --- a/code/examples/angular-cli/src/stories/legacy/README.stories.mdx +++ b/code/examples/angular-cli/src/stories/legacy/README.stories.mdx @@ -4,4 +4,4 @@ import { Meta } from '@storybook/addon-docs'; # Legacy examples -Example of sotry still supported by storybook but no longer recommended or deprecated +Example of story still supported by storybook but no longer recommended or deprecated diff --git a/code/examples/cra-kitchen-sink/.storybook/manager.js b/code/examples/cra-kitchen-sink/.storybook/manager.js index a53f23565dd2..8b2c926cf5fe 100644 --- a/code/examples/cra-kitchen-sink/.storybook/manager.js +++ b/code/examples/cra-kitchen-sink/.storybook/manager.js @@ -1,4 +1,4 @@ -import { create } from '@storybook/theming'; +import { create } from '@storybook/theming/create'; import { addons } from '@storybook/addons'; addons.setConfig({ diff --git a/code/examples/cra-kitchen-sink/package.json b/code/examples/cra-kitchen-sink/package.json index a294d95c32d1..303f8400475b 100644 --- a/code/examples/cra-kitchen-sink/package.json +++ b/code/examples/cra-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "cra-kitchen-sink", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "react-scripts build", @@ -11,7 +11,7 @@ "test": "react-scripts test --env=jsdom" }, "dependencies": { - "@storybook/client-logger": "7.0.0-alpha.18", + "@storybook/client-logger": "7.0.0-alpha.23", "global": "^4.4.0", "prop-types": "^15.7.2", "react": "16.14.0", @@ -21,21 +21,21 @@ }, "devDependencies": { "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5", - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-jest": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/builder-webpack5": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-jest": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/builder-webpack5": "7.0.0-alpha.23", "@storybook/preset-create-react-app": "^4.1.0", - "@storybook/react": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", - "storybook": "7.0.0-alpha.18", + "@storybook/react": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", + "storybook": "7.0.0-alpha.23", "webpack": "5" }, "storybook": { diff --git a/code/examples/cra-ts-essentials/.storybook/main.ts b/code/examples/cra-ts-essentials/.storybook/main.ts index 01c95af66b35..8a4882ff3aa7 100644 --- a/code/examples/cra-ts-essentials/.storybook/main.ts +++ b/code/examples/cra-ts-essentials/.storybook/main.ts @@ -12,6 +12,7 @@ const mainConfig: StorybookConfig = { viewport: false, }, }, + '@storybook/addon-interactions', ], logLevel: 'debug', // add monorepo root as a valid directory to import modules from diff --git a/code/examples/cra-ts-essentials/package.json b/code/examples/cra-ts-essentials/package.json index a4809b8c0471..3895ad5c3c5b 100644 --- a/code/examples/cra-ts-essentials/package.json +++ b/code/examples/cra-ts-essentials/package.json @@ -1,6 +1,6 @@ { "name": "cra-ts-essentials", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "react-scripts build", @@ -23,8 +23,8 @@ ] }, "dependencies": { - "@storybook/components": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "@types/jest": "^26.0.16", "@types/node": "^14.14.20 || ^16.0.0", "@types/react": "^16.14.23", @@ -37,14 +37,15 @@ "typescript": "~4.6.3" }, "devDependencies": { - "@storybook/addon-essentials": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/builder-webpack5": "7.0.0-alpha.18", + "@storybook/addon-essentials": "7.0.0-alpha.23", + "@storybook/addon-interactions": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/builder-webpack5": "7.0.0-alpha.23", "@storybook/preset-create-react-app": "^4.1.0", - "@storybook/react": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", + "@storybook/react": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", "@storybook/testing-library": "^0.0.9", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "ts-node": "^10.4.0", "webpack": "5" }, diff --git a/code/examples/cra-ts-essentials/src/stories/testing-react/components/Button.stories.tsx b/code/examples/cra-ts-essentials/src/stories/testing-react/components/Button.stories.tsx index 7dc7cabc6a55..d87e1e317baf 100644 --- a/code/examples/cra-ts-essentials/src/stories/testing-react/components/Button.stories.tsx +++ b/code/examples/cra-ts-essentials/src/stories/testing-react/components/Button.stories.tsx @@ -79,8 +79,10 @@ export const CSF3InputFieldFilled: CSF3Story = { render: () => { return ; }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - await userEvent.type(canvas.getByTestId('input'), 'Hello world!'); + await step('Step label', async () => { + await userEvent.type(canvas.getByTestId('input'), 'Hello world!'); + }); }, }; diff --git a/code/examples/cra-ts-kitchen-sink/package.json b/code/examples/cra-ts-kitchen-sink/package.json index e82a5a53a937..3a8ba5bc97dc 100644 --- a/code/examples/cra-ts-kitchen-sink/package.json +++ b/code/examples/cra-ts-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "cra-ts-kitchen-sink", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "react-scripts build", @@ -34,23 +34,23 @@ "typescript": "~4.6.3" }, "devDependencies": { - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/builder-webpack5": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/builder-webpack5": "7.0.0-alpha.23", "@storybook/preset-create-react-app": "^4.1.0", - "@storybook/react": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", + "@storybook/react": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", "@types/enzyme": "^3.10.8", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.9.1", "enzyme-to-json": "^3.6.1", "fork-ts-checker-webpack-plugin": "^7.2.6", "react-moment-proptypes": "^1.7.0", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "ts-node": "^10.4.0", "webpack": "5" }, diff --git a/code/examples/doc-blocks/package.json b/code/examples/doc-blocks/package.json index 7f41a86e080c..492169197a82 100644 --- a/code/examples/doc-blocks/package.json +++ b/code/examples/doc-blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/example-doc-blocks", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build-storybook": "cross-env STORYBOOK_DISPLAY_WARNING=true DISPLAY_WARNING=true sb build", @@ -15,20 +15,20 @@ "@babel/preset-env": "^7.12.11", "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", - "@storybook/addon-essentials": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/cli": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/addon-essentials": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/cli": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "@types/babel__preset-env": "^7", "@types/react": "^16.14.23", "@types/react-dom": "^16.9.14", "cross-env": "^7.0.3", "lodash": "^4.17.21", - "sb": "7.0.0-alpha.18", + "sb": "7.0.0-alpha.23", "typescript": "~4.6.3", "webpack": "5" }, diff --git a/code/examples/ember-cli/package.json b/code/examples/ember-cli/package.json index 1773b827c707..c99dbe99691d 100644 --- a/code/examples/ember-cli/package.json +++ b/code/examples/ember-cli/package.json @@ -1,6 +1,6 @@ { "name": "ember-example", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "--build-storybook": "yarn storybook-prebuild && storybook build", @@ -17,19 +17,19 @@ "devDependencies": { "@babel/core": "^7.12.10", "@ember/optional-features": "^2.0.0", - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addon-viewport": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/ember": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addon-viewport": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/ember": "7.0.0-alpha.23", "@storybook/ember-cli-storybook": "^0.2.1", - "@storybook/source-loader": "7.0.0-alpha.18", + "@storybook/source-loader": "7.0.0-alpha.23", "babel-loader": "^8.2.5", "broccoli-asset-rev": "^3.0.0", "browserify-zlib": "^0.2.0", @@ -49,7 +49,7 @@ "loader.js": "^4.7.0", "os-browserify": "^0.3.0", "shx": "^0.3.2", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "stream-browserify": "^3.0.0", "vm-browserify": "^1.1.2", "webpack": "5", diff --git a/code/examples/external-docs/package.json b/code/examples/external-docs/package.json index 45ea4cae4e13..414fc2fbf0e4 100644 --- a/code/examples/external-docs/package.json +++ b/code/examples/external-docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/external-docs", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "next build", @@ -11,15 +11,15 @@ "storybook": "cross-env STORYBOOK_DISPLAY_WARNING=true DISPLAY_WARNING=true storybook dev -p 9011 --no-manager-cache -c .storybook" }, "dependencies": { - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-essentials": "7.0.0-alpha.18", - "@storybook/blocks": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-essentials": "7.0.0-alpha.23", + "@storybook/blocks": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", "@storybook/csf": "0.0.2--canary.0899bb7.0", - "@storybook/preview-web": "7.0.0-alpha.18", - "@storybook/react": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/preview-web": "7.0.0-alpha.23", + "@storybook/react": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "formik": "^2.2.9", "next": "^12.1.0", "nextra": "^1.1.0", @@ -38,7 +38,7 @@ "cross-env": "^7.0.3", "eslint": "8.7.0", "eslint-config-next": "12.0.8", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "typescript": "~4.6.3", "webpack": "5" } diff --git a/code/examples/html-kitchen-sink/package.json b/code/examples/html-kitchen-sink/package.json index 424bfc448a48..260b27d95dc9 100644 --- a/code/examples/html-kitchen-sink/package.json +++ b/code/examples/html-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "html-kitchen-sink", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "description": "", "keywords": [], @@ -13,31 +13,31 @@ "storybook": "storybook dev -p 9006 --no-manager-cache" }, "devDependencies": { - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-jest": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-jest": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", "@storybook/addon-postcss": "^2.0.0", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addon-viewport": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/client-api": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", - "@storybook/html": "7.0.0-alpha.18", - "@storybook/html-webpack5": "7.0.0-alpha.18", - "@storybook/source-loader": "7.0.0-alpha.18", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addon-viewport": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/client-api": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", + "@storybook/html": "7.0.0-alpha.23", + "@storybook/html-webpack5": "7.0.0-alpha.23", + "@storybook/source-loader": "7.0.0-alpha.23", "autoprefixer": "^10.0.1", "eventemitter3": "^4.0.7", "format-json": "^1.0.3", "global": "^4.4.0", "postcss": "^8.2.4", "postcss-color-rebeccapurple": "^6.0.0", - "storybook": "7.0.0-alpha.18" + "storybook": "7.0.0-alpha.23" }, "storybook": { "chromatic": { diff --git a/code/examples/official-storybook/manager.js b/code/examples/official-storybook/manager.js index 642d6e7bfb23..77104c4f6326 100644 --- a/code/examples/official-storybook/manager.js +++ b/code/examples/official-storybook/manager.js @@ -8,10 +8,11 @@ import addHeadWarning from './head-warning'; addHeadWarning('manager-head-not-loaded', 'Manager head not loaded'); const PrefixIcon = styled(Icons)(({ theme }) => ({ - marginRight: 8, + marginRight: 5, fontSize: 'inherit', - height: '1em', - width: '1em', + height: 12, + width: 12, + paddingTop: 1, display: 'inline', alignSelf: 'center', })); diff --git a/code/examples/official-storybook/package.json b/code/examples/official-storybook/package.json index 7745dffa6777..41e0c8a5b323 100644 --- a/code/examples/official-storybook/package.json +++ b/code/examples/official-storybook/package.json @@ -1,6 +1,6 @@ { "name": "official-storybook", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build-storybook": "cross-env STORYBOOK_DISPLAY_WARNING=true DISPLAY_WARNING=true storybook build -c ./", @@ -13,33 +13,33 @@ "devDependencies": { "@emotion/jest": "^11.8.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5", - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-interactions": "7.0.0-alpha.18", - "@storybook/addon-jest": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storyshots-puppeteer": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addon-toolbars": "7.0.0-alpha.18", - "@storybook/addon-viewport": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/cli": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-interactions": "7.0.0-alpha.23", + "@storybook/addon-jest": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storyshots-puppeteer": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addon-toolbars": "7.0.0-alpha.23", + "@storybook/addon-viewport": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/cli": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", "@storybook/design-system": "^5.4.7", "@storybook/jest": "^0.0.10", - "@storybook/node-logger": "7.0.0-alpha.18", - "@storybook/react": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", - "@storybook/router": "7.0.0-alpha.18", - "@storybook/source-loader": "7.0.0-alpha.18", + "@storybook/node-logger": "7.0.0-alpha.23", + "@storybook/react": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", + "@storybook/router": "7.0.0-alpha.23", + "@storybook/source-loader": "7.0.0-alpha.23", "@storybook/testing-library": "0.0.14-next.0", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/theming": "7.0.0-alpha.23", "@testing-library/dom": "^7.31.2", "@testing-library/user-event": "^13.1.9", "chromatic": "^6.0.2", @@ -55,7 +55,7 @@ "prop-types": "^15.7.2", "react": "16.14.0", "react-dom": "16.14.0", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "terser-webpack-plugin": "^5.3.1", "uuid-browser": "^3.1.0", "webpack": "5" diff --git a/code/examples/official-storybook/preview.js b/code/examples/official-storybook/preview.js index 638d31b1af82..e4e0ef7fa7d9 100644 --- a/code/examples/official-storybook/preview.js +++ b/code/examples/official-storybook/preview.js @@ -72,6 +72,25 @@ const ThemeStack = styled.div( }) ); +const PlayFnNotice = styled.div( + { + position: 'absolute', + bottom: '1rem', + right: '1rem', + border: '1px solid #ccc', + borderRadius: '5px', + padding: '1rem', + fontSize: '12px', + '> *': { + display: 'block', + }, + }, + ({ theme }) => ({ + background: theme.background.app, + color: theme.color.defaultText, + }) +); + const ThemedSetRoot = () => { const theme = useTheme(); @@ -87,8 +106,9 @@ const ThemedSetRoot = () => { }; export const decorators = [ - (StoryFn, { globals, parameters }) => { - const theme = globals.theme || parameters.theme || (isChromatic() ? 'stacked' : 'light'); + (StoryFn, { globals, parameters, playFunction }) => { + const defaultTheme = isChromatic() && !playFunction ? 'stacked' : 'light'; + const theme = globals.theme || parameters.theme || defaultTheme; switch (theme) { case 'side-by-side': { @@ -137,6 +157,12 @@ export const decorators = [ + {!parameters.theme && isChromatic() && playFunction && ( + + Detected play function. + Rendering in a single theme + + )} ); diff --git a/code/examples/official-storybook/stories/title/AutoTitle.stories.js b/code/examples/official-storybook/stories/title/AutoTitle.stories.js index 125c1157c1c1..a7fcbf4a4e82 100644 --- a/code/examples/official-storybook/stories/title/AutoTitle.stories.js +++ b/code/examples/official-storybook/stories/title/AutoTitle.stories.js @@ -9,4 +9,4 @@ export default { component: Button, }; -export const Basic = () => ; diff --git a/code/examples/official-storybook/stories/title/CustomTitle.stories.js b/code/examples/official-storybook/stories/title/CustomTitle.stories.js index 1ff5710b11d1..12182a5d961e 100644 --- a/code/examples/official-storybook/stories/title/CustomTitle.stories.js +++ b/code/examples/official-storybook/stories/title/CustomTitle.stories.js @@ -8,4 +8,4 @@ export default { component: Button, }; -export const Basic = () => ; diff --git a/code/examples/preact-kitchen-sink/package.json b/code/examples/preact-kitchen-sink/package.json index 2b0865fd1dbe..36ea950a5ad3 100644 --- a/code/examples/preact-kitchen-sink/package.json +++ b/code/examples/preact-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "preact-example", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", @@ -14,18 +14,18 @@ }, "devDependencies": { "@babel/core": "^7.12.10", - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addon-viewport": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/preact": "7.0.0-alpha.18", - "@storybook/preact-webpack5": "7.0.0-alpha.18", - "@storybook/source-loader": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addon-viewport": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/preact": "7.0.0-alpha.23", + "@storybook/preact-webpack5": "7.0.0-alpha.23", + "@storybook/source-loader": "7.0.0-alpha.23", "@types/prop-types": "^15.7.3", "@types/react": "^17", "@types/react-dom": "^17", @@ -38,7 +38,7 @@ "raw-loader": "^4.0.2", "react": "^17.0.2", "react-dom": "^17.0.2", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "svg-url-loader": "^7.1.1", "webpack": "5", "webpack-dev-server": "^4.8.1" diff --git a/code/examples/react-ts/package.json b/code/examples/react-ts/package.json index a1df138de38e..d1320c777f99 100644 --- a/code/examples/react-ts/package.json +++ b/code/examples/react-ts/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/example-react-ts", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build-storybook": "cross-env STORYBOOK_DISPLAY_WARNING=true DISPLAY_WARNING=true storybook build", @@ -17,15 +17,15 @@ "@babel/preset-env": "^7.12.11", "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", - "@storybook/addon-essentials": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/cli": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/react": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/addon-essentials": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/cli": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/react": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "@testing-library/dom": "^7.31.2", "@testing-library/react": "12.1.2", "@testing-library/user-event": "^13.1.9", @@ -34,7 +34,7 @@ "@types/react-dom": "^16.9.14", "cross-env": "^7.0.3", "lodash": "^4.17.21", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "typescript": "~4.6.3", "webpack": "5" } diff --git a/code/examples/react-ts/src/__snapshots__/storyshots.test.ts.snap b/code/examples/react-ts/src/__snapshots__/storyshots.test.ts.snap index a3430706744a..fbd5d981a4b7 100644 --- a/code/examples/react-ts/src/__snapshots__/storyshots.test.ts.snap +++ b/code/examples/react-ts/src/__snapshots__/storyshots.test.ts.snap @@ -46,12 +46,12 @@ exports[`Storyshots Custom Prefix/AutoTitle Basic 1`] = ` .emotion-0 svg { display: inline-block; - height: 14px; - width: 14px; + height: 12px; + width: 12px; vertical-align: top; margin-right: 4px; - margin-top: -1px; - margin-bottom: -1px; + margin-top: 0; + margin-bottom: 0; pointer-events: none; } @@ -81,8 +81,9 @@ exports[`Storyshots Custom Prefix/AutoTitle Basic 1`] = ` `; exports[`Storyshots Custom Prefix/CustomTitle Basic 1`] = ` @@ -131,12 +132,12 @@ exports[`Storyshots Custom Prefix/CustomTitle Basic 1`] = ` .emotion-0 svg { display: inline-block; - height: 14px; - width: 14px; + height: 12px; + width: 12px; vertical-align: top; margin-right: 4px; - margin-top: -1px; - margin-bottom: -1px; + margin-top: 0; + margin-bottom: 0; pointer-events: none; } @@ -166,8 +167,9 @@ exports[`Storyshots Custom Prefix/CustomTitle Basic 1`] = ` `; exports[`Storyshots Demo/AccountForm Standard 1`] = ` diff --git a/code/examples/react-ts/src/title/AutoTitle.stories.js b/code/examples/react-ts/src/title/AutoTitle.stories.js index 125c1157c1c1..a7fcbf4a4e82 100644 --- a/code/examples/react-ts/src/title/AutoTitle.stories.js +++ b/code/examples/react-ts/src/title/AutoTitle.stories.js @@ -9,4 +9,4 @@ export default { component: Button, }; -export const Basic = () => ; diff --git a/code/examples/react-ts/src/title/CustomTitle.stories.js b/code/examples/react-ts/src/title/CustomTitle.stories.js index 1ff5710b11d1..12182a5d961e 100644 --- a/code/examples/react-ts/src/title/CustomTitle.stories.js +++ b/code/examples/react-ts/src/title/CustomTitle.stories.js @@ -8,4 +8,4 @@ export default { component: Button, }; -export const Basic = () => ; diff --git a/code/examples/server-kitchen-sink/package.json b/code/examples/server-kitchen-sink/package.json index 12f6f3614d40..d50272f9c0e1 100644 --- a/code/examples/server-kitchen-sink/package.json +++ b/code/examples/server-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "server-kitchen-sink", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "description": "", "keywords": [], @@ -14,15 +14,15 @@ "storybook": "SERVER_PORT=1137 storybook dev -p 9006 --quiet" }, "devDependencies": { - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/node-logger": "7.0.0-alpha.18", - "@storybook/server": "7.0.0-alpha.18", - "@storybook/server-webpack5": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/node-logger": "7.0.0-alpha.23", + "@storybook/server": "7.0.0-alpha.23", + "@storybook/server-webpack5": "7.0.0-alpha.23", "concurrently": "^5.3.0", "cors": "^2.8.5", "express": "~4.17.1", @@ -30,6 +30,6 @@ "nodemon": "^2.0.7", "pug": "^3.0.0", "safe-identifier": "^0.4.1", - "storybook": "7.0.0-alpha.18" + "storybook": "7.0.0-alpha.23" } } diff --git a/code/examples/standalone-preview/package.json b/code/examples/standalone-preview/package.json index a094b0c6e5fd..9c9f818b4390 100644 --- a/code/examples/standalone-preview/package.json +++ b/code/examples/standalone-preview/package.json @@ -1,20 +1,20 @@ { "name": "standalone-preview", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "storybook": "cross-env STORYBOOK_DISPLAY_WARNING=true DISPLAY_WARNING=true storybook dev -p 9011 -c ../official-storybook --no-manager-cache --preview-url=http://localhost:1337/external-iframe.html", "storybook-preview": "cross-env PREVIEW_URL=external-iframe.html parcel ./storybook.html --port 1337" }, "devDependencies": { - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/cli": "7.0.0-alpha.18", - "@storybook/react": "7.0.0-alpha.18", - "@storybook/react-webpack5": "7.0.0-alpha.18", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/cli": "7.0.0-alpha.23", + "@storybook/react": "7.0.0-alpha.23", + "@storybook/react-webpack5": "7.0.0-alpha.23", "cross-env": "^7.0.3", "parcel": "2.0.1", "react": "16.14.0", "react-dom": "16.14.0", - "storybook": "7.0.0-alpha.18" + "storybook": "7.0.0-alpha.23" } } diff --git a/code/examples/svelte-kitchen-sink/package.json b/code/examples/svelte-kitchen-sink/package.json index b6f3e5327af8..4957373ba177 100644 --- a/code/examples/svelte-kitchen-sink/package.json +++ b/code/examples/svelte-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "svelte-example", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build-storybook": "storybook build", @@ -10,24 +10,24 @@ "global": "^4.4.0" }, "devDependencies": { - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-interactions": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addon-viewport": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-interactions": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addon-viewport": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", "@storybook/jest": "^0.0.10", - "@storybook/source-loader": "7.0.0-alpha.18", - "@storybook/svelte": "7.0.0-alpha.18", - "@storybook/svelte-webpack5": "7.0.0-alpha.18", + "@storybook/source-loader": "7.0.0-alpha.23", + "@storybook/svelte": "7.0.0-alpha.23", + "@storybook/svelte-webpack5": "7.0.0-alpha.23", "@storybook/testing-library": "0.0.14-next.0", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "svelte-jester": "^2.3.2", "svelte-preprocess": "^4.10.6" }, diff --git a/code/examples/svelte-kitchen-sink/src/stories/addon-docs.stories.mdx b/code/examples/svelte-kitchen-sink/src/stories/addon-docs.stories.mdx index 2774e7d290d5..4eab7e5c6774 100644 --- a/code/examples/svelte-kitchen-sink/src/stories/addon-docs.stories.mdx +++ b/code/examples/svelte-kitchen-sink/src/stories/addon-docs.stories.mdx @@ -67,7 +67,7 @@ And `square`: ## More info -For more info, check out the [Storybook Docs README](https://github.com/storybookjs/storybook/tree/next/addons/docs). +For more info, check out the [Storybook Docs README](https://github.com/storybookjs/storybook/tree/next/code/addons/docs). We want your feedback to help make this more useful. diff --git a/code/examples/vue-3-cli/package.json b/code/examples/vue-3-cli/package.json index 54cf20617505..024ed471e2f2 100644 --- a/code/examples/vue-3-cli/package.json +++ b/code/examples/vue-3-cli/package.json @@ -1,6 +1,6 @@ { "name": "vue-3-cli-example", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "vue-cli-service build", @@ -14,21 +14,21 @@ }, "devDependencies": { "@babel/core": "^7.12.10", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-essentials": "7.0.0-alpha.18", - "@storybook/addon-interactions": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-essentials": "7.0.0-alpha.23", + "@storybook/addon-interactions": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", "@storybook/jest": "^0.0.10", "@storybook/testing-library": "0.0.14-next.0", - "@storybook/vue3": "7.0.0-alpha.18", - "@storybook/vue3-webpack5": "7.0.0-alpha.18", + "@storybook/vue3": "7.0.0-alpha.23", + "@storybook/vue3-webpack5": "7.0.0-alpha.23", "@vue/cli-plugin-babel": "^5.0.4", "@vue/cli-plugin-typescript": "^5.0.4", "@vue/cli-service": "^5.0.4", "@vue/compiler-sfc": "^3.2.36", "babel-loader": "^8.2.5", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "typescript": "~4.6.3", "vue-jest": "^5.0.0-alpha.8", "vue-loader": "^16.0.0" diff --git a/code/examples/vue-cli/package.json b/code/examples/vue-cli/package.json index 19de2ab13d21..5620dead0c8d 100644 --- a/code/examples/vue-cli/package.json +++ b/code/examples/vue-cli/package.json @@ -1,6 +1,6 @@ { "name": "vue-cli-example", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "vue-cli-service build", @@ -15,16 +15,16 @@ "vue-property-decorator": "^9.1.2" }, "devDependencies": { - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-essentials": "7.0.0-alpha.18", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-essentials": "7.0.0-alpha.23", "@storybook/preset-scss": "^1.0.3", - "@storybook/source-loader": "7.0.0-alpha.18", - "@storybook/vue": "7.0.0-alpha.18", - "@storybook/vue-webpack5": "7.0.0-alpha.18", + "@storybook/source-loader": "7.0.0-alpha.23", + "@storybook/vue": "7.0.0-alpha.23", + "@storybook/vue-webpack5": "7.0.0-alpha.23", "@vue/cli-plugin-babel": "^5.0.4", "@vue/cli-plugin-typescript": "^5.0.4", "@vue/cli-service": "^5.0.4", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "typescript": "~4.6.3", "vue-template-compiler": "^2.6.14" } diff --git a/code/examples/vue-kitchen-sink/package.json b/code/examples/vue-kitchen-sink/package.json index 4ceab0ad9e99..7d5e784769d9 100644 --- a/code/examples/vue-kitchen-sink/package.json +++ b/code/examples/vue-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "vue-example", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "scripts": { "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", @@ -14,29 +14,29 @@ }, "devDependencies": { "@babel/core": "^7.12.10", - "@storybook/addon-a11y": "7.0.0-alpha.18", - "@storybook/addon-actions": "7.0.0-alpha.18", - "@storybook/addon-backgrounds": "7.0.0-alpha.18", - "@storybook/addon-controls": "7.0.0-alpha.18", - "@storybook/addon-docs": "7.0.0-alpha.18", - "@storybook/addon-highlight": "7.0.0-alpha.18", - "@storybook/addon-interactions": "7.0.0-alpha.18", - "@storybook/addon-links": "7.0.0-alpha.18", - "@storybook/addon-storyshots": "7.0.0-alpha.18", - "@storybook/addon-storysource": "7.0.0-alpha.18", - "@storybook/addon-viewport": "7.0.0-alpha.18", - "@storybook/addons": "7.0.0-alpha.18", + "@storybook/addon-a11y": "7.0.0-alpha.23", + "@storybook/addon-actions": "7.0.0-alpha.23", + "@storybook/addon-backgrounds": "7.0.0-alpha.23", + "@storybook/addon-controls": "7.0.0-alpha.23", + "@storybook/addon-docs": "7.0.0-alpha.23", + "@storybook/addon-highlight": "7.0.0-alpha.23", + "@storybook/addon-interactions": "7.0.0-alpha.23", + "@storybook/addon-links": "7.0.0-alpha.23", + "@storybook/addon-storyshots": "7.0.0-alpha.23", + "@storybook/addon-storysource": "7.0.0-alpha.23", + "@storybook/addon-viewport": "7.0.0-alpha.23", + "@storybook/addons": "7.0.0-alpha.23", "@storybook/jest": "^0.0.10", - "@storybook/source-loader": "7.0.0-alpha.18", + "@storybook/source-loader": "7.0.0-alpha.23", "@storybook/testing-library": "0.0.14-next.0", - "@storybook/vue": "7.0.0-alpha.18", - "@storybook/vue-webpack5": "7.0.0-alpha.18", + "@storybook/vue": "7.0.0-alpha.23", + "@storybook/vue-webpack5": "7.0.0-alpha.23", "@vue/babel-preset-jsx": "^1.2.4", "babel-loader": "^8.2.5", "cross-env": "^7.0.3", "file-loader": "^6.2.0", "prop-types": "^15.7.2", - "storybook": "7.0.0-alpha.18", + "storybook": "7.0.0-alpha.23", "svg-url-loader": "^7.1.1", "vue-loader": "^15.9.6", "vue-style-loader": "^4.1.3", diff --git a/code/examples/web-components-kitchen-sink/package.json b/code/examples/web-components-kitchen-sink/package.json index c58271a52225..9e38870d6675 100644 --- a/code/examples/web-components-kitchen-sink/package.json +++ b/code/examples/web-components-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "web-components-kitchen-sink", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "private": true, "description": "", "keywords": [], diff --git a/code/frameworks/angular/README.md b/code/frameworks/angular/README.md index f18b4cdfb590..ceb998025f85 100644 --- a/code/frameworks/angular/README.md +++ b/code/frameworks/angular/README.md @@ -12,7 +12,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-angular-app -npx sb init +npx storybook init ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index d7cf5c28e966..39bbe18c0394 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", @@ -34,19 +34,19 @@ "prepare": "node ../../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "7.0.0-alpha.18", - "@storybook/api": "7.0.0-alpha.18", - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/core-client": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", - "@storybook/core-server": "7.0.0-alpha.18", + "@storybook/addons": "7.0.0-alpha.23", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/core-client": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", + "@storybook/core-server": "7.0.0-alpha.23", "@storybook/csf": "0.0.2--canary.0899bb7.0", - "@storybook/docs-tools": "7.0.0-alpha.18", - "@storybook/node-logger": "7.0.0-alpha.18", + "@storybook/docs-tools": "7.0.0-alpha.23", + "@storybook/node-logger": "7.0.0-alpha.23", "@storybook/semver": "^7.3.2", - "@storybook/store": "7.0.0-alpha.18", + "@storybook/store": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "@types/react": "^16.14.23", "@types/react-dom": "^16.9.14", @@ -128,5 +128,5 @@ "access": "public" }, "builders": "dist/types/builders/builders.json", - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/angular/template/components/button.component.ts b/code/frameworks/angular/template/components/button.component.ts new file mode 100644 index 000000000000..3d0efd6af2f3 --- /dev/null +++ b/code/frameworks/angular/template/components/button.component.ts @@ -0,0 +1,53 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'storybook-button', + template: ` `, + styleUrls: ['./button.css'], +}) +export default class ButtonComponent { + /** + * Is this the principal call to action on the page? + */ + @Input() + primary = false; + + /** + * What background color to use + */ + @Input() + backgroundColor?: string; + + /** + * How large should the button be? + */ + @Input() + size: 'small' | 'medium' | 'large' = 'medium'; + + /** + * Button contents + * + * @required + */ + @Input() + label = 'Button'; + + /** + * Optional click handler + */ + @Output() + onClick = new EventEmitter(); + + public get classes(): string[] { + const mode = this.primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + + return ['storybook-button', `storybook-button--${this.size}`, mode]; + } +} diff --git a/code/frameworks/angular/template/components/button.css b/code/frameworks/angular/template/components/button.css new file mode 100644 index 000000000000..dc91dc76370b --- /dev/null +++ b/code/frameworks/angular/template/components/button.css @@ -0,0 +1,30 @@ +.storybook-button { + font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 700; + border: 0; + border-radius: 3em; + cursor: pointer; + display: inline-block; + line-height: 1; +} +.storybook-button--primary { + color: white; + background-color: #1ea7fd; +} +.storybook-button--secondary { + color: #333; + background-color: transparent; + box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset; +} +.storybook-button--small { + font-size: 12px; + padding: 10px 16px; +} +.storybook-button--medium { + font-size: 14px; + padding: 11px 20px; +} +.storybook-button--large { + font-size: 16px; + padding: 12px 24px; +} diff --git a/code/frameworks/angular/template/components/index.js b/code/frameworks/angular/template/components/index.js new file mode 100644 index 000000000000..5ae9ef153d83 --- /dev/null +++ b/code/frameworks/angular/template/components/index.js @@ -0,0 +1,5 @@ +import globalThis from 'global'; + +import Button from './button.component'; + +globalThis.Components = { Button }; diff --git a/code/frameworks/angular/template/stories/child.component.ts b/code/frameworks/angular/template/stories/child.component.ts new file mode 100644 index 000000000000..4666ec952ad1 --- /dev/null +++ b/code/frameworks/angular/template/stories/child.component.ts @@ -0,0 +1,20 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'child-component', + template: ` + Child
+ Input text: {{ childText }}
+ Output :
+ Private text: {{ childPrivateText }}
+ `, +}) +export default class ChildComponent { + @Input() + childText = ''; + + childPrivateText = ''; + + @Output() + onClickChild = new EventEmitter(); +} diff --git a/code/frameworks/angular/template/stories/decorators.stories.ts b/code/frameworks/angular/template/stories/decorators.stories.ts new file mode 100644 index 000000000000..1f4b61b9bec9 --- /dev/null +++ b/code/frameworks/angular/template/stories/decorators.stories.ts @@ -0,0 +1,117 @@ +// your-component.stories.ts + +import { componentWrapperDecorator, Meta, moduleMetadata } from '@storybook/angular'; +import ChildComponent from './child.component'; +import ParentComponent from './parent.component'; + +export default { + title: 'Core / Decorators / ComponentWrapperDecorator', + component: ChildComponent, + decorators: [ + componentWrapperDecorator( + (story) => `Grandparent
${story}
` + ), + ], + args: { childText: 'Child text', childPrivateText: 'Child private text' }, + argTypes: { onClickChild: { action: 'onClickChild' } }, +} as Meta; + +export const WithTemplate = (args) => ({ + template: `Child Template`, + props: { + ...args, + }, +}); + +export const WithComponent = (args) => ({ + props: { + ...args, + }, +}); + +export const WithLegacyComponent = (args) => ({ + component: ChildComponent, + props: { + ...args, + }, +}); + +export const WithComponentWrapperDecorator = (args) => ({ + component: ChildComponent, + props: { + ...args, + }, +}); +WithComponentWrapperDecorator.decorators = [ + moduleMetadata({ declarations: [ParentComponent] }), + componentWrapperDecorator(ParentComponent), +]; + +export const WithComponentWrapperDecoratorAndProps = (args) => ({ + component: ChildComponent, + props: { + ...args, + }, +}); +WithComponentWrapperDecoratorAndProps.decorators = [ + moduleMetadata({ declarations: [ParentComponent] }), + componentWrapperDecorator(ParentComponent, { + parentText: 'Parent text', + onClickParent: () => { + console.log('onClickParent'); + }, + }), +]; + +export const WithComponentWrapperDecoratorAndArgs = (args) => ({ + component: ChildComponent, + props: { + ...args, + }, +}); +WithComponentWrapperDecoratorAndArgs.argTypes = { + parentText: { control: { type: 'text' } }, + onClickParent: { action: 'onClickParent' }, +}; +WithComponentWrapperDecoratorAndArgs.decorators = [ + moduleMetadata({ declarations: [ParentComponent] }), + componentWrapperDecorator(ParentComponent, ({ args }) => ({ + parentText: args.parentText, + onClickParent: args.onClickParent, + })), +]; + +export const WithCustomDecorator = (args) => ({ + template: `Child Template`, + props: { + ...args, + }, +}); +WithCustomDecorator.decorators = [ + (storyFunc) => { + const story = storyFunc(); + + return { + ...story, + template: `Custom Decorator
${story.template}
`, + }; + }, +]; + +export const AngularLegacyRendering = (args) => ({ + template: `Child Template`, + props: { + ...args, + }, +}); +AngularLegacyRendering.parameters = { angularLegacyRendering: true }; +AngularLegacyRendering.decorators = [ + (storyFunc) => { + const story = storyFunc(); + + return { + ...story, + template: `Custom Decorator
${story.template}
`, + }; + }, +]; diff --git a/code/frameworks/angular/template/stories/parent.component.ts b/code/frameworks/angular/template/stories/parent.component.ts new file mode 100644 index 000000000000..f49ce1bb1873 --- /dev/null +++ b/code/frameworks/angular/template/stories/parent.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'parent-component', + template: ` + Parent
+ Input text: {{ parentText }}
+ Output :
+
+ `, +}) +export default class ParentComponent { + @Input() + parentText = ''; + + @Output() + onClickParent = new EventEmitter(); +} diff --git a/code/frameworks/ember/README.md b/code/frameworks/ember/README.md index 95b842a85ad8..f15503cd24ca 100644 --- a/code/frameworks/ember/README.md +++ b/code/frameworks/ember/README.md @@ -12,7 +12,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-ember-app -npx sb init +npx storybook init ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index 0e73fca8fc47..b0c91e79887f 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/main/frameworks/ember", "bugs": { @@ -30,11 +30,11 @@ "prepare": "node ../../../scripts/prepare.js" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-client": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/docs-tools": "7.0.0-alpha.18", - "@storybook/store": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-client": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/docs-tools": "7.0.0-alpha.23", + "@storybook/store": "7.0.0-alpha.23", "core-js": "^3.8.2", "global": "^4.4.0", "react": "16.14.0", @@ -58,5 +58,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/html-webpack5/README.md b/code/frameworks/html-webpack5/README.md index e898ba689536..d18efbcb9829 100644 --- a/code/frameworks/html-webpack5/README.md +++ b/code/frameworks/html-webpack5/README.md @@ -14,7 +14,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-app -npx sb init -t html +npx storybook init -t html ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index 41cc1e99e04e..acd01d03e28e 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -50,10 +50,10 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/html": "7.0.0-alpha.18", - "@storybook/preset-html-webpack": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/html": "7.0.0-alpha.23", + "@storybook/preset-html-webpack": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -79,5 +79,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/preact-webpack5/README.md b/code/frameworks/preact-webpack5/README.md index 2bbdd89def68..60b338b400b2 100644 --- a/code/frameworks/preact-webpack5/README.md +++ b/code/frameworks/preact-webpack5/README.md @@ -12,7 +12,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-preact-app -npx sb init +npx storybook init ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index ccd363007808..286048776544 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" @@ -50,10 +50,10 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/preact": "7.0.0-alpha.18", - "@storybook/preset-preact-webpack": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/preact": "7.0.0-alpha.23", + "@storybook/preset-preact-webpack": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "core-js": "^3.8.2", "react": "16.14.0", @@ -80,5 +80,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/react-webpack5/README.md b/code/frameworks/react-webpack5/README.md index 60379031702d..6aee8981736d 100644 --- a/code/frameworks/react-webpack5/README.md +++ b/code/frameworks/react-webpack5/README.md @@ -12,7 +12,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-react-app -npx sb init +npx storybook init ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index 468d984bad61..d6e17ae59de3 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -51,9 +51,9 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/preset-react-webpack": "7.0.0-alpha.18", - "@storybook/react": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/preset-react-webpack": "7.0.0-alpha.23", + "@storybook/react": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "core-js": "^3.8.2" }, @@ -87,5 +87,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/server-webpack5/README.md b/code/frameworks/server-webpack5/README.md index 28e5e50205aa..160b17845323 100644 --- a/code/frameworks/server-webpack5/README.md +++ b/code/frameworks/server-webpack5/README.md @@ -14,7 +14,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-app -npx sb init -t server +npx storybook init -t server ``` To configure the server that Storybook will connect to, export a global parameter `parameters.server.url` in `.storybook/preview.js`: diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index 5522e4cf8b23..9e20a2a97374 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -50,10 +50,10 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/preset-server-webpack": "7.0.0-alpha.18", - "@storybook/server": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/preset-server-webpack": "7.0.0-alpha.23", + "@storybook/server": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "core-js": "^3.8.2", "react": "16.14.0", @@ -75,5 +75,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/svelte-webpack5/README.md b/code/frameworks/svelte-webpack5/README.md index 49bbb60840e3..2c1279392720 100644 --- a/code/frameworks/svelte-webpack5/README.md +++ b/code/frameworks/svelte-webpack5/README.md @@ -12,7 +12,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-svelte-app -npx sb init +npx storybook init ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 8b7df1b4c83b..07f7f2559ed7 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -51,10 +51,10 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/preset-svelte-webpack": "7.0.0-alpha.18", - "@storybook/svelte": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/preset-svelte-webpack": "7.0.0-alpha.23", + "@storybook/svelte": "7.0.0-alpha.23", "core-js": "^3.8.2", "react": "16.14.0", "react-dom": "16.14.0" @@ -82,5 +82,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/vue-webpack5/README.md b/code/frameworks/vue-webpack5/README.md index 33ae491f8f41..e9ddd06ffa95 100644 --- a/code/frameworks/vue-webpack5/README.md +++ b/code/frameworks/vue-webpack5/README.md @@ -12,7 +12,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-vue-app -npx sb init +npx storybook init ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/vue-webpack5/package.json b/code/frameworks/vue-webpack5/package.json index baf1af65002c..d6d925297e5c 100644 --- a/code/frameworks/vue-webpack5/package.json +++ b/code/frameworks/vue-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for Vue: Develop Vue Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -50,10 +50,10 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/preset-vue-webpack": "7.0.0-alpha.18", - "@storybook/vue": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/preset-vue-webpack": "7.0.0-alpha.23", + "@storybook/vue": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "core-js": "^3.8.2", "react": "16.14.0", @@ -86,5 +86,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/vue3-webpack5/README.md b/code/frameworks/vue3-webpack5/README.md index b0fafaff0295..8ce5b4dafb8d 100644 --- a/code/frameworks/vue3-webpack5/README.md +++ b/code/frameworks/vue3-webpack5/README.md @@ -12,7 +12,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-vue3-app -npx sb init +npx storybook init ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index 3d368db14b76..6c79da4ae0b7 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -50,10 +50,10 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/preset-vue3-webpack": "7.0.0-alpha.18", - "@storybook/vue3": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/preset-vue3-webpack": "7.0.0-alpha.23", + "@storybook/vue3": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "core-js": "^3.8.2", "react": "16.14.0", @@ -83,5 +83,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/frameworks/web-components-webpack5/README.md b/code/frameworks/web-components-webpack5/README.md index e07aad25f2bb..2239de4e631d 100644 --- a/code/frameworks/web-components-webpack5/README.md +++ b/code/frameworks/web-components-webpack5/README.md @@ -14,7 +14,7 @@ So you can develop UI components in isolation without worrying about app specifi ```sh cd my-app -npx sb init -t web_components +npx storybook init -t web_components ``` For more information visit: [storybook.js.org](https://storybook.js.org) diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index 5aa70e053955..3c4cab8ccd91 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-webpack5", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit-html", @@ -53,10 +53,10 @@ }, "dependencies": { "@babel/preset-env": "^7.12.11", - "@storybook/builder-webpack5": "7.0.0-alpha.18", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/preset-web-components-webpack": "7.0.0-alpha.18", - "@storybook/web-components": "7.0.0-alpha.18", + "@storybook/builder-webpack5": "7.0.0-alpha.23", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/preset-web-components-webpack": "7.0.0-alpha.23", + "@storybook/web-components": "7.0.0-alpha.23", "@types/node": "^14.14.20 || ^16.0.0", "core-js": "^3.8.2", "react": "16.14.0", @@ -82,5 +82,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/lerna.json b/code/lerna.json index ddd8bede1d8b..bf295ef75c2c 100644 --- a/code/lerna.json +++ b/code/lerna.json @@ -2,5 +2,5 @@ "npmClient": "yarn", "useWorkspaces": true, "registry": "https://registry.npmjs.org", - "version": "7.0.0-alpha.18" + "version": "7.0.0-alpha.23" } diff --git a/code/lib/addons/package.json b/code/lib/addons/package.json index 05f986a0407f..187113cf715d 100644 --- a/code/lib/addons/package.json +++ b/code/lib/addons/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addons", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook addons store", "keywords": [ "storybook" @@ -34,13 +34,13 @@ "prepare": "node ../../../scripts/prepare.js" }, "dependencies": { - "@storybook/api": "7.0.0-alpha.18", - "@storybook/channels": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/channels": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", "@storybook/csf": "0.0.2--canary.0899bb7.0", - "@storybook/router": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/router": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "@types/webpack-env": "^1.16.4", "core-js": "^3.8.2", "global": "^4.4.0" @@ -52,5 +52,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/lib/api/package.json b/code/lib/api/package.json index 5b9d75e73951..1c9b2febb979 100644 --- a/code/lib/api/package.json +++ b/code/lib/api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/api", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Core Storybook API & Context", "keywords": [ "storybook" @@ -32,13 +32,13 @@ "prepare": "node ../../../scripts/prepare.js" }, "dependencies": { - "@storybook/channels": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", + "@storybook/channels": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", "@storybook/csf": "0.0.2--canary.0899bb7.0", - "@storybook/router": "7.0.0-alpha.18", + "@storybook/router": "7.0.0-alpha.23", "@storybook/semver": "^7.3.2", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/theming": "7.0.0-alpha.23", "core-js": "^3.8.2", "dequal": "^2.0.2", "global": "^4.4.0", @@ -65,5 +65,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/lib/api/src/modules/layout.ts b/code/lib/api/src/modules/layout.ts index 0cd7c12f608e..36991ef2e617 100644 --- a/code/lib/api/src/modules/layout.ts +++ b/code/lib/api/src/modules/layout.ts @@ -1,7 +1,7 @@ import global from 'global'; import pick from 'lodash/pick'; import { dequal as deepEqual } from 'dequal'; -import { create } from '@storybook/theming'; +import { create } from '@storybook/theming/create'; import { SET_CONFIG } from '@storybook/core-events'; import type { ThemeVars } from '@storybook/theming'; import { once } from '@storybook/client-logger'; diff --git a/code/lib/api/src/modules/stories.ts b/code/lib/api/src/modules/stories.ts index ea4215ebcaec..ef1d5aa68641 100644 --- a/code/lib/api/src/modules/stories.ts +++ b/code/lib/api/src/modules/stories.ts @@ -162,8 +162,6 @@ export const init: ModuleFn = ({ if (parameters) { return parameterName ? parameters[parameterName] : parameters; } - - return {}; } return null; diff --git a/code/lib/api/src/version.ts b/code/lib/api/src/version.ts index 254f721cfecb..393ae7f6556e 100644 --- a/code/lib/api/src/version.ts +++ b/code/lib/api/src/version.ts @@ -1 +1 @@ -export const version = '7.0.0-alpha.18'; +export const version = '7.0.0-alpha.23'; diff --git a/code/lib/blocks/package.json b/code/lib/blocks/package.json index 80122fd35435..1f21556295cb 100644 --- a/code/lib/blocks/package.json +++ b/code/lib/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook Doc Blocks", "keywords": [ "storybook" @@ -41,16 +41,16 @@ "prepare": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/api": "7.0.0-alpha.18", - "@storybook/channels": "7.0.0-alpha.18", - "@storybook/client-logger": "7.0.0-alpha.18", - "@storybook/components": "7.0.0-alpha.18", - "@storybook/core-events": "7.0.0-alpha.18", + "@storybook/api": "7.0.0-alpha.23", + "@storybook/channels": "7.0.0-alpha.23", + "@storybook/client-logger": "7.0.0-alpha.23", + "@storybook/components": "7.0.0-alpha.23", + "@storybook/core-events": "7.0.0-alpha.23", "@storybook/csf": "0.0.2--canary.0899bb7.0", - "@storybook/docs-tools": "7.0.0-alpha.18", - "@storybook/preview-web": "7.0.0-alpha.18", - "@storybook/store": "7.0.0-alpha.18", - "@storybook/theming": "7.0.0-alpha.18", + "@storybook/docs-tools": "7.0.0-alpha.23", + "@storybook/preview-web": "7.0.0-alpha.23", + "@storybook/store": "7.0.0-alpha.23", + "@storybook/theming": "7.0.0-alpha.23", "color-convert": "^2.0.1", "core-js": "^3.8.2", "dequal": "^2.0.2", @@ -64,7 +64,7 @@ "util-deprecate": "^1.0.2" }, "devDependencies": { - "@storybook/addons": "7.0.0-alpha.18" + "@storybook/addons": "7.0.0-alpha.23" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" @@ -77,5 +77,5 @@ "./src/index.ts" ] }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/lib/blocks/src/components/Preview.stories.tsx b/code/lib/blocks/src/components/Preview.stories.tsx index 6e4c379596e5..a6555636ab32 100644 --- a/code/lib/blocks/src/components/Preview.stories.tsx +++ b/code/lib/blocks/src/components/Preview.stories.tsx @@ -188,7 +188,7 @@ export const WithAdditionalActions = () => ( title: 'Open on GitHub', onClick: () => { globalWindow.location.href = - 'https://github.com/storybookjs/storybook/blob/next/lib/components/src/blocks/Preview.stories.tsx#L140-L147'; + 'https://github.com/storybookjs/storybook/blob/next/code/lib/blocks/src/components/Preview.stories.tsx#L165-L186'; }, }, ]} diff --git a/code/lib/builder-manager/package.json b/code/lib/builder-manager/package.json index ecb0811946d3..c8e6cb127058 100644 --- a/code/lib/builder-manager/package.json +++ b/code/lib/builder-manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-manager", - "version": "7.0.0-alpha.18", + "version": "7.0.0-alpha.23", "description": "Storybook manager builder", "keywords": [ "storybook" @@ -42,9 +42,9 @@ }, "dependencies": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@storybook/core-common": "7.0.0-alpha.18", - "@storybook/node-logger": "7.0.0-alpha.18", - "@storybook/ui": "7.0.0-alpha.18", + "@storybook/core-common": "7.0.0-alpha.23", + "@storybook/node-logger": "7.0.0-alpha.23", + "@storybook/ui": "7.0.0-alpha.23", "@types/ejs": "^3.1.1", "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", "browser-assert": "^1.2.1", @@ -54,7 +54,6 @@ "esbuild-plugin-alias": "^0.2.1", "express": "^4.17.1", "fs-extra": "^9.0.1", - "readdirp": "^3.6.0", "rollup-plugin-node-polyfills": "^0.2.1" }, "devDependencies": { @@ -69,5 +68,5 @@ ], "platform": "node" }, - "gitHead": "bd59f1eef0f644175abdb0d9873ed0553f431f53" + "gitHead": "0900e20acfbc12551c6a3f788b8de5dd6af5f80a" } diff --git a/code/lib/builder-manager/src/index.ts b/code/lib/builder-manager/src/index.ts index f857728d2ed6..9b1d96323265 100644 --- a/code/lib/builder-manager/src/index.ts +++ b/code/lib/builder-manager/src/index.ts @@ -19,11 +19,12 @@ import { ManagerBuilder, StarterFunction, } from './types'; -import { readDeep } from './utils/directory'; import { getData } from './utils/data'; import { safeResolve } from './utils/safeResolve'; +import { readOrderedFiles } from './utils/files'; -let compilation: Compilation; +// eslint-disable-next-line import/no-mutable-exports +export let compilation: Compilation; let asyncIterator: ReturnType | ReturnType; export const getConfig: ManagerBuilder['getConfig'] = async (options) => { @@ -38,6 +39,7 @@ export const getConfig: ManagerBuilder['getConfig'] = async (options) => { : addonsEntryPoints, outdir: join(options.outputDir || './', 'sb-addons'), format: 'esm', + write: false, outExtension: { '.js': '.mjs' }, loader: { '.js': 'jsx', @@ -118,7 +120,7 @@ const starter: StarterFunction = async function* starterGeneratorFn({ router.use(`/sb-addons`, express.static(addonsDir)); router.use(`/sb-manager`, express.static(coreDirOrigin)); - const addonFiles = readDeep(addonsDir); + const { cssFiles, jsFiles } = await readOrderedFiles(addonsDir); yield; @@ -126,7 +128,8 @@ const starter: StarterFunction = async function* starterGeneratorFn({ template, title, customHead, - addonFiles, + cssFiles, + jsFiles, features, refs, logLevel, @@ -182,13 +185,16 @@ const builder: BuilderFunction = async function* builderGeneratorFn({ startTime, yield; const managerFiles = copy(coreDirOrigin, coreDirTarget); - const addonFiles = readDeep(addonsDir); + const { cssFiles, jsFiles } = await readOrderedFiles(addonsDir); + + yield; const html = await renderHTML( template, title, customHead, - addonFiles, + cssFiles, + jsFiles, features, refs, logLevel, @@ -196,8 +202,6 @@ const builder: BuilderFunction = async function* builderGeneratorFn({ startTime, options ); - yield; - await Promise.all([ // writeFile(join(options.outputDir, 'index.html'), html), diff --git a/code/lib/builder-manager/src/types.ts b/code/lib/builder-manager/src/types.ts index c14c82e13bf2..dfa97b6c02aa 100644 --- a/code/lib/builder-manager/src/types.ts +++ b/code/lib/builder-manager/src/types.ts @@ -12,7 +12,10 @@ export type WithRequiredProperty = Type & [Property in Key]-?: Type[Property]; }; -export type ManagerBuilder = Builder, Stats>; +export type ManagerBuilder = Builder< + WithRequiredProperty & { entryPoints: string[] }, + Stats +>; export type Unpromise> = T extends Promise ? U : never; export type BuilderStartOptions = Parameters['0']; diff --git a/code/lib/builder-manager/src/utils/directory.ts b/code/lib/builder-manager/src/utils/directory.ts deleted file mode 100644 index a834ce1410b5..000000000000 --- a/code/lib/builder-manager/src/utils/directory.ts +++ /dev/null @@ -1,12 +0,0 @@ -import readdirp, { ReaddirpOptions } from 'readdirp'; - -const defaults = { - fileFilter: ['*.mjs', '*.css'], - lstat: false, - type: 'files', - depth: 10, -} as ReaddirpOptions; - -export const readDeep = async (dir: string, options: ReaddirpOptions = {}) => { - return readdirp.promise(dir, { ...defaults, ...options }); -}; diff --git a/code/lib/builder-manager/src/utils/files.ts b/code/lib/builder-manager/src/utils/files.ts new file mode 100644 index 000000000000..56c6204ead56 --- /dev/null +++ b/code/lib/builder-manager/src/utils/files.ts @@ -0,0 +1,15 @@ +import { writeFile, ensureFile } from 'fs-extra'; +import { compilation } from '../index'; + +export async function readOrderedFiles(addonsDir: string) { + const files = await Promise.all( + compilation?.outputFiles?.map(async (file) => { + await ensureFile(file.path).then(() => writeFile(file.path, file.contents)); + return file.path.replace(addonsDir, './sb-addons'); + }) || [] + ); + + const jsFiles = files.filter((file) => file.endsWith('.mjs')); + const cssFiles = files.filter((file) => file.endsWith('.css')); + return { cssFiles, jsFiles }; +} diff --git a/code/lib/builder-manager/src/utils/template.ts b/code/lib/builder-manager/src/utils/template.ts index dca1eab9023b..b9d619ee701e 100644 --- a/code/lib/builder-manager/src/utils/template.ts +++ b/code/lib/builder-manager/src/utils/template.ts @@ -5,8 +5,6 @@ import { render } from 'ejs'; import type { DocsOptions, Options, Ref } from '@storybook/core-common'; -import { readDeep } from './directory'; - const interpolate = (string: string, data: Record = {}) => Object.entries(data).reduce((acc, [k, v]) => acc.replace(new RegExp(`%${k}%`, 'g'), v), string); @@ -52,7 +50,8 @@ export const renderHTML = async ( template: Promise, title: Promise, customHead: Promise, - files: ReturnType, + cssFiles: string[], + jsFiles: string[], features: Promise>, refs: Promise>, logLevel: Promise, @@ -62,14 +61,10 @@ export const renderHTML = async ( const customHeadRef = await customHead; const titleRef = await title; const templateRef = await template; - const filesRef = await files; return render(templateRef, { title: titleRef ? `${titleRef} - Storybook` : 'Storybook', - files: { - js: filesRef.filter((f) => f.path.match(/\.mjs$/)).map((f) => `./sb-addons/${f.path}`), - css: filesRef.filter((f) => f.path.match(/\.css$/)).map((f) => `./sb-addons/${f.path}`), - }, + files: { js: jsFiles, css: cssFiles }, globals: { FEATURES: JSON.stringify(await features, null, 2), REFS: JSON.stringify(await refs, null, 2), diff --git a/code/lib/builder-manager/templates/template.ejs b/code/lib/builder-manager/templates/template.ejs index 046d109199ee..1eaad092f2a9 100644 --- a/code/lib/builder-manager/templates/template.ejs +++ b/code/lib/builder-manager/templates/template.ejs @@ -2,13 +2,14 @@ + <%= typeof title !== 'undefined'? title : 'Storybook'%> <% if (typeof head !== 'undefined') { %> <%- head %> <% } %> - + + + + + + + + +