diff --git a/CHANGELOG.md b/CHANGELOG.md index 649310bf1c11..6a1978abc0d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## 8.0.0 + +#### Storybook 8.0 is here + +It brings major improvements to Storybook's feature set for testing and documentation, with strengthened framework support across React, Vue, Angular, web-components, Svelte, and more. + +- ๐Ÿฉป Built-in visual testing +- โš›๏ธ React Server Component support +- ๐ŸŽ›๏ธ Improved controls for React and Vue projects +- โšก๏ธ Improved Vite architecture, Vitest testing, and Vite 5 support +- ๐Ÿงช 2-4x faster Storybooks for testing +- โœจ Refreshed desktop UI +- ๐Ÿ“ฒ Rebuilt mobile UX +- ๐Ÿ™…โ€โ™€๏ธ No more React requirement in non-React projects + +Please checkout our [Migration Guide](https://storybook.js.org/docs/8.0/migration-guide) to upgrade from earlier versions of Storybook. To see a comprehensive list of changes that went into 8.0, you can refer to the [8.0 prerelease changelogs](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.prerelease.md). + ## 7.6.17 - Addon-docs: Fix Table of Contents heading leak - [#23677](https://github.com/storybookjs/storybook/pull/23677), thanks [@vmizg](https://github.com/vmizg)! @@ -105,91 +122,91 @@ Storybook 7.6 is here with increased performance and much more! List of all updates - - Actions: Attach spies on actions across stories when defined in meta - [#24451](https://github.com/storybookjs/storybook/pull/24451), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Actions: Fix `@storybook/core-events/preview-errors` dependency missing for Yarn PnP - [#24973](https://github.com/storybookjs/storybook/pull/24973), thanks [@JReinhold](https://github.com/JReinhold)! - - Actions: Fix missing crypto module crashing React Native - [#24546](https://github.com/storybookjs/storybook/pull/24546), thanks [@dannyhw](https://github.com/dannyhw)! - - Actions: Warn on implicit actions - [#24856](https://github.com/storybookjs/storybook/pull/24856), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Addon A11y: Avoid CSP issue - [#24477](https://github.com/storybookjs/storybook/pull/24477), thanks [@Marklb](https://github.com/Marklb)! - - Addon: Move Visual Test addon to the code directory - [#24771](https://github.com/storybookjs/storybook/pull/24771), thanks [@cdedreuille](https://github.com/cdedreuille)! - - Addons, core: Make `react` and Storybook packages `devDependencies` where possible - [#24676](https://github.com/storybookjs/storybook/pull/24676), thanks [@JReinhold](https://github.com/JReinhold)! - - Addons, core: Make `react` and Storybook packages `devDependencies` where possible - ATTEMPT 2 - [#24834](https://github.com/storybookjs/storybook/pull/24834), thanks [@JReinhold](https://github.com/JReinhold)! - - Angular: Add source-map option to builder - [#24466](https://github.com/storybookjs/storybook/pull/24466), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Angular: Handle nested module metadata - [#24798](https://github.com/storybookjs/storybook/pull/24798), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Angular: Include object configured styles - [#24768](https://github.com/storybookjs/storybook/pull/24768), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Babel: Update all @babel/* dependencies - [#24610](https://github.com/storybookjs/storybook/pull/24610), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - CLI: Add "doctor" command - [#22236](https://github.com/storybookjs/storybook/pull/22236), thanks [@yannbf](https://github.com/yannbf)! - - CLI: Add @storybook/addon-designs to non-core list - [#24507](https://github.com/storybookjs/storybook/pull/24507), thanks [@yannbf](https://github.com/yannbf)! - - CLI: Ensure errors with opening the browser are caught - [#24668](https://github.com/storybookjs/storybook/pull/24668), thanks [@xueyawei](https://github.com/xueyawei)! - - CLI: Ignore `addon-onboarding` when checking versions - [#24634](https://github.com/storybookjs/storybook/pull/24634), thanks [@JReinhold](https://github.com/JReinhold)! - - CLI: Use @storybook/test in template stories - [#24393](https://github.com/storybookjs/storybook/pull/24393), thanks [@yannbf](https://github.com/yannbf)! - - Controls: Improve accessibility of BooleanControl for screen readers - [#24418](https://github.com/storybookjs/storybook/pull/24418), thanks [@danielmarcano](https://github.com/danielmarcano)! - - Core-Server: Ignore all node_module folders for watchpack - [#24553](https://github.com/storybookjs/storybook/pull/24553), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Core: Add deprecation notice for Vite + CommonJS - [#23950](https://github.com/storybookjs/storybook/pull/23950), thanks [@JReinhold](https://github.com/JReinhold)! - - Core: Detect no matching export error in storybook start and build - [#24877](https://github.com/storybookjs/storybook/pull/24877), thanks [@yannbf](https://github.com/yannbf)! - - Core: Fix `useStoryPrepared` hook failing with `undefined` data - [#22631](https://github.com/storybookjs/storybook/pull/22631), thanks [@SpookyJelly](https://github.com/SpookyJelly)! - - Core: Fix pnp support when cache dir is outside working dir - [#24572](https://github.com/storybookjs/storybook/pull/24572), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Core: Fix post message channel location.search access for React Native - [#24545](https://github.com/storybookjs/storybook/pull/24545), thanks [@dannyhw](https://github.com/dannyhw)! - - Core: Gracefully handle error when parsing preview.js file - [#24858](https://github.com/storybookjs/storybook/pull/24858), thanks [@yannbf](https://github.com/yannbf)! - - Core: Make warnOnIncompatibleAddons fault-tolerant - [#24880](https://github.com/storybookjs/storybook/pull/24880), thanks [@taozhou-glean](https://github.com/taozhou-glean)! - - Dependencies: Fix Yarn 4 failing to install due to jscodeshift dependency issue - [#24914](https://github.com/storybookjs/storybook/pull/24914), thanks [@samvv](https://github.com/samvv)! - - Dependencies: Update @babel/traverse and @babel/core to fix vulnerability - [#24670](https://github.com/storybookjs/storybook/pull/24670), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Dependencies: Update browserify-sign transitive dependency - [#24674](https://github.com/storybookjs/storybook/pull/24674), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Dependencies: Update jscodeshift to v0.15.1 - [#24882](https://github.com/storybookjs/storybook/pull/24882), thanks [@epreston](https://github.com/epreston)! - - Dependencies: Update nx dependencies to v17 - [#24671](https://github.com/storybookjs/storybook/pull/24671), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Doc Blocks: Add support for `of` prop to `Primary` block - [#23849](https://github.com/storybookjs/storybook/pull/23849), thanks [@Wilson2k](https://github.com/Wilson2k)! - - Doc Blocks: Remove `defaultProps` in `Stories` block - [#24506](https://github.com/storybookjs/storybook/pull/24506), thanks [@WouterK12](https://github.com/WouterK12)! - - Docs: Changes corresponding to docs design updates - [#24925](https://github.com/storybookjs/storybook/pull/24925), thanks [@kylegach](https://github.com/kylegach)! - - Maintenance: Split renderers preview entrypoints - [#24623](https://github.com/storybookjs/storybook/pull/24623), thanks [@ndelangen](https://github.com/ndelangen)! - - Manager: Update `store.settings.lastTrackedStoryId` - [#24115](https://github.com/storybookjs/storybook/pull/24115), thanks [@rashidshamloo](https://github.com/rashidshamloo)! - - ManagerAPI: Fix setting status without index, crashes storybook - [#24866](https://github.com/storybookjs/storybook/pull/24866), thanks [@ndelangen](https://github.com/ndelangen)! - - ManagerBuilder: Fix `"type": "commonjs"` compatibility - [#24534](https://github.com/storybookjs/storybook/pull/24534), thanks [@ndelangen](https://github.com/ndelangen)! - - Next.js: Add avif support - [#24611](https://github.com/storybookjs/storybook/pull/24611), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Next.js: Add back image context CommonJS export - [#24885](https://github.com/storybookjs/storybook/pull/24885), thanks [@martinnabhan](https://github.com/martinnabhan)! - - Next.js: Add experimental SWC support - [#24852](https://github.com/storybookjs/storybook/pull/24852), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Next.js: Fix Fast Refresh config for SWC mode - [#24991](https://github.com/storybookjs/storybook/pull/24991), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Next.js: Fix forwarding ref for Image component - [#24648](https://github.com/storybookjs/storybook/pull/24648), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Next.js: Fix import path in swc loader - [#24922](https://github.com/storybookjs/storybook/pull/24922), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Next.js: Fix react-docgen usage with preset-env settings - [#24993](https://github.com/storybookjs/storybook/pull/24993), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Next.js: Remove duplicate Fast Refresh plugin init - [#24963](https://github.com/storybookjs/storybook/pull/24963), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - React: Upgrade `react-docgen` to v7 - [#24530](https://github.com/storybookjs/storybook/pull/24530), thanks [@shilman](https://github.com/shilman)! - - ReactNative: Fix missing assert dep in docs-tools - [#24732](https://github.com/storybookjs/storybook/pull/24732), thanks [@dannyhw](https://github.com/dannyhw)! - - Svelte: Fix decorators always running twice - [#24921](https://github.com/storybookjs/storybook/pull/24921), thanks [@paoloricciuti](https://github.com/paoloricciuti)! - - Svelte: Fix source with decorators always showing the `SlotDecorator` component - [#24800](https://github.com/storybookjs/storybook/pull/24800), thanks [@JReinhold](https://github.com/JReinhold)! - - SvelteKit: Add experimental page and navigation mocking - [#24795](https://github.com/storybookjs/storybook/pull/24795), thanks [@paoloricciuti](https://github.com/paoloricciuti)! - - SvelteKit: Default to log an action for `goto`, `invalidate` and `invalidateAll` - [#24955](https://github.com/storybookjs/storybook/pull/24955), thanks [@paoloricciuti](https://github.com/paoloricciuti)! - - SWC: Add settings for react and preact - [#24805](https://github.com/storybookjs/storybook/pull/24805), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Test Build: Add env-variable support to `--test` CLI-flag - [#24862](https://github.com/storybookjs/storybook/pull/24862), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Add tests and rename to camelCase - [#24911](https://github.com/storybookjs/storybook/pull/24911), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Disable composition when `--test` is `true` - [#24799](https://github.com/storybookjs/storybook/pull/24799), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Disable docs related stuff for test builds - [#24691](https://github.com/storybookjs/storybook/pull/24691), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Disable telemetry for test builds - [#24706](https://github.com/storybookjs/storybook/pull/24706), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Test Build: Disable warnOnIncompatibleAddons - [#24797](https://github.com/storybookjs/storybook/pull/24797), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Filter out addon-docs from essentials in the test build - [#24994](https://github.com/storybookjs/storybook/pull/24994), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Test Build: Fix disabledAddons filter - [#24924](https://github.com/storybookjs/storybook/pull/24924), thanks [@IanVS](https://github.com/IanVS)! - - Test Build: Fix indexer bug - [#24890](https://github.com/storybookjs/storybook/pull/24890), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Globalize `@storybook/blocks` if `build.test.emptyBlocks` is `true` - [#24650](https://github.com/storybookjs/storybook/pull/24650), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Implement builder options for test build - [#24826](https://github.com/storybookjs/storybook/pull/24826), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Test Build: Improve config loading & naming - [#24837](https://github.com/storybookjs/storybook/pull/24837), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: No sourcemaps for test builds - [#24804](https://github.com/storybookjs/storybook/pull/24804), thanks [@ndelangen](https://github.com/ndelangen)! - - Test Build: Revert defaulting to SWC in test build, but keep using esbuild for minification - [#24843](https://github.com/storybookjs/storybook/pull/24843), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Test: Create @storybook/test package based on vitest - [#24392](https://github.com/storybookjs/storybook/pull/24392), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Test: Don\'t attach action to function mock if action was added already - [#24966](https://github.com/storybookjs/storybook/pull/24966), thanks [@tmeasday](https://github.com/tmeasday)! - - Test: Model loaders as before each and restore mocks properly - [#24948](https://github.com/storybookjs/storybook/pull/24948), thanks [@kasperpeulen](https://github.com/kasperpeulen)! - - Theming: Add theme variable to set the preview background color - [#24575](https://github.com/storybookjs/storybook/pull/24575), thanks [@JReinhold](https://github.com/JReinhold)! - - Typescript: Add \'skipCompiler\' option to TypeScript presets - [#24847](https://github.com/storybookjs/storybook/pull/24847), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - UI: Fix horizontal scroll bar in Canvas hidden by styling - [#24408](https://github.com/storybookjs/storybook/pull/24408), thanks [@yoshi2no](https://github.com/yoshi2no)! - - UI: improve A11Y remove redundant styling rules, update icon color - [#24402](https://github.com/storybookjs/storybook/pull/24402), thanks [@tolkadot](https://github.com/tolkadot)! - - UI: Logo fixed value - [#24726](https://github.com/storybookjs/storybook/pull/24726), thanks [@black-arm](https://github.com/black-arm)! - - UI: Update zIndex on NotificationList to fix the notification not being clickable in certain cases - [#24602](https://github.com/storybookjs/storybook/pull/24602), thanks [@yoshi2no](https://github.com/yoshi2no)! - - Viewport: Add newer device viewports - [#24777](https://github.com/storybookjs/storybook/pull/24777), thanks [@Tomo5524](https://github.com/Tomo5524)! - - Vite: Prevent non-deterministic build output - [#24833](https://github.com/storybookjs/storybook/pull/24833), thanks [@henkerik](https://github.com/henkerik)! - - Webpack: Add export-order-loader and remove babel-plugin-named-exports-order - [#24749](https://github.com/storybookjs/storybook/pull/24749), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Webpack: Add react-docgen loader and remove babel-plugin-react-docgen - [#24762](https://github.com/storybookjs/storybook/pull/24762), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Webpack: Fix race condition for export-order loader - [#24817](https://github.com/storybookjs/storybook/pull/24817), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Webpack: Hide critical dependency warning - [#24784](https://github.com/storybookjs/storybook/pull/24784), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Webpack: Only load babel config when babel-loader is used - [#25002](https://github.com/storybookjs/storybook/pull/25002), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - - Webpack: Resolve circular dependency and fix HMR - [#24974](https://github.com/storybookjs/storybook/pull/24974), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! - +- Actions: Attach spies on actions across stories when defined in meta - [#24451](https://github.com/storybookjs/storybook/pull/24451), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Actions: Fix `@storybook/core-events/preview-errors` dependency missing for Yarn PnP - [#24973](https://github.com/storybookjs/storybook/pull/24973), thanks [@JReinhold](https://github.com/JReinhold)! +- Actions: Fix missing crypto module crashing React Native - [#24546](https://github.com/storybookjs/storybook/pull/24546), thanks [@dannyhw](https://github.com/dannyhw)! +- Actions: Warn on implicit actions - [#24856](https://github.com/storybookjs/storybook/pull/24856), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Addon A11y: Avoid CSP issue - [#24477](https://github.com/storybookjs/storybook/pull/24477), thanks [@Marklb](https://github.com/Marklb)! +- Addon: Move Visual Test addon to the code directory - [#24771](https://github.com/storybookjs/storybook/pull/24771), thanks [@cdedreuille](https://github.com/cdedreuille)! +- Addons, core: Make `react` and Storybook packages `devDependencies` where possible - [#24676](https://github.com/storybookjs/storybook/pull/24676), thanks [@JReinhold](https://github.com/JReinhold)! +- Addons, core: Make `react` and Storybook packages `devDependencies` where possible - ATTEMPT 2 - [#24834](https://github.com/storybookjs/storybook/pull/24834), thanks [@JReinhold](https://github.com/JReinhold)! +- Angular: Add source-map option to builder - [#24466](https://github.com/storybookjs/storybook/pull/24466), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Angular: Handle nested module metadata - [#24798](https://github.com/storybookjs/storybook/pull/24798), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Angular: Include object configured styles - [#24768](https://github.com/storybookjs/storybook/pull/24768), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Babel: Update all @babel/\* dependencies - [#24610](https://github.com/storybookjs/storybook/pull/24610), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- CLI: Add "doctor" command - [#22236](https://github.com/storybookjs/storybook/pull/22236), thanks [@yannbf](https://github.com/yannbf)! +- CLI: Add @storybook/addon-designs to non-core list - [#24507](https://github.com/storybookjs/storybook/pull/24507), thanks [@yannbf](https://github.com/yannbf)! +- CLI: Ensure errors with opening the browser are caught - [#24668](https://github.com/storybookjs/storybook/pull/24668), thanks [@xueyawei](https://github.com/xueyawei)! +- CLI: Ignore `addon-onboarding` when checking versions - [#24634](https://github.com/storybookjs/storybook/pull/24634), thanks [@JReinhold](https://github.com/JReinhold)! +- CLI: Use @storybook/test in template stories - [#24393](https://github.com/storybookjs/storybook/pull/24393), thanks [@yannbf](https://github.com/yannbf)! +- Controls: Improve accessibility of BooleanControl for screen readers - [#24418](https://github.com/storybookjs/storybook/pull/24418), thanks [@danielmarcano](https://github.com/danielmarcano)! +- Core-Server: Ignore all node_module folders for watchpack - [#24553](https://github.com/storybookjs/storybook/pull/24553), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Core: Add deprecation notice for Vite + CommonJS - [#23950](https://github.com/storybookjs/storybook/pull/23950), thanks [@JReinhold](https://github.com/JReinhold)! +- Core: Detect no matching export error in storybook start and build - [#24877](https://github.com/storybookjs/storybook/pull/24877), thanks [@yannbf](https://github.com/yannbf)! +- Core: Fix `useStoryPrepared` hook failing with `undefined` data - [#22631](https://github.com/storybookjs/storybook/pull/22631), thanks [@SpookyJelly](https://github.com/SpookyJelly)! +- Core: Fix pnp support when cache dir is outside working dir - [#24572](https://github.com/storybookjs/storybook/pull/24572), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Core: Fix post message channel location.search access for React Native - [#24545](https://github.com/storybookjs/storybook/pull/24545), thanks [@dannyhw](https://github.com/dannyhw)! +- Core: Gracefully handle error when parsing preview.js file - [#24858](https://github.com/storybookjs/storybook/pull/24858), thanks [@yannbf](https://github.com/yannbf)! +- Core: Make warnOnIncompatibleAddons fault-tolerant - [#24880](https://github.com/storybookjs/storybook/pull/24880), thanks [@taozhou-glean](https://github.com/taozhou-glean)! +- Dependencies: Fix Yarn 4 failing to install due to jscodeshift dependency issue - [#24914](https://github.com/storybookjs/storybook/pull/24914), thanks [@samvv](https://github.com/samvv)! +- Dependencies: Update @babel/traverse and @babel/core to fix vulnerability - [#24670](https://github.com/storybookjs/storybook/pull/24670), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Dependencies: Update browserify-sign transitive dependency - [#24674](https://github.com/storybookjs/storybook/pull/24674), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Dependencies: Update jscodeshift to v0.15.1 - [#24882](https://github.com/storybookjs/storybook/pull/24882), thanks [@epreston](https://github.com/epreston)! +- Dependencies: Update nx dependencies to v17 - [#24671](https://github.com/storybookjs/storybook/pull/24671), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Doc Blocks: Add support for `of` prop to `Primary` block - [#23849](https://github.com/storybookjs/storybook/pull/23849), thanks [@Wilson2k](https://github.com/Wilson2k)! +- Doc Blocks: Remove `defaultProps` in `Stories` block - [#24506](https://github.com/storybookjs/storybook/pull/24506), thanks [@WouterK12](https://github.com/WouterK12)! +- Docs: Changes corresponding to docs design updates - [#24925](https://github.com/storybookjs/storybook/pull/24925), thanks [@kylegach](https://github.com/kylegach)! +- Maintenance: Split renderers preview entrypoints - [#24623](https://github.com/storybookjs/storybook/pull/24623), thanks [@ndelangen](https://github.com/ndelangen)! +- Manager: Update `store.settings.lastTrackedStoryId` - [#24115](https://github.com/storybookjs/storybook/pull/24115), thanks [@rashidshamloo](https://github.com/rashidshamloo)! +- ManagerAPI: Fix setting status without index, crashes storybook - [#24866](https://github.com/storybookjs/storybook/pull/24866), thanks [@ndelangen](https://github.com/ndelangen)! +- ManagerBuilder: Fix `"type": "commonjs"` compatibility - [#24534](https://github.com/storybookjs/storybook/pull/24534), thanks [@ndelangen](https://github.com/ndelangen)! +- Next.js: Add avif support - [#24611](https://github.com/storybookjs/storybook/pull/24611), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Next.js: Add back image context CommonJS export - [#24885](https://github.com/storybookjs/storybook/pull/24885), thanks [@martinnabhan](https://github.com/martinnabhan)! +- Next.js: Add experimental SWC support - [#24852](https://github.com/storybookjs/storybook/pull/24852), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Next.js: Fix Fast Refresh config for SWC mode - [#24991](https://github.com/storybookjs/storybook/pull/24991), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Next.js: Fix forwarding ref for Image component - [#24648](https://github.com/storybookjs/storybook/pull/24648), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Next.js: Fix import path in swc loader - [#24922](https://github.com/storybookjs/storybook/pull/24922), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Next.js: Fix react-docgen usage with preset-env settings - [#24993](https://github.com/storybookjs/storybook/pull/24993), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Next.js: Remove duplicate Fast Refresh plugin init - [#24963](https://github.com/storybookjs/storybook/pull/24963), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- React: Upgrade `react-docgen` to v7 - [#24530](https://github.com/storybookjs/storybook/pull/24530), thanks [@shilman](https://github.com/shilman)! +- ReactNative: Fix missing assert dep in docs-tools - [#24732](https://github.com/storybookjs/storybook/pull/24732), thanks [@dannyhw](https://github.com/dannyhw)! +- Svelte: Fix decorators always running twice - [#24921](https://github.com/storybookjs/storybook/pull/24921), thanks [@paoloricciuti](https://github.com/paoloricciuti)! +- Svelte: Fix source with decorators always showing the `SlotDecorator` component - [#24800](https://github.com/storybookjs/storybook/pull/24800), thanks [@JReinhold](https://github.com/JReinhold)! +- SvelteKit: Add experimental page and navigation mocking - [#24795](https://github.com/storybookjs/storybook/pull/24795), thanks [@paoloricciuti](https://github.com/paoloricciuti)! +- SvelteKit: Default to log an action for `goto`, `invalidate` and `invalidateAll` - [#24955](https://github.com/storybookjs/storybook/pull/24955), thanks [@paoloricciuti](https://github.com/paoloricciuti)! +- SWC: Add settings for react and preact - [#24805](https://github.com/storybookjs/storybook/pull/24805), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Test Build: Add env-variable support to `--test` CLI-flag - [#24862](https://github.com/storybookjs/storybook/pull/24862), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Add tests and rename to camelCase - [#24911](https://github.com/storybookjs/storybook/pull/24911), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Disable composition when `--test` is `true` - [#24799](https://github.com/storybookjs/storybook/pull/24799), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Disable docs related stuff for test builds - [#24691](https://github.com/storybookjs/storybook/pull/24691), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Disable telemetry for test builds - [#24706](https://github.com/storybookjs/storybook/pull/24706), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Test Build: Disable warnOnIncompatibleAddons - [#24797](https://github.com/storybookjs/storybook/pull/24797), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Filter out addon-docs from essentials in the test build - [#24994](https://github.com/storybookjs/storybook/pull/24994), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Test Build: Fix disabledAddons filter - [#24924](https://github.com/storybookjs/storybook/pull/24924), thanks [@IanVS](https://github.com/IanVS)! +- Test Build: Fix indexer bug - [#24890](https://github.com/storybookjs/storybook/pull/24890), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Globalize `@storybook/blocks` if `build.test.emptyBlocks` is `true` - [#24650](https://github.com/storybookjs/storybook/pull/24650), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Implement builder options for test build - [#24826](https://github.com/storybookjs/storybook/pull/24826), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Test Build: Improve config loading & naming - [#24837](https://github.com/storybookjs/storybook/pull/24837), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: No sourcemaps for test builds - [#24804](https://github.com/storybookjs/storybook/pull/24804), thanks [@ndelangen](https://github.com/ndelangen)! +- Test Build: Revert defaulting to SWC in test build, but keep using esbuild for minification - [#24843](https://github.com/storybookjs/storybook/pull/24843), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Test: Create @storybook/test package based on vitest - [#24392](https://github.com/storybookjs/storybook/pull/24392), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Test: Don\'t attach action to function mock if action was added already - [#24966](https://github.com/storybookjs/storybook/pull/24966), thanks [@tmeasday](https://github.com/tmeasday)! +- Test: Model loaders as before each and restore mocks properly - [#24948](https://github.com/storybookjs/storybook/pull/24948), thanks [@kasperpeulen](https://github.com/kasperpeulen)! +- Theming: Add theme variable to set the preview background color - [#24575](https://github.com/storybookjs/storybook/pull/24575), thanks [@JReinhold](https://github.com/JReinhold)! +- Typescript: Add \'skipCompiler\' option to TypeScript presets - [#24847](https://github.com/storybookjs/storybook/pull/24847), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- UI: Fix horizontal scroll bar in Canvas hidden by styling - [#24408](https://github.com/storybookjs/storybook/pull/24408), thanks [@yoshi2no](https://github.com/yoshi2no)! +- UI: improve A11Y remove redundant styling rules, update icon color - [#24402](https://github.com/storybookjs/storybook/pull/24402), thanks [@tolkadot](https://github.com/tolkadot)! +- UI: Logo fixed value - [#24726](https://github.com/storybookjs/storybook/pull/24726), thanks [@black-arm](https://github.com/black-arm)! +- UI: Update zIndex on NotificationList to fix the notification not being clickable in certain cases - [#24602](https://github.com/storybookjs/storybook/pull/24602), thanks [@yoshi2no](https://github.com/yoshi2no)! +- Viewport: Add newer device viewports - [#24777](https://github.com/storybookjs/storybook/pull/24777), thanks [@Tomo5524](https://github.com/Tomo5524)! +- Vite: Prevent non-deterministic build output - [#24833](https://github.com/storybookjs/storybook/pull/24833), thanks [@henkerik](https://github.com/henkerik)! +- Webpack: Add export-order-loader and remove babel-plugin-named-exports-order - [#24749](https://github.com/storybookjs/storybook/pull/24749), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Webpack: Add react-docgen loader and remove babel-plugin-react-docgen - [#24762](https://github.com/storybookjs/storybook/pull/24762), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Webpack: Fix race condition for export-order loader - [#24817](https://github.com/storybookjs/storybook/pull/24817), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Webpack: Hide critical dependency warning - [#24784](https://github.com/storybookjs/storybook/pull/24784), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Webpack: Only load babel config when babel-loader is used - [#25002](https://github.com/storybookjs/storybook/pull/25002), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- Webpack: Resolve circular dependency and fix HMR - [#24974](https://github.com/storybookjs/storybook/pull/24974), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! + ## 7.5.2 diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index dce7c33f53c7..aec117765b12 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,34 @@ +## 8.0.0-rc.5 + +- CLI: Automigration fix version detection of upgrading related packages - [#26410](https://github.com/storybookjs/storybook/pull/26410), thanks @ndelangen! + +## 8.0.0-rc.4 + +- Actions: Fix attaching action after a spy is restored to original function - [#26364](https://github.com/storybookjs/storybook/pull/26364), thanks @kasperpeulen! +- CLI: Add explicit actions to header story - [#26352](https://github.com/storybookjs/storybook/pull/26352), thanks @kasperpeulen! +- CLI: Automigration for upgrading storybook related dependencies - [#26377](https://github.com/storybookjs/storybook/pull/26377), thanks @ndelangen! +- CLI: Fix doctor compatibility check - [#26363](https://github.com/storybookjs/storybook/pull/26363), thanks @yannbf! +- CLI: Fix fn reference in preact templates - [#26384](https://github.com/storybookjs/storybook/pull/26384), thanks @kasperpeulen! +- CLI: Remove duplicated dependency warning - [#26385](https://github.com/storybookjs/storybook/pull/26385), thanks @yannbf! +- CLI: Vite migration link (shorter) - [#26379](https://github.com/storybookjs/storybook/pull/26379), thanks @ndelangen! +- Composition: Fix refs not loading when there's multiple - [#26356](https://github.com/storybookjs/storybook/pull/26356), thanks @ndelangen! +- Dependencies: Broaden `esbuild` version range - [#26405](https://github.com/storybookjs/storybook/pull/26405), thanks @ndelangen! +- Maintenance: Replace `@storybook/testing-library` with `@storybook/test` in monorepo - [#26351](https://github.com/storybookjs/storybook/pull/26351), thanks @ndelangen! +- Maintenance: What's new modal changes - [#26355](https://github.com/storybookjs/storybook/pull/26355), thanks @kasperpeulen! +- Portable Stories: Fix injected root element changing layout - [#26387](https://github.com/storybookjs/storybook/pull/26387), thanks @JReinhold! +- React: Support all React component types in JSX Decorator - [#26382](https://github.com/storybookjs/storybook/pull/26382), thanks @yannbf! + +## 8.0.0-rc.3 + +- Addon-themes: Fix switcher initialization after first start - [#26353](https://github.com/storybookjs/storybook/pull/26353), thanks @valentinpalkovic! +- Build: Upgrade `esbuild` (`0.20.1`) - [#26255](https://github.com/storybookjs/storybook/pull/26255), thanks @43081j! +- Core: Fix path separator issue in check-addon-order - [#26362](https://github.com/storybookjs/storybook/pull/26362), thanks @valentinpalkovic! +- Dependencies: Remove `qs` from `@storybook/manager-api` & `@storybook/channels` - [#26285](https://github.com/storybookjs/storybook/pull/26285), thanks @43081j! +- UI: Fix sidebar scrolling to selected story when state changes - [#26337](https://github.com/storybookjs/storybook/pull/26337), thanks @JReinhold! +- UI: Remove 'left' property from TooltipLinkList and Link components - [#26324](https://github.com/storybookjs/storybook/pull/26324), thanks @valentinpalkovic! +- Viewport: Fix editing when default viewport is set - [#26360](https://github.com/storybookjs/storybook/pull/26360), thanks @shilman! +- Vue: Fix reference error when using re-exports with "vue-component-meta" - [#26303](https://github.com/storybookjs/storybook/pull/26303), thanks @larsrickert! + ## 8.0.0-rc.2 - CLI: Add @storybook/addons automigration - [#26295](https://github.com/storybookjs/storybook/pull/26295), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! diff --git a/MIGRATION.md b/MIGRATION.md index 6488919f513b..561a9a61b899 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -4,7 +4,6 @@ - [Portable stories](#portable-stories) - [Project annotations are now merged instead of overwritten in composeStory](#project-annotations-are-now-merged-instead-of-overwritten-in-composestory) - [Type change in `composeStories` API](#type-change-in-composestories-api) - - [DOM structure changed in portable stories](#dom-structure-changed-in-portable-stories) - [Composed Vue stories are now components instead of functions](#composed-vue-stories-are-now-components-instead-of-functions) - [Tab addons are now routed to a query parameter](#tab-addons-are-now-routed-to-a-query-parameter) - [Default keyboard shortcuts changed](#default-keyboard-shortcuts-changed) @@ -65,6 +64,7 @@ - [Removed `passArgsFirst` option](#removed-passargsfirst-option) - [Methods and properties from AddonStore](#methods-and-properties-from-addonstore) - [Methods and properties from PreviewAPI](#methods-and-properties-from-previewapi) + - [Removals in @storybook/components](#removals-in-storybookcomponents) - [Removals in @storybook/types](#removals-in-storybooktypes) - [--use-npm flag in storybook CLI](#--use-npm-flag-in-storybook-cli) - [hideNoControlsWarning parameter from addon controls](#hidenocontrolswarning-parameter-from-addon-controls) @@ -439,35 +439,6 @@ await Primary.play!(...) // if you want a runtime error when the play function d There are plans to make the type of the play function be inferred based on your imported story's play function in a near future, so the types will be 100% accurate. -#### DOM structure changed in portable stories - -The portable stories API now adds a wrapper to your stories with a unique id based on your story id, such as: - -```html -
- -
-``` - -This means that if you take DOM snapshots of your stories, they will be affected and you will have to update them. - -The id calculation is based on different heuristics based on your Meta title and Story name. When using `composeStories`, the id can be inferred automatically. However, when using `composeStory` and your story does not explicitly have a `storyName` property, the story name can't be inferred automatically. As a result, its name will be "Unnamed Story", resulting in a wrapper id like `"#storybook-story-button--unnamed-story"`. If the id matters to you and you want to fix it, you have to specify the `exportsName` property like so: - -```ts -test("snapshots the story with custom id", () => { - const Primary = composeStory( - stories.Primary, - stories.default, - undefined, - // If you do not want the `unnamed-story` id, you have to pass the name of the story as a parameter - "Primary" - ); - - const { baseElement } = render(); - expect(baseElement).toMatchSnapshot(); -}); -``` - #### Composed Vue stories are now components instead of functions `composeStory` (and `composeStories`) from `@storybook/vue3` now return Vue components rather than story functions that return components. This means that when rendering these composed stories you just pass the composed story _without_ first calling it. @@ -1068,6 +1039,45 @@ The following exports from `@storybook/preview-api` are now removed: Please file an issue if you need these APIs. +#### Removals in @storybook/components + +The `TooltipLinkList` UI component used to customize the Storybook toolbar has been updated to use the `icon` property instead of the `left` property to position its content. If you've enabled this property in your `globalTypes` configuration, addons, or any other place, you'll need to replace it with an `icon` property to mimic the same behavior. For example: + +```diff +// .storybook/preview.js|ts +// Replace your-framework with the framework you are using (e.g., react, vue3) +import { Preview } from '@storybook/your-framework'; + +const preview: Preview = { + globalTypes: { + locale: { + description: 'Internationalization locale', + defaultValue: 'en', + toolbar: { + icon: 'globe', + items: [ + { + value: 'en', + right: '๐Ÿ‡บ๐Ÿ‡ธ', +- left: '๏ผ„' ++ icon: 'facehappy' + title: 'English' + }, + { value: 'fr', right: '๐Ÿ‡ซ๐Ÿ‡ท', title: 'Franรงais' }, + { value: 'es', right: '๐Ÿ‡ช๐Ÿ‡ธ', title: 'Espaรฑol' }, + { value: 'zh', right: '๐Ÿ‡จ๐Ÿ‡ณ', title: 'ไธญๆ–‡' }, + { value: 'kr', right: '๐Ÿ‡ฐ๐Ÿ‡ท', title: 'ํ•œ๊ตญ์–ด' }, + ], + }, + }, + }, +}; + +export default preview; +``` + +To learn more about the available icons and their names, see the [Storybook documentation](https://storybook.js.org/docs/8.0/faq#what-icons-are-available-for-my-toolbar-or-my-addon). + #### Removals in @storybook/types The following exports from `@storybook/types` are now removed: diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index abe43c249f6b..73f802106851 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index 5dcdd61e3c52..2f13f8e98a15 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Get UI feedback when an action is performed on an interactive element", "keywords": [ "storybook", diff --git a/code/addons/actions/src/loaders.ts b/code/addons/actions/src/loaders.ts index cc6c8494b7fc..3acfa9795eef 100644 --- a/code/addons/actions/src/loaders.ts +++ b/code/addons/actions/src/loaders.ts @@ -2,6 +2,8 @@ import type { LoaderFunction } from '@storybook/types'; import { action } from './runtime'; +export const tinySpyInternalState = Symbol.for('tinyspy:spy'); + const attachActionsToFunctionMocks: LoaderFunction = (context) => { const { args, @@ -15,7 +17,11 @@ const attachActionsToFunctionMocks: LoaderFunction = (context) => { typeof value === 'function' && '_isMockFunction' in value && value._isMockFunction ) .forEach(([key, value]) => { - const previous = value.getMockImplementation(); + // See this discussion for context: + // https://github.com/vitest-dev/vitest/pull/5352 + const previous = + value.getMockImplementation() ?? + (tinySpyInternalState in value ? value[tinySpyInternalState]?.getOriginal() : undefined); if (previous?._actionAttached !== true && previous?.isAction !== true) { const implementation = (...params: unknown[]) => { action(key)(...params); diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index 17a842b06f13..08ea5529d139 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Switch backgrounds to view components in different settings", "keywords": [ "addon", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index 3df650748609..d59821722737 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-controls", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Interact with component inputs dynamically in the Storybook UI", "keywords": [ "addon", diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index a74ff2e67653..3c6eaa0d625a 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Document component usage and properties in Markdown", "keywords": [ "addon", diff --git a/code/addons/docs/template/stories/docspage/autoplay.stories.ts b/code/addons/docs/template/stories/docspage/autoplay.stories.ts index 36fc395949d8..6ebdc43b3ad7 100644 --- a/code/addons/docs/template/stories/docspage/autoplay.stories.ts +++ b/code/addons/docs/template/stories/docspage/autoplay.stories.ts @@ -1,6 +1,5 @@ import { global as globalThis } from '@storybook/global'; -import { expect } from '@storybook/test'; -import { within } from '@storybook/testing-library'; +import { expect, within } from '@storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index 5b01bbd974b1..3b9143837d78 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-essentials", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Curated addons to bring out the best of Storybook", "keywords": [ "addon", diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json index 031416826745..b35c226de305 100644 --- a/code/addons/gfm/package.json +++ b/code/addons/gfm/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-mdx-gfm", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "GitHub Flavored Markdown in Storybook", "keywords": [ "addon", diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index e4802d08da43..bae6a544048d 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-highlight", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Highlight DOM nodes within your stories", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 29d753da6fbf..dbb88085b22b 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-interactions", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Automate, test and debug user interactions", "keywords": [ "storybook-addons", @@ -65,7 +65,7 @@ "@storybook/instrumenter": "workspace:*", "@storybook/manager-api": "workspace:*", "@storybook/preview-api": "workspace:*", - "@storybook/testing-library": "next", + "@storybook/test": "workspace:*", "@storybook/theming": "workspace:*", "@types/node": "^18.0.0", "formik": "^2.2.9", diff --git a/code/addons/interactions/src/components/Interaction.stories.tsx b/code/addons/interactions/src/components/Interaction.stories.tsx index b18cd7136c6a..a6f8bd3a3b46 100644 --- a/code/addons/interactions/src/components/Interaction.stories.tsx +++ b/code/addons/interactions/src/components/Interaction.stories.tsx @@ -1,7 +1,6 @@ import type { StoryObj, Meta } from '@storybook/react'; -import { expect } from '@storybook/test'; import { CallStates } from '@storybook/instrumenter'; -import { userEvent, within } from '@storybook/testing-library'; +import { userEvent, within, expect } from '@storybook/test'; import { getCalls } from '../mocks'; import { Interaction } from './Interaction'; diff --git a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx index a2435113ef02..89f7ef115b59 100644 --- a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx +++ b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx @@ -2,8 +2,7 @@ import React from 'react'; import type { StoryObj, Meta } from '@storybook/react'; import { CallStates } from '@storybook/instrumenter'; import { styled } from '@storybook/theming'; -import { userEvent, within, waitFor } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { userEvent, within, waitFor, expect } from '@storybook/test'; import isChromatic from 'chromatic/isChromatic'; import { getCalls, getInteractions } from '../mocks'; diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 7284de78eec3..bd511b8e0b5c 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "React storybook addon that show component jest report", "keywords": [ "addon", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index a23690c6e9b2..686c684f829b 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Link stories together to build demos and prototypes with your UI components", "keywords": [ "addon", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index 843dd37f5197..1985366f670c 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-measure", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Inspect layouts by visualizing the box model", "keywords": [ "storybook-addons", diff --git a/code/addons/onboarding/package.json b/code/addons/onboarding/package.json index 5064aa48addb..72726fb3726f 100644 --- a/code/addons/onboarding/package.json +++ b/code/addons/onboarding/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-onboarding", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook Addon Onboarding - Introduces a new onboarding experience", "keywords": [ "storybook-addons", @@ -55,7 +55,6 @@ "@storybook/react": "workspace:*", "@storybook/telemetry": "workspace:*", "@storybook/test": "workspace:*", - "@storybook/testing-library": "next", "@storybook/theming": "workspace:*", "@storybook/types": "workspace:*", "framer-motion": "^11.0.3", diff --git a/code/addons/onboarding/src/components/List/List.stories.tsx b/code/addons/onboarding/src/components/List/List.stories.tsx index 380fd07ca4cc..9ff667586fc3 100644 --- a/code/addons/onboarding/src/components/List/List.stories.tsx +++ b/code/addons/onboarding/src/components/List/List.stories.tsx @@ -1,7 +1,6 @@ import React, { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/react'; -import { userEvent, waitFor, within } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { userEvent, waitFor, within, expect } from '@storybook/test'; import { List } from './List'; import { ListItem } from './ListItem/ListItem'; diff --git a/code/addons/onboarding/src/components/Modal/Modal.stories.tsx b/code/addons/onboarding/src/components/Modal/Modal.stories.tsx index 51d19c49b4f5..527aa87d4323 100644 --- a/code/addons/onboarding/src/components/Modal/Modal.stories.tsx +++ b/code/addons/onboarding/src/components/Modal/Modal.stories.tsx @@ -1,7 +1,6 @@ import React, { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { userEvent, within, expect } from '@storybook/test'; import { Modal } from './Modal'; diff --git a/code/addons/onboarding/src/components/PulsatingEffect/PulsatingEffect.stories.tsx b/code/addons/onboarding/src/components/PulsatingEffect/PulsatingEffect.stories.tsx index 67b31843dc45..6a87a2147c0a 100644 --- a/code/addons/onboarding/src/components/PulsatingEffect/PulsatingEffect.stories.tsx +++ b/code/addons/onboarding/src/components/PulsatingEffect/PulsatingEffect.stories.tsx @@ -1,8 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { PulsatingEffect } from './PulsatingEffect'; import React from 'react'; -import { within } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { within, expect } from '@storybook/test'; const meta: Meta = { component: PulsatingEffect, diff --git a/code/addons/onboarding/src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx b/code/addons/onboarding/src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx index d2284dbd913f..d2fe6ba470b4 100644 --- a/code/addons/onboarding/src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx +++ b/code/addons/onboarding/src/features/WriteStoriesModal/WriteStoriesModal.stories.tsx @@ -1,8 +1,7 @@ import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; -import { waitFor, within } from '@storybook/testing-library'; -import { expect, fn } from '@storybook/test'; +import { waitFor, within, expect, fn } from '@storybook/test'; import { STORY_INDEX_INVALIDATED, STORY_RENDERED } from '@storybook/core-events'; import { WriteStoriesModal } from './WriteStoriesModal'; import typescriptSnippet from './code/typescript'; diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index b5b5771d6049..f8db2b4ea149 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-outline", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Outline all elements with CSS to help with layout placement and alignment", "keywords": [ "storybook-addons", diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index e060751d1a6f..c7326a263ad1 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "View a storyโ€™s source code to see how it works and paste into your app", "keywords": [ "addon", diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json index a13dcf595c17..a3599f8288e2 100644 --- a/code/addons/themes/package.json +++ b/code/addons/themes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-themes", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Switch between multiple themes for you components in Storybook", "keywords": [ "css", diff --git a/code/addons/themes/src/constants.ts b/code/addons/themes/src/constants.ts index a1872de9e88e..677c9499a7b4 100644 --- a/code/addons/themes/src/constants.ts +++ b/code/addons/themes/src/constants.ts @@ -1,5 +1,5 @@ export const PARAM_KEY = 'themes' as const; -export const ADDON_ID = `storybook/${PARAM_KEY}}` as const; +export const ADDON_ID = `storybook/${PARAM_KEY}` as const; export const GLOBAL_KEY = 'theme' as const; export const THEME_SWITCHER_ID = `${ADDON_ID}/theme-switcher` as const; diff --git a/code/addons/themes/src/theme-switcher.tsx b/code/addons/themes/src/theme-switcher.tsx index ef27f0d25769..0a0ac5f34bec 100644 --- a/code/addons/themes/src/theme-switcher.tsx +++ b/code/addons/themes/src/theme-switcher.tsx @@ -1,5 +1,11 @@ import React, { Fragment, useMemo } from 'react'; -import { useAddonState, useChannel, useGlobals, useParameter } from '@storybook/manager-api'; +import { + useAddonState, + useChannel, + useGlobals, + useParameter, + addons, +} from '@storybook/manager-api'; import { styled } from '@storybook/theming'; import { IconButton, WithTooltip, TooltipLinkList } from '@storybook/components'; @@ -20,16 +26,23 @@ const IconButtonLabel = styled.div(({ theme }) => ({ const hasMultipleThemes = (themesList: ThemeAddonState['themesList']) => themesList.length > 1; const hasTwoThemes = (themesList: ThemeAddonState['themesList']) => themesList.length === 2; -export const ThemeSwitcher = () => { +export const ThemeSwitcher = React.memo(function ThemeSwitcher() { const { themeOverride } = useParameter( PARAM_KEY, DEFAULT_THEME_PARAMETERS ) as ThemeParameters; const [{ theme: selected }, updateGlobals] = useGlobals(); + const channel = addons.getChannel(); + const fromLast = channel.last(THEMING_EVENTS.REGISTER_THEMES); + const initializeThemeState = Object.assign({}, DEFAULT_ADDON_STATE, { + themesList: fromLast?.[0]?.themes || [], + themeDefault: fromLast?.[0]?.defaultTheme || '', + }); + const [{ themesList, themeDefault }, updateState] = useAddonState( THEME_SWITCHER_ID, - DEFAULT_ADDON_STATE + initializeThemeState ); useChannel({ @@ -103,4 +116,4 @@ export const ThemeSwitcher = () => { } return null; -}; +}); diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index b1bdae2a70cd..ec4a11506175 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", diff --git a/code/addons/toolbars/src/types.ts b/code/addons/toolbars/src/types.ts index e07d11f73ae0..8427c53e4606 100644 --- a/code/addons/toolbars/src/types.ts +++ b/code/addons/toolbars/src/types.ts @@ -15,7 +15,6 @@ export type ToolbarShortcuts = Record { registerShortcuts(api, globals, updateGlobals, Object.keys(viewports)); - }, [viewports, globals.viewport]); + }, [viewports, globals, globals.viewport, updateGlobals, api]); useEffect(() => { const defaultRotated = defaultOrientation === 'landscape'; @@ -150,7 +150,18 @@ export const ViewportTool: FC = memo( viewportRotated: defaultRotated, }); } - }, [defaultOrientation, defaultViewport, globals, updateGlobals]); + // NOTE: we don't want to re-run this effect when `globals` changes + // due to https://github.com/storybookjs/storybook/issues/26334 + // + // Also, this *will* rerun every time you change story as the parameter is briefly `undefined`. + // This behaviour is intentional, if a bit of a happy accident in implementation. + // + // Ultimately this process of "locking in" a parameter value should be + // replaced by https://github.com/storybookjs/storybook/discussions/23347 + // or something similar. + // + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [defaultOrientation, defaultViewport, updateGlobals]); const item = list.find((i) => i.id === globals.viewport) || diff --git a/code/builders/builder-manager/package.json b/code/builders/builder-manager/package.json index 8f4a9c8c964a..a31a2e91a374 100644 --- a/code/builders/builder-manager/package.json +++ b/code/builders/builder-manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-manager", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook manager builder", "keywords": [ "storybook" @@ -52,7 +52,7 @@ "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", "browser-assert": "^1.2.1", "ejs": "^3.1.8", - "esbuild": "^0.18.0", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0", "esbuild-plugin-alias": "^0.2.1", "express": "^4.17.3", "fs-extra": "^11.1.0", diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index affa9c2fa59b..1d0dd1b7610c 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-vite", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "A plugin to run and build Storybooks with Vite", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme", "bugs": { diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index 9565198092f8..31d47498ee40 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-webpack5", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/e2e-tests/addon-viewport.spec.ts b/code/e2e-tests/addon-viewport.spec.ts index ec96a3bd93ea..64f8eb097dfb 100644 --- a/code/e2e-tests/addon-viewport.spec.ts +++ b/code/e2e-tests/addon-viewport.spec.ts @@ -40,4 +40,26 @@ test.describe('addon-viewport', () => { // Compare the two widths await expect(adjustedDimensions?.width).not.toBe(originalDimensions?.width); }); + + test('viewport should be editable when a default viewport is set', async ({ page }) => { + const sbPage = new SbPage(page); + + // Story parameters/selected is set to small mobile + await sbPage.navigateToStory('addons/viewport/parameters', 'selected'); + + // Measure the original dimensions of previewRoot + const originalDimensions = await sbPage.getCanvasBodyElement().boundingBox(); + await expect(originalDimensions?.width).toBeDefined(); + + // Manually select "large mobile" and give it time to adjust + await sbPage.selectToolbar('[title="Change the size of the preview"]', '#list-item-mobile2'); + await new Promise((r) => setTimeout(r, 200)); + + // Measure the adjusted dimensions of previewRoot after clicking the mobile item. + const adjustedDimensions = await sbPage.getCanvasBodyElement().boundingBox(); + await expect(adjustedDimensions?.width).toBeDefined(); + + // Compare the two widths + await expect(adjustedDimensions?.width).not.toBe(originalDimensions?.width); + }); }); diff --git a/code/frameworks/angular/README.md b/code/frameworks/angular/README.md index d97e1ab93f2a..4bfadb7f16f4 100644 --- a/code/frameworks/angular/README.md +++ b/code/frameworks/angular/README.md @@ -1,324 +1,3 @@ # Storybook for Angular -- [Storybook for Angular](#storybook-for-angular) - - [Getting Started](#getting-started) - - [Setup Storybook for your Angular projects](#setup-storybook-for-your-angular-projects) - - [Run Storybook](#run-storybook) - - [Setup Compodoc](#setup-compodoc) - - [Automatic setup](#automatic-setup) - - [Manual setup](#manual-setup) - - [moduleMetadata decorator](#modulemetadata-decorator) - - [applicationConfig decorator](#applicationconfig-decorator) - - [FAQ](#faq) - - [How do I migrate to an Angular Storybook builder?](#how-do-i-migrate-to-an-angular-storybook-builder) - - [Do you have only one Angular project in your workspace?](#do-you-have-only-one-angular-project-in-your-workspace) - - [Adjust your `package.json`](#adjust-your-packagejson) - - [I have multiple projects in my Angular workspace](#i-have-multiple-projects-in-my-angular-workspace) - -Storybook for Angular is a UI development environment for your Angular components. -With it, you can visualize different states of your UI components and develop them interactively. - -![Storybook Screenshot](https://github.com/storybookjs/storybook/blob/main/media/storybook-intro.gif) - -Storybook runs outside of your app. -So you can develop UI components in isolation without worrying about app specific dependencies and requirements. - -## Getting Started - -```sh -cd my-angular-app -npx storybook@latest init -``` - -## Setup Storybook for your Angular projects - -Storybook supports Angular multi-project workspace. You can setup Storybook for each project in the workspace. When running `npx storybook@latest init` you will be asked for which project Storybook should be set up. Essentially, during initialization, the `.storybook` folder will be created and the `angular.json` will be edited to add the Storybook configuration for the selected project. The configuration looks approximately like this: - -```json -// angular.json -{ - ... - "projects": { - ... - "your-project": { - ... - "architect": { - ... - "storybook": { - "builder": "@storybook/angular:start-storybook", - "options": { - // the path to the storybook config directory - "configDir": ".storybook", - // the build target of your project - "browserTarget": "your-project:build", - // the port you want to start Storybook on - "port": 6006 - // further options are available and can be found in - // https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular/src/builders/start-storybook/schema.json - } - }, - "build-storybook": { - "builder": "@storybook/angular:build-storybook", - "options": { - "configDir": ".storybook", - "browserTarget": "your-project:build", - "outputDir": "dist/storybook/your-project" - // further options are available and can be found in - // https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular/src/builders/build-storybook/schema.json - } - } - } - } - } -} -``` - -## Run Storybook - -To run Storybook for a particular project, please run: - -```sh -ng run :storybook -``` - -To build Storybook, run: - -```sh -ng run :build-storybook -``` - -You will find the output in `dist/storybook/your-project`. - -For more information visit: [storybook.js.org](https://storybook.js.org) - -## Setup Compodoc - -You can include JSDoc comments above components, directives, and other parts of your Angular code to include documentation for those elements. Compodoc uses these comments to generate documentation for your application. In Storybook, it is useful to add explanatory comments above @Inputs and @Outputs, since these are the main elements that Storybook displays in its user interface. The @Inputs and @Outputs are the elements that you can interact with in Storybook, such as controls. - -### Automatic setup - -When installing Storybook via `sb init`, you will be given the option to set up Compodoc automatically. - -### Manual setup - -If you have already installed Storybook, you can set up Compodoc manually. - -Install the following dependencies: - -```sh -npm i -D @compodoc/compodoc -``` - -Add the following option to your to the Storybook Builder: - -```json -{ - ... - "projects": { - ... - "your-project": { - ... - "architect": { - ... - "storybook": { - "builder": "@storybook/angular:start-storybook", - "options": { - ... - "compodoc": true, - "compodocArgs": [ - "-e", - "json", - "-d", - // Where to store the generated documentation. It's usually the root of your Angular project. It's not necessarily the root of your Angular Workspace! - "." - ], - } - }, - "build-storybook": { - "builder": "@storybook/angular:build-storybook", - "options": { - ... - "compodoc": true, - "compodocArgs": [ - "-e", - "json", - "-d", - "." - ], - } - } - } - } - } -} -``` - -Go to your `.storybook/preview.js` and add the following: - -```js -import { setCompodocJson } from '@storybook/addon-docs/angular'; -import docJson from '../documentation.json'; -setCompodocJson(docJson); - -const preview: Preview = { - ... -}; - -export default preview; -``` - -## moduleMetadata decorator - -If your component has dependencies on other Angular directives and modules, these can be supplied using the moduleMetadata decorator either for all stories or for individual stories. - -```js -import { StoryFn, Meta, moduleMetadata } from '@storybook/angular'; -import { SomeComponent } from './some.component'; - -export default { - component: SomeComponent, - decorators: [ - // Apply metadata to all stories - moduleMetadata({ - // import necessary ngModules or standalone components - imports: [...], - // declare components that are used in the template - declarations: [...], - // List of providers that should be available to the root component and all its children. - providers: [...], - }), - ], -} as Meta; - -const Template = (): StoryFn => (args) => ({ - props: args, -}); - -export const Base = Template(); - -export const WithCustomProvider = Template(); -WithCustomProvider.decorators = [ - // Apply metadata to a specific story - moduleMetadata({ - imports: [...], - declarations: [...], - providers: [...] - }), -]; -``` - -## applicationConfig decorator - -If your component relies on application-wide providers, like the ones defined by BrowserAnimationsModule or any other modules which use the forRoot pattern to provide a ModuleWithProviders, you can use the applicationConfig decorator on the meta default export to provide them to the [bootstrapApplication function](https://angular.io/guide/standalone-components#configuring-dependency-injection), which we use to bootstrap the component in Storybook. - -```js - -import { StoryObj, Meta, applicationConfig } from '@storybook/angular'; -import { BrowserAnimationsModule, provideAnimations } from '@angular/platform-browser/animations'; -import { importProvidersFrom } from '@angular/core'; -import { ChipsModule } from './angular-src/chips.module'; - -const meta: Meta = { - component: ChipsGroupComponent, - decorators: [ - // Apply application config to all stories - applicationConfig({ - // List of providers and environment providers that should be available to the root component and all its children. - providers: [ - ... - // Import application-wide providers from a module - importProvidersFrom(BrowserAnimationsModule) - // Or use provide-style functions if available instead, e.g. - provideAnimations() - ], - }), - ], -}; - -export default meta; - -type Story = StoryObj; - -export const WithCustomApplicationProvider: Story = { - render: () => ({ - // Apply application config to a specific story - applicationConfig: { - // The providers will be merged with the ones defined in the applicationConfig decorators providers array of the global meta object - providers: [...] - } - }) -} -``` - -## FAQ - -### How do I migrate to an Angular Storybook builder? - -The Storybook [Angular builder](https://angular.io/guide/glossary#builder) is a new way to run Storybook in an Angular workspace. It is a drop-in replacement for running `storybook dev` and `storybook build` directly. - -You can run `npx storybook@next automigrate` to try let Storybook detect and automatically fix your configuration. Otherwise, you can follow the next steps to manually adjust your configuration. - -#### Do you have only one Angular project in your workspace? - -In this case go to your `angular.json` and add `storybook` and `build-storybook` entries in `architect` section of your project like shown above. - -##### Adjust your `package.json` - -Go to your `package.json` and adjust your script section. Usually, it will look like this: - -```json -{ - "scripts": { - "storybook": "start-storybook -p 6006", // or `storybook dev -p 6006` - "build-storybook": "build-storybook" // or `storybook build` - } -} -``` - -Now, you can run Storybook with `ng run :storybook` and build it with `ng run :build-storybook`. Adjust the scripts in your `package.json` accordingly. - -```json -{ - "scripts": { - "storybook": "ng run :storybook", // or `storybook dev -p 6006` - "build-storybook": "ng run :build-storybook" // or `storybook build` - } -} -``` - -Also remove the compodoc part in your script section if you have set it up previously. -It is now built-in in `@storybook/angular` and you don't have to call it explicitly: - -```json -{ - "scripts": { - "docs:json": "compodoc -p tsconfig.json -e json -d ./documentation", - "storybook": "npm run docs:json && start-storybook -p 6006", - "build-storybook": "npm run docs:json && build-storybook" - } -} -``` - -Change it to: - -```json -{ - "scripts": { - "storybook": "ng run :storybook", - "build-storybook": "ng run :build-storybook" - } -} -``` - -#### I have multiple projects in my Angular workspace - -In this case you have to adjust your `angular.json` and `package.json` as described above for each project in which you want to use Storybook. Please note, that each project should have a dedicated `.storybook` folder, which should be placed in the root of the project. - -You can run `npx sb init` sequentially for each project to setup Storybook for each of them to automatically create the `.storybook` folder and create the necessary configuration in your `angular.json`. - -You can then use [Storybook composition](https://storybook.js.org/docs/angular/sharing/storybook-composition) to composite multiple Storybooks into one. - ---- - -Storybook also comes with a lot of [addons](https://storybook.js.org/addons) and a great API to customize as you wish. -You can also build a [static version](https://storybook.js.org/docs/angular/sharing/publish-storybook) of your Storybook and deploy it anywhere you want. +See [documentation](https://storybook.js.org/docs/8.0/get-started/angular?renderer=angular) for installation instructions, usage examples, APIs, and more. diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index 8639c28d08c2..9ffa620ac401 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", diff --git a/code/frameworks/angular/template/cli/header.stories.ts b/code/frameworks/angular/template/cli/header.stories.ts index 3222518ace44..3f3fb684e855 100644 --- a/code/frameworks/angular/template/cli/header.stories.ts +++ b/code/frameworks/angular/template/cli/header.stories.ts @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/angular'; import { HeaderComponent } from './header.component'; +import { fn } from '@storybook/test'; const meta: Meta = { title: 'Example/Header', @@ -11,6 +12,11 @@ const meta: Meta = { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, }; export default meta; diff --git a/code/frameworks/angular/template/stories/core/applicationConfig/with-browser-animations.stories.ts b/code/frameworks/angular/template/stories/core/applicationConfig/with-browser-animations.stories.ts index f61db00d8f0e..ef30854c26f9 100644 --- a/code/frameworks/angular/template/stories/core/applicationConfig/with-browser-animations.stories.ts +++ b/code/frameworks/angular/template/stories/core/applicationConfig/with-browser-animations.stories.ts @@ -1,7 +1,6 @@ import { Meta, StoryObj, applicationConfig } from '@storybook/angular'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { within, userEvent } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { within, userEvent, expect } from '@storybook/test'; import { importProvidersFrom } from '@angular/core'; import { OpenCloseComponent } from '../moduleMetadata/angular-src/open-close-component/open-close.component'; diff --git a/code/frameworks/angular/template/stories/core/applicationConfig/with-noop-browser-animations.stories.ts b/code/frameworks/angular/template/stories/core/applicationConfig/with-noop-browser-animations.stories.ts index 1a4341ec77cf..3369b9949d33 100644 --- a/code/frameworks/angular/template/stories/core/applicationConfig/with-noop-browser-animations.stories.ts +++ b/code/frameworks/angular/template/stories/core/applicationConfig/with-noop-browser-animations.stories.ts @@ -1,7 +1,6 @@ import { Meta, StoryObj } from '@storybook/angular'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { within, userEvent } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { within, userEvent, expect } from '@storybook/test'; import { importProvidersFrom } from '@angular/core'; import { OpenCloseComponent } from '../moduleMetadata/angular-src/open-close-component/open-close.component'; diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index db1b2cfe14aa..9c796b2f5b7c 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember", "bugs": { diff --git a/code/frameworks/ember/template/cli/Button.stories.js b/code/frameworks/ember/template/cli/Button.stories.js index 61de1a4f9cc9..c8fffd70feb0 100644 --- a/code/frameworks/ember/template/cli/Button.stories.js +++ b/code/frameworks/ember/template/cli/Button.stories.js @@ -1,6 +1,7 @@ import { hbs } from 'ember-cli-htmlbars'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; +import { fn } from '@storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/writing-stories export default { @@ -14,20 +15,19 @@ export default { }, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/ember/writing-docs/autodocs tags: ['autodocs'], + args: { onClick: fn() }, }; // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args export const Text = { args: { label: 'Button', - onClick: action('onClick'), }, }; export const Emoji = { args: { label: '๐Ÿ˜€ ๐Ÿ˜Ž ๐Ÿ‘ ๐Ÿ’ฏ', - onClick: action('onClick'), }, }; diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json index 5fb64a4a8c48..26bcfa5687c7 100644 --- a/code/frameworks/html-vite/package.json +++ b/code/frameworks/html-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-vite", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index 55e6496baa3c..7c6e27ae25e1 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index f622f9eeaabe..f3a10ee4210d 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/nextjs", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Next.js", "keywords": [ "storybook", diff --git a/code/frameworks/nextjs/template/cli/js/Header.stories.js b/code/frameworks/nextjs/template/cli/js/Header.stories.js index a1d32b3ad65e..982cd970fb5c 100644 --- a/code/frameworks/nextjs/template/cli/js/Header.stories.js +++ b/code/frameworks/nextjs/template/cli/js/Header.stories.js @@ -1,3 +1,4 @@ +import { fn } from '@storybook/test'; import { Header } from './Header'; export default { @@ -9,6 +10,11 @@ export default { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, }; export const LoggedIn = { args: { diff --git a/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts b/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts index 82a109720879..feddeae98faf 100644 --- a/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts +++ b/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts @@ -1,4 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; +import { fn } from '@storybook/test'; + import { Header } from './Header'; const meta: Meta = { @@ -10,6 +12,11 @@ const meta: Meta = { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, }; export default meta; diff --git a/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts index 046982e62673..39d15874f4c1 100644 --- a/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts +++ b/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react'; +import { fn } from '@storybook/test'; import { Header } from './Header'; const meta = { @@ -10,6 +11,11 @@ const meta = { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, } satisfies Meta; export default meta; diff --git a/code/frameworks/nextjs/template/stories/Image.stories.jsx b/code/frameworks/nextjs/template/stories/Image.stories.jsx index 8fa4f6a53de1..79ab308e1286 100644 --- a/code/frameworks/nextjs/template/stories/Image.stories.jsx +++ b/code/frameworks/nextjs/template/stories/Image.stories.jsx @@ -1,6 +1,5 @@ import React, { useRef, useState } from 'react'; import Image from 'next/image'; -import { waitFor } from '@storybook/testing-library'; import Accessibility from '../../assets/accessibility.svg'; import AvifImage from '../../assets/avif-test-image.avif'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/Head.stories.jsx b/code/frameworks/nextjs/template/stories_nextjs-default-js/Head.stories.jsx index f031096d6ced..1e43bb39eba6 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-js/Head.stories.jsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-js/Head.stories.jsx @@ -1,7 +1,6 @@ -import { expect } from '@storybook/test'; import Head from 'next/head'; import React from 'react'; -import { within, userEvent, waitFor } from '@storybook/testing-library'; +import { waitFor, expect } from '@storybook/test'; function Component() { return ( diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index 19e035c0740d..b8b67128ef22 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-vite", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index 8423ab98fade..51bdc48718ad 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/frameworks/react-vite/README.md b/code/frameworks/react-vite/README.md index e8a35450aec9..847119afd03d 100644 --- a/code/frameworks/react-vite/README.md +++ b/code/frameworks/react-vite/README.md @@ -1 +1,3 @@ -# Storybook for React +# Storybook for React & Vite + +See [documentation](https://storybook.js.org/docs/8.0/get-started/react-vite?renderer=react) for installation instructions, usage examples, APIs, and more. diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index a76d1c4cbddc..da08584b7625 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-vite", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-webpack5/README.md b/code/frameworks/react-webpack5/README.md index b3b1d877eaa2..d691444758e2 100644 --- a/code/frameworks/react-webpack5/README.md +++ b/code/frameworks/react-webpack5/README.md @@ -1,47 +1,3 @@ -# Storybook for React +# Storybook for React & Webpack -Storybook for React is a UI development environment for your React components. -With it, you can visualize different states of your UI components and develop them interactively. - -![Storybook Screenshot](https://github.com/storybookjs/storybook/blob/main/media/storybook-intro.gif) - -Storybook runs outside of your app. -So you can develop UI components in isolation without worrying about app specific dependencies and requirements. - -## Getting Started - -```sh -cd my-react-app -npx storybook@latest init -``` - -For more information visit: [storybook.js.org](https://storybook.js.org) - ---- - -Storybook also comes with a lot of [addons](https://storybook.js.org/addons) and a great API to customize as you wish. -You can also build a [static version](https://storybook.js.org/docs/react/sharing/publish-storybook) of your Storybook and deploy it anywhere you want. - -Here are some featured storybooks that you can reference to see how Storybook works: - -- [Demo of Storybook Design System](https://storybook.js.org/design-system) - [source](https://github.com/storybookjs/design-system) - -## Create React App - -Support for [Create React App](https://create-react-app.dev/) is handled by [`@storybook/preset-create-react-app`](https://github.com/storybookjs/presets/tree/master/packages/preset-create-react-app). - -This preset enables support for all Create React App features, including Sass/SCSS and TypeScript. - -If you're working on an app that was initialized manually (i.e., without the use of Create React App), ensure that your app has [react-dom](https://www.npmjs.com/package/react-dom) included as a dependency. Failing to do so can lead to unforeseen issues with Storybook and your project. - -## Typescript - -`@storybook/react` is now exporting its own types to use with Typescript. -You don't need to have `@types/storybook__react` installed anymore if it was your case. -But you probably also need to use types from `@types/node @types/react`. - -## Docs - -- [Basics](https://storybook.js.org/docs/react/get-started) -- [Configurations](https://storybook.js.org/docs/react/configure) -- [Addons](https://storybook.js.org/docs/react/configure/storybook-addons) +See [documentation](https://storybook.js.org/docs/8.0/get-started/react-webpack5?renderer=react) for installation instructions, usage examples, APIs, and more. diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index a2096ef8e059..3d5ceb3ba80c 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index 7c3771652cfd..6aa05a0c122d 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-vite/README.md b/code/frameworks/svelte-vite/README.md index 30a7c36ca01e..1f1dc740151d 100644 --- a/code/frameworks/svelte-vite/README.md +++ b/code/frameworks/svelte-vite/README.md @@ -1 +1,3 @@ -# Storybook for Svelte +# Storybook for Svelte & Vite + +See [documentation](https://storybook.js.org/docs/8.0/get-started/svelte-vite?renderer=svelte) for installation instructions, usage examples, APIs, and more. diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index edac75e5589d..9090da475670 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-vite", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 85a17dfc6a76..db4ed258f40c 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index b6450c030f5f..2acf401c3f24 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/sveltekit", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for SvelteKit", "keywords": [ "storybook", diff --git a/code/frameworks/vue3-vite/README.md b/code/frameworks/vue3-vite/README.md index bb1eb15f980e..08eb5ae95c13 100644 --- a/code/frameworks/vue3-vite/README.md +++ b/code/frameworks/vue3-vite/README.md @@ -1,44 +1,3 @@ -# Storybook for Vue 3 and Vite +# Storybook for Vue and Vite -Storybook for Vue 3 is a UI development environment for your Vue 3 components. -With it, you can visualize different states of your UI components and develop them interactively. - -![Storybook Screenshot](https://github.com/storybookjs/storybook/blob/main/media/storybook-intro.gif) - -Storybook runs outside of your app. -So you can develop UI components in isolation without worrying about app specific dependencies and requirements. - -## Getting Started - -```sh -cd my-vue3-app -npx storybook@latest init -``` - -For more information visit: [storybook.js.org](https://storybook.js.org) - ---- - -Storybook also comes with a lot of [addons](https://storybook.js.org/addons) and a great API to customize as you wish. -You can also build a [static version](https://storybook.js.org/docs/sharing/publish-storybook) of your Storybook and deploy it anywhere you want. - -## Extending the Vue application - -Storybook creates a [Vue 3 application](https://vuejs.org/api/application.html#application-api) for your component preview. -When using global custom components (`app.component`), directives (`app.directive`), extensions (`app.use`), or other application methods, you will need to configure those in the `./storybook/preview.js` file. - -Therefore, Storybook provides you with a `setup` function exported from this package, which receives as a callback your Storybook instance, which you can interact with and add your custom configuration. - -```js -// .storybook/preview.js - -import { setup } from '@storybook/vue3'; - -setup((app) => { - app.use(MyPlugin); - app.component('my-component', MyComponent); - app.mixin({ - /* My mixin */ - }); -}); -``` +See [documentation](https://storybook.js.org/docs/8.0/get-started/vue3-vite?renderer=vue) for installation instructions, usage examples, APIs, and more. diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index 58e9602305b1..44297c5a4047 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-vite", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index a23d5980b17f..094fb5103f2d 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json index 6c559ff1a849..cbe4ffdc247d 100644 --- a/code/frameworks/web-components-vite/package.json +++ b/code/frameworks/web-components-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-vite", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index 04f0b31cbf1f..866ab3d35e5d 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": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit", diff --git a/code/lib/channels/package.json b/code/lib/channels/package.json index 6020059195b0..1f583dc9865d 100644 --- a/code/lib/channels/package.json +++ b/code/lib/channels/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/channels", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "", "keywords": [ "storybook" @@ -47,7 +47,6 @@ "@storybook/client-logger": "workspace:*", "@storybook/core-events": "workspace:*", "@storybook/global": "^5.0.0", - "qs": "^6.10.0", "telejson": "^7.2.0", "tiny-invariant": "^1.3.1" }, diff --git a/code/lib/channels/src/postmessage/index.ts b/code/lib/channels/src/postmessage/index.ts index 267e8a34f18a..1320a6577b4c 100644 --- a/code/lib/channels/src/postmessage/index.ts +++ b/code/lib/channels/src/postmessage/index.ts @@ -5,7 +5,6 @@ import { global } from '@storybook/global'; import * as EVENTS from '@storybook/core-events'; import { logger, pretty } from '@storybook/client-logger'; import { isJSON, parse, stringify } from 'telejson'; -import qs from 'qs'; import invariant from 'tiny-invariant'; import type { ChannelTransport, @@ -102,13 +101,13 @@ export class PostMessageTransport implements ChannelTransport { const frames = this.getFrames(target); - const query = qs.parse(location?.search || '', { ignoreQueryPrefix: true }); + const query = new URLSearchParams(location?.search || ''); const data = stringify( { key: KEY, event, - refId: query.refId, + refId: query.get('refId'), }, stringifyOptions ); diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index 821450e6252c..e707547191dd 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -1,6 +1,6 @@ { "name": "sb", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index 17585083a303..3eb1547fccc0 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json index 0f8d72361143..01d064068c60 100644 --- a/code/lib/cli/package.json +++ b/code/lib/cli/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/cli", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook's CLI - install, dev, build, upgrade, and more", "keywords": [ "cli", diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index 17b3d4942be1..022074fa8301 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -26,6 +26,7 @@ import { removeJestTestingLibrary } from './remove-jest-testing-library'; import { addonsAPI } from './addons-api'; import { mdx1to3 } from './mdx-1-to-3'; import { addonPostCSS } from './addon-postcss'; +import { upgradeStorybookRelatedDependencies } from './upgrade-storybook-related-dependencies'; export * from '../types'; @@ -56,6 +57,7 @@ export const allFixes: Fix[] = [ removeLegacyMDX1, webpack5CompilerSetup, mdx1to3, + upgradeStorybookRelatedDependencies, ]; export const initFixes: Fix[] = [eslintPlugin]; diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.test.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.test.ts new file mode 100644 index 000000000000..0c16309647bd --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.test.ts @@ -0,0 +1,95 @@ +import { describe, afterEach, it, expect, vi } from 'vitest'; +import type { StorybookConfig } from '@storybook/types'; +import type { JsPackageManager } from '@storybook/core-common'; +import * as docsUtils from '../../doctor/getIncompatibleStorybookPackages'; + +import { upgradeStorybookRelatedDependencies } from './upgrade-storybook-related-dependencies'; + +vi.mock('../../doctor/getIncompatibleStorybookPackages'); + +const check = async ({ + packageManager, + main: mainConfig = {}, + storybookVersion = '8.0.0', +}: { + packageManager: Partial; + main?: Partial & Record; + storybookVersion?: string; +}) => { + return upgradeStorybookRelatedDependencies.check({ + packageManager: packageManager as any, + configDir: '', + mainConfig: mainConfig as any, + storybookVersion, + }); +}; + +describe('upgrade-storybook-related-dependencies fix', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should detect storyshots registered in main.js', async () => { + const analyzedPackages = [ + { + packageName: '@chromatic-com/storybook', + packageVersion: '1.2.9', + availableUpgrade: '2.0.0', + hasIncompatibleDependencies: false, + }, + { + packageName: '@storybook/jest', + packageVersion: '0.2.3', + availableUpgrade: '1.0.0', + hasIncompatibleDependencies: false, + }, + { + packageName: '@storybook/preset-create-react-app', + packageVersion: '3.2.0', + availableUpgrade: '8.0.0', + hasIncompatibleDependencies: true, + }, + { + packageName: 'storybook', + packageVersion: '8.0.0', + availableUpgrade: undefined, + hasIncompatibleDependencies: true, + }, + ]; + vi.mocked(docsUtils.getIncompatibleStorybookPackages).mockResolvedValue(analyzedPackages); + await expect( + check({ + packageManager: { + getAllDependencies: async () => ({ + '@chromatic-com/storybook': '1.2.9', + '@storybook/jest': '0.2.3', + '@storybook/preset-create-react-app': '3.2.0', + storybook: '8.0.0', + }), + latestVersion: async (pkgName) => + analyzedPackages.find((pkg) => pkg.packageName === pkgName)?.availableUpgrade || '', + }, + }) + ).resolves.toMatchInlineSnapshot(` + { + "upgradable": [ + { + "afterVersion": "2.0.0", + "beforeVersion": "1.2.9", + "packageName": "@chromatic-com/storybook", + }, + { + "afterVersion": "1.0.0", + "beforeVersion": "0.2.3", + "packageName": "@storybook/jest", + }, + { + "afterVersion": "8.0.0", + "beforeVersion": "3.2.0", + "packageName": "@storybook/preset-create-react-app", + }, + ], + } + `); + }); +}); diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts new file mode 100644 index 000000000000..5614b7e35ad0 --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -0,0 +1,162 @@ +import { dedent } from 'ts-dedent'; +import { cyan, yellow } from 'chalk'; +import { valid, coerce } from 'semver'; +import type { JsPackageManager } from '@storybook/core-common'; +import { isCorePackage } from '@storybook/core-common'; +import type { Fix } from '../types'; +import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; + +type PackageMetadata = { + packageName: string; + beforeVersion: string | null; + afterVersion: string | null; +}; + +interface Options { + upgradable: PackageMetadata[]; +} + +async function getLatestVersions( + packageManager: JsPackageManager, + packages: [string, string][] +): Promise { + return Promise.all( + packages.map(async ([packageName, beforeVersion]) => ({ + packageName, + beforeVersion: coerce(beforeVersion)?.toString() || null, + afterVersion: await packageManager.latestVersion(packageName).catch(() => null), + })) + ); +} + +function isPackageUpgradable( + afterVersion: string, + packageName: string, + allDependencies: Record +) { + const installedVersion = coerce(allDependencies[packageName])?.toString(); + + return valid(afterVersion) && afterVersion !== installedVersion; +} + +/** + * Is the user upgrading to the `latest` version of Storybook? + * Let's try to pull along some of the storybook related dependencies to `latest` as well! + * + * We communicate clearly that this migration is a helping hand, but not a complete solution. + * The user should still manually check for other dependencies that might be incompatible. + * + * see: https://github.com/storybookjs/storybook/issues/25731#issuecomment-1977346398 + */ +export const upgradeStorybookRelatedDependencies = { + id: 'upgradeStorybookRelatedDependencies', + versionRange: ['*.*.*', '*.*.*'], + promptType: 'auto', + promptDefaultValue: false, + + async check({ packageManager, storybookVersion }) { + const analyzedPackages = await getIncompatibleStorybookPackages({ + currentStorybookVersion: storybookVersion, + packageManager, + skipErrors: true, + }); + + const allDependencies = (await packageManager.getAllDependencies()) as Record; + const storybookDependencies = Object.keys(allDependencies) + .filter((dep) => dep.includes('storybook')) + .filter((dep) => !isCorePackage(dep)); + const incompatibleDependencies = analyzedPackages + .filter((pkg) => pkg.hasIncompatibleDependencies) + .map((pkg) => pkg.packageName); + + const uniquePackages = Array.from( + new Set([...storybookDependencies, ...incompatibleDependencies]) + ).map((packageName) => [packageName, allDependencies[packageName]]) as [string, string][]; + + const packageVersions = await getLatestVersions(packageManager, uniquePackages); + + const upgradablePackages = packageVersions.filter( + ({ packageName, afterVersion, beforeVersion }) => { + if (beforeVersion === null || afterVersion === null) { + return false; + } + + return isPackageUpgradable(afterVersion, packageName, allDependencies); + } + ); + + return upgradablePackages.length > 0 ? { upgradable: upgradablePackages } : null; + }, + + prompt({ upgradable }) { + return dedent` + You're upgrading to the latest version of Storybook. We recommend upgrading the following packages: + ${upgradable + .map(({ packageName, afterVersion, beforeVersion }) => { + return `- ${cyan(packageName)}: ${cyan(beforeVersion)} => ${cyan(afterVersion)}`; + }) + .join('\n')} + + After upgrading, we will run the dedupe command, which could possibly have effects on dependencies that are not Storybook related. + see: https://docs.npmjs.com/cli/commands/npm-dedupe + + Do you want to proceed (upgrade the detected packages)? + `; + }, + + async run({ result: { upgradable }, packageManager, dryRun }) { + if (dryRun) { + console.log(dedent` + We would have upgrade the following: + ${upgradable + .map( + ({ packageName, afterVersion, beforeVersion }) => + `${packageName}: ${beforeVersion} => ${afterVersion}` + ) + .join('\n')} + `); + return; + } + + if (upgradable.length > 0) { + const packageJson = await packageManager.readPackageJson(); + + upgradable.forEach((item) => { + if (!item) { + return; + } + + const { packageName, afterVersion: version } = item; + const prefixed = `^${version}`; + + if (packageJson.dependencies?.[packageName]) { + packageJson.dependencies[packageName] = prefixed; + } + if (packageJson.devDependencies?.[packageName]) { + packageJson.devDependencies[packageName] = prefixed; + } + if (packageJson.peerDependencies?.[packageName]) { + packageJson.peerDependencies[packageName] = prefixed; + } + }); + + await packageManager.writePackageJson(packageJson); + await packageManager.installDependencies(); + + await packageManager + .executeCommand({ command: 'dedupe', args: [], stdio: 'ignore' }) + .catch(() => {}); + + console.log(); + console.log(dedent` + We upgraded ${yellow(upgradable.length)} packages: + ${upgradable + .map(({ packageName, afterVersion, beforeVersion }) => { + return `- ${cyan(packageName)}: ${cyan(beforeVersion)} => ${cyan(afterVersion)}`; + }) + .join('\n')} + `); + } + console.log(); + }, +} satisfies Fix; diff --git a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts index 6a8dd9ec0e02..9203b45f225f 100644 --- a/code/lib/cli/src/automigrate/fixes/vite-config-file.ts +++ b/code/lib/cli/src/automigrate/fixes/vite-config-file.ts @@ -105,7 +105,7 @@ export const viteConfigFile = { If you do already have these plugins, you can ignore this message. You can find more information on how to do this here: - https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#framework-specific-vite-plugins-have-to-be-explicitly-added + https://storybook.js.org/docs/8.0/migration-guide/#missing-viteconfigjs-file This change was necessary to support newer versions of Vite. `; @@ -115,7 +115,7 @@ export const viteConfigFile = { Please add a vite.config.js file to your project root. You can find more information on how to do this here: - https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#framework-specific-vite-plugins-have-to-be-explicitly-added + https://storybook.js.org/docs/8.0/migration-guide/#missing-viteconfigjs-file This change was necessary to support newer versions of Vite. `; diff --git a/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts b/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts index f43e84370852..eb49848ab2c0 100644 --- a/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts +++ b/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts @@ -129,35 +129,7 @@ describe('getMigrationSummary', () => { The automigrations try to migrate common patterns in your project, but might not contain everything needed to migrate to the latest version of Storybook. Please check the changelog and migration guide for manual migrations and more information: https://storybook.js.org/docs/8.0/migration-guide - And reach out on Discord if you need help: https://discord.gg/storybook - - โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - - Critical: The following dependencies are duplicated and WILL cause unexpected behavior: - - @storybook/instrumenter: - 6.0.0, 7.1.0 - - @storybook/core-common: - 6.0.0, 7.1.0 - - - - - Attention: The following dependencies are duplicated which might cause unexpected behavior: - - @storybook/addon-essentials: - 7.0.0, 7.1.0 - - - - - Please try de-duplicating these dependencies by running yarn dedupe - - - - - You can find more information for a given dependency by running yarn why " + And reach out on Discord if you need help: https://discord.gg/storybook" `); }); diff --git a/code/lib/cli/src/automigrate/helpers/getMigrationSummary.ts b/code/lib/cli/src/automigrate/helpers/getMigrationSummary.ts index aa0503865749..12c8ac07bfa7 100644 --- a/code/lib/cli/src/automigrate/helpers/getMigrationSummary.ts +++ b/code/lib/cli/src/automigrate/helpers/getMigrationSummary.ts @@ -4,7 +4,6 @@ import dedent from 'ts-dedent'; import type { InstallationMetadata } from '@storybook/core-common'; import type { FixSummary } from '../types'; import { FixStatus } from '../types'; -import { getDuplicatedDepsWarnings } from '../../doctor/getDuplicatedDepsWarnings'; export const messageDivider = '\n\n'; const segmentDivider = '\n\nโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n'; @@ -75,14 +74,6 @@ export function getMigrationSummary({ And reach out on Discord if you need help: ${chalk.yellow('https://discord.gg/storybook')} `); - const duplicatedDepsMessage = installationMetadata - ? getDuplicatedDepsWarnings(installationMetadata) - : getDuplicatedDepsWarnings(); - - if (duplicatedDepsMessage) { - messages.push(duplicatedDepsMessage.join(messageDivider)); - } - const hasNoFixes = Object.values(fixResults).every((r) => r === FixStatus.UNNECESSARY); const hasFailures = Object.values(fixResults).some( (r) => r === FixStatus.FAILED || r === FixStatus.CHECK_FAILED diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 8a84476b5e93..340a90f7ec38 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -29,6 +29,9 @@ import { getMigrationSummary } from './helpers/getMigrationSummary'; import { getStorybookData } from './helpers/mainConfigFile'; import { doctor } from '../doctor'; +import { upgradeStorybookRelatedDependencies } from './fixes/upgrade-storybook-related-dependencies'; +import dedent from 'ts-dedent'; + const logger = console; const LOG_FILE_NAME = 'migration-storybook.log'; const LOG_FILE_PATH = join(process.cwd(), LOG_FILE_NAME); @@ -56,8 +59,16 @@ const cleanup = () => { }; const logAvailableMigrations = () => { - const availableFixes = allFixes.map((f) => chalk.yellow(f.id)).join(', '); - logger.info(`\nThe following migrations are available: ${availableFixes}`); + const availableFixes = allFixes + .map((f) => chalk.yellow(f.id)) + .map((x) => `- ${x}`) + .join('\n'); + + console.log(); + logger.info(dedent` + The following migrations are available: + ${availableFixes} + `); }; export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { @@ -84,7 +95,7 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { throw new Error('Could not determine main config path'); } - await automigrate({ + const outcome = await automigrate({ ...options, packageManager, storybookVersion, @@ -92,9 +103,12 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { mainConfigPath, configDir, isUpgrade: false, + isLatest: false, }); - await doctor({ configDir, packageManager: options.packageManager }); + if (outcome) { + await doctor({ configDir, packageManager: options.packageManager }); + } }; export const automigrate = async ({ @@ -112,6 +126,7 @@ export const automigrate = async ({ skipInstall, hideMigrationSummary = false, isUpgrade, + isLatest, }: AutofixOptions): Promise<{ fixResults: Record; preCheckFailure?: PreCheckFailure; @@ -121,8 +136,21 @@ export const automigrate = async ({ return null; } - const selectedFixes = inputFixes || allFixes; - const fixes = fixId ? selectedFixes.filter((f) => f.id === fixId) : selectedFixes; + const selectedFixes: Fix[] = + inputFixes || + allFixes.filter((fix) => { + // we only allow this automigration when the user explicitly asks for it, or they are upgrading to the latest version of storybook + if ( + fix.id === upgradeStorybookRelatedDependencies.id && + isLatest === false && + fixId !== upgradeStorybookRelatedDependencies.id + ) { + return false; + } + + return true; + }); + const fixes: Fix[] = fixId ? selectedFixes.filter((f) => f.id === fixId) : selectedFixes; if (fixId && fixes.length === 0) { logger.info(`๐Ÿ“ญ No migrations found for ${chalk.magenta(fixId)}.`); @@ -143,7 +171,7 @@ export const automigrate = async ({ mainConfigPath, storybookVersion, beforeVersion, - isUpgrade, + isUpgrade: !!isUpgrade, dryRun, yes, }); @@ -314,7 +342,7 @@ export async function runFixes({ type: 'confirm', name: 'fix', message: `Do you want to run the '${chalk.cyan(f.id)}' migration on your project?`, - initial: true, + initial: f.promptDefaultValue ?? true, }, { onCancel: () => { diff --git a/code/lib/cli/src/automigrate/types.ts b/code/lib/cli/src/automigrate/types.ts index d8cc9f06af3e..43447102162f 100644 --- a/code/lib/cli/src/automigrate/types.ts +++ b/code/lib/cli/src/automigrate/types.ts @@ -1,5 +1,5 @@ -import type { StorybookConfigRaw } from '@storybook/types'; import type { JsPackageManager, PackageManagerName } from '@storybook/core-common'; +import type { StorybookConfigRaw } from '@storybook/types'; export interface CheckOptions { packageManager: JsPackageManager; @@ -37,6 +37,7 @@ type BaseFix = { versionRange: [from: string, to: string]; check: (options: CheckOptions) => Promise; prompt: (result: ResultType) => string; + promptDefaultValue?: boolean; }; type PromptType = @@ -75,6 +76,7 @@ export interface AutofixOptions extends Omit { - const storybookVersion = semver.coerce(currentStorybookVersion); - const packageVersion = semver.coerce(installedVersion); - return storybookVersion?.major !== packageVersion?.major; -}; - export const checkPackageCompatibility = async (dependency: string, context: Context) => { const { currentStorybookVersion, skipErrors, packageManager } = context; try { @@ -46,12 +40,12 @@ export const checkPackageCompatibility = async (dependency: string, context: Con ...peerDependencies, }) .filter(([dep]) => storybookCorePackages[dep as keyof typeof storybookCorePackages]) - .find(([, version]) => { + .find(([_, versionRange]) => { // prevent issues with "tag" based versions e.g. "latest" or "next" instead of actual numbers return ( - version && - semver.validRange(version) && - isPackageIncompatible(version, currentStorybookVersion) + versionRange && + semver.validRange(versionRange) && + !semver.satisfies(currentStorybookVersion, versionRange) ); }); diff --git a/code/lib/cli/src/migrate.ts b/code/lib/cli/src/migrate.ts index 15d2169120e7..29ee10dc82a3 100644 --- a/code/lib/cli/src/migrate.ts +++ b/code/lib/cli/src/migrate.ts @@ -1,11 +1,12 @@ import { listCodemods, runCodemod } from '@storybook/codemod'; -import { runFixes } from './automigrate'; -import { mdxToCSF } from './automigrate/fixes/mdx-to-csf'; import { JsPackageManagerFactory, - getStorybookInfo, getCoercedStorybookVersion, + getStorybookInfo, } from '@storybook/core-common'; + +import { runFixes } from './automigrate'; +import { mdxToCSF } from './automigrate/fixes/mdx-to-csf'; import { getStorybookVersionSpecifier } from './helpers'; const logger = console; diff --git a/code/lib/cli/src/sandbox-templates.ts b/code/lib/cli/src/sandbox-templates.ts index 182e49798148..b28021be7049 100644 --- a/code/lib/cli/src/sandbox-templates.ts +++ b/code/lib/cli/src/sandbox-templates.ts @@ -443,7 +443,7 @@ const baseTemplates = { }, 'qwik-vite/default-ts': { name: 'Qwik CLI Latest (Vite | TypeScript)', - script: 'yarn create qwik basic {{beforeDir}}', + script: 'npm create qwik basic {{beforeDir}}', // TODO: The community template does not provide standard stories, which is required for e2e tests. Reenable once it does. inDevelopment: true, expected: { diff --git a/code/lib/cli/src/upgrade.ts b/code/lib/cli/src/upgrade.ts index 179c7d806a2f..f0b7cc5ff612 100644 --- a/code/lib/cli/src/upgrade.ts +++ b/code/lib/cli/src/upgrade.ts @@ -148,6 +148,7 @@ export const doUpgrade = async ({ ]); const isOutdated = lt(currentVersion, latestVersion); + const isExactLatest = currentVersion === latestVersion; const isPrerelease = prerelease(currentVersion) !== null; const borderColor = isOutdated ? '#FC521F' : '#F1618C'; @@ -261,7 +262,8 @@ export const doUpgrade = async ({ mainConfigPath, beforeVersion, storybookVersion: currentVersion, - isUpgrade: true, + isUpgrade: isOutdated, + isLatest: isExactLatest, }); } diff --git a/code/lib/client-logger/package.json b/code/lib/client-logger/package.json index 60716ac1c3cb..83926ddd07ac 100644 --- a/code/lib/client-logger/package.json +++ b/code/lib/client-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/client-logger", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "", "keywords": [ "storybook" diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index dbcac376c369..290164c50f5f 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/codemod", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "A collection of codemod scripts written with JSCodeshift", "keywords": [ "storybook" diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json index b4804a0b2772..b46b9a1de983 100644 --- a/code/lib/core-common/package.json +++ b/code/lib/core-common/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-common", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" @@ -52,7 +52,7 @@ "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.0", "cross-spawn": "^7.0.3", - "esbuild": "^0.18.0", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0", "esbuild-register": "^3.5.0", "execa": "^5.0.0", "file-system-cache": "2.3.0", diff --git a/code/lib/core-common/src/utils/__tests__/check-addon-order.test.ts b/code/lib/core-common/src/utils/__tests__/check-addon-order.test.ts index 692402ba5844..db4820b02ec6 100644 --- a/code/lib/core-common/src/utils/__tests__/check-addon-order.test.ts +++ b/code/lib/core-common/src/utils/__tests__/check-addon-order.test.ts @@ -17,6 +17,7 @@ const essentialAddons = [ 'toolbars', 'measure', 'outline', + 'highlight', ]; const pkgName = (entry: CoreCommon_AddonEntry): string => { @@ -42,6 +43,22 @@ afterEach(() => { describe.each([ ['docs', 'controls', ['docs', 'controls']], ['docs', 'controls', ['docs', 'foo/node_modules/@storybook/addon-controls']], + [ + 'actions', + 'interactions', + [ + 'foo\\node_modules\\@storybook\\addon-essentials', + 'foo\\node_modules\\@storybook\\addon-interactions', + ], + ], + [ + 'actions', + 'interactions', + [ + 'foo\\\\node_modules\\\\@storybook\\\\addon-essentials', + 'foo\\\\node_modules\\\\@storybook\\\\addon-interactions', + ], + ], ['docs', 'controls', [{ name: '@storybook/addon-docs' }, 'controls']], ['docs', 'controls', ['essentials', 'controls']], ['docs', 'controls', ['essentials']], diff --git a/code/lib/core-common/src/utils/check-addon-order.ts b/code/lib/core-common/src/utils/check-addon-order.ts index 58faeccee228..b91c93e7df02 100644 --- a/code/lib/core-common/src/utils/check-addon-order.ts +++ b/code/lib/core-common/src/utils/check-addon-order.ts @@ -15,7 +15,7 @@ interface Options { const predicateFor = (addon: string) => (entry: CoreCommon_AddonEntry) => { const name = (entry as CoreCommon_OptionsEntry).name || (entry as string); - return name && name.includes(addon); + return name && name.replaceAll(/(\\){1,2}/g, '/').includes(addon); }; const isCorrectOrder = ( diff --git a/code/lib/core-common/src/versions.ts b/code/lib/core-common/src/versions.ts index 1de3269c4e5b..0109c9c2a8a3 100644 --- a/code/lib/core-common/src/versions.ts +++ b/code/lib/core-common/src/versions.ts @@ -1,83 +1,83 @@ // auto generated file, do not edit export default { - '@storybook/addon-a11y': '8.0.0-rc.2', - '@storybook/addon-actions': '8.0.0-rc.2', - '@storybook/addon-backgrounds': '8.0.0-rc.2', - '@storybook/addon-controls': '8.0.0-rc.2', - '@storybook/addon-docs': '8.0.0-rc.2', - '@storybook/addon-essentials': '8.0.0-rc.2', - '@storybook/addon-highlight': '8.0.0-rc.2', - '@storybook/addon-interactions': '8.0.0-rc.2', - '@storybook/addon-jest': '8.0.0-rc.2', - '@storybook/addon-links': '8.0.0-rc.2', - '@storybook/addon-mdx-gfm': '8.0.0-rc.2', - '@storybook/addon-measure': '8.0.0-rc.2', - '@storybook/addon-onboarding': '8.0.0-rc.2', - '@storybook/addon-outline': '8.0.0-rc.2', - '@storybook/addon-storysource': '8.0.0-rc.2', - '@storybook/addon-themes': '8.0.0-rc.2', - '@storybook/addon-toolbars': '8.0.0-rc.2', - '@storybook/addon-viewport': '8.0.0-rc.2', - '@storybook/angular': '8.0.0-rc.2', - '@storybook/blocks': '8.0.0-rc.2', - '@storybook/builder-manager': '8.0.0-rc.2', - '@storybook/builder-vite': '8.0.0-rc.2', - '@storybook/builder-webpack5': '8.0.0-rc.2', - '@storybook/channels': '8.0.0-rc.2', - '@storybook/cli': '8.0.0-rc.2', - '@storybook/client-logger': '8.0.0-rc.2', - '@storybook/codemod': '8.0.0-rc.2', - '@storybook/components': '8.0.0-rc.2', - '@storybook/core-common': '8.0.0-rc.2', - '@storybook/core-events': '8.0.0-rc.2', - '@storybook/core-server': '8.0.0-rc.2', - '@storybook/core-webpack': '8.0.0-rc.2', - '@storybook/csf-plugin': '8.0.0-rc.2', - '@storybook/csf-tools': '8.0.0-rc.2', - '@storybook/docs-tools': '8.0.0-rc.2', - '@storybook/ember': '8.0.0-rc.2', - '@storybook/html': '8.0.0-rc.2', - '@storybook/html-vite': '8.0.0-rc.2', - '@storybook/html-webpack5': '8.0.0-rc.2', - '@storybook/instrumenter': '8.0.0-rc.2', - '@storybook/manager': '8.0.0-rc.2', - '@storybook/manager-api': '8.0.0-rc.2', - '@storybook/nextjs': '8.0.0-rc.2', - '@storybook/node-logger': '8.0.0-rc.2', - '@storybook/preact': '8.0.0-rc.2', - '@storybook/preact-vite': '8.0.0-rc.2', - '@storybook/preact-webpack5': '8.0.0-rc.2', - '@storybook/preset-create-react-app': '8.0.0-rc.2', - '@storybook/preset-html-webpack': '8.0.0-rc.2', - '@storybook/preset-preact-webpack': '8.0.0-rc.2', - '@storybook/preset-react-webpack': '8.0.0-rc.2', - '@storybook/preset-server-webpack': '8.0.0-rc.2', - '@storybook/preset-svelte-webpack': '8.0.0-rc.2', - '@storybook/preset-vue3-webpack': '8.0.0-rc.2', - '@storybook/preview': '8.0.0-rc.2', - '@storybook/preview-api': '8.0.0-rc.2', - '@storybook/react': '8.0.0-rc.2', - '@storybook/react-dom-shim': '8.0.0-rc.2', - '@storybook/react-vite': '8.0.0-rc.2', - '@storybook/react-webpack5': '8.0.0-rc.2', - '@storybook/router': '8.0.0-rc.2', - '@storybook/server': '8.0.0-rc.2', - '@storybook/server-webpack5': '8.0.0-rc.2', - '@storybook/source-loader': '8.0.0-rc.2', - '@storybook/svelte': '8.0.0-rc.2', - '@storybook/svelte-vite': '8.0.0-rc.2', - '@storybook/svelte-webpack5': '8.0.0-rc.2', - '@storybook/sveltekit': '8.0.0-rc.2', - '@storybook/telemetry': '8.0.0-rc.2', - '@storybook/test': '8.0.0-rc.2', - '@storybook/theming': '8.0.0-rc.2', - '@storybook/types': '8.0.0-rc.2', - '@storybook/vue3': '8.0.0-rc.2', - '@storybook/vue3-vite': '8.0.0-rc.2', - '@storybook/vue3-webpack5': '8.0.0-rc.2', - '@storybook/web-components': '8.0.0-rc.2', - '@storybook/web-components-vite': '8.0.0-rc.2', - '@storybook/web-components-webpack5': '8.0.0-rc.2', - sb: '8.0.0-rc.2', - storybook: '8.0.0-rc.2', + '@storybook/addon-a11y': '8.1.0-alpha.0', + '@storybook/addon-actions': '8.1.0-alpha.0', + '@storybook/addon-backgrounds': '8.1.0-alpha.0', + '@storybook/addon-controls': '8.1.0-alpha.0', + '@storybook/addon-docs': '8.1.0-alpha.0', + '@storybook/addon-essentials': '8.1.0-alpha.0', + '@storybook/addon-highlight': '8.1.0-alpha.0', + '@storybook/addon-interactions': '8.1.0-alpha.0', + '@storybook/addon-jest': '8.1.0-alpha.0', + '@storybook/addon-links': '8.1.0-alpha.0', + '@storybook/addon-mdx-gfm': '8.1.0-alpha.0', + '@storybook/addon-measure': '8.1.0-alpha.0', + '@storybook/addon-onboarding': '8.1.0-alpha.0', + '@storybook/addon-outline': '8.1.0-alpha.0', + '@storybook/addon-storysource': '8.1.0-alpha.0', + '@storybook/addon-themes': '8.1.0-alpha.0', + '@storybook/addon-toolbars': '8.1.0-alpha.0', + '@storybook/addon-viewport': '8.1.0-alpha.0', + '@storybook/angular': '8.1.0-alpha.0', + '@storybook/blocks': '8.1.0-alpha.0', + '@storybook/builder-manager': '8.1.0-alpha.0', + '@storybook/builder-vite': '8.1.0-alpha.0', + '@storybook/builder-webpack5': '8.1.0-alpha.0', + '@storybook/channels': '8.1.0-alpha.0', + '@storybook/cli': '8.1.0-alpha.0', + '@storybook/client-logger': '8.1.0-alpha.0', + '@storybook/codemod': '8.1.0-alpha.0', + '@storybook/components': '8.1.0-alpha.0', + '@storybook/core-common': '8.1.0-alpha.0', + '@storybook/core-events': '8.1.0-alpha.0', + '@storybook/core-server': '8.1.0-alpha.0', + '@storybook/core-webpack': '8.1.0-alpha.0', + '@storybook/csf-plugin': '8.1.0-alpha.0', + '@storybook/csf-tools': '8.1.0-alpha.0', + '@storybook/docs-tools': '8.1.0-alpha.0', + '@storybook/ember': '8.1.0-alpha.0', + '@storybook/html': '8.1.0-alpha.0', + '@storybook/html-vite': '8.1.0-alpha.0', + '@storybook/html-webpack5': '8.1.0-alpha.0', + '@storybook/instrumenter': '8.1.0-alpha.0', + '@storybook/manager': '8.1.0-alpha.0', + '@storybook/manager-api': '8.1.0-alpha.0', + '@storybook/nextjs': '8.1.0-alpha.0', + '@storybook/node-logger': '8.1.0-alpha.0', + '@storybook/preact': '8.1.0-alpha.0', + '@storybook/preact-vite': '8.1.0-alpha.0', + '@storybook/preact-webpack5': '8.1.0-alpha.0', + '@storybook/preset-create-react-app': '8.1.0-alpha.0', + '@storybook/preset-html-webpack': '8.1.0-alpha.0', + '@storybook/preset-preact-webpack': '8.1.0-alpha.0', + '@storybook/preset-react-webpack': '8.1.0-alpha.0', + '@storybook/preset-server-webpack': '8.1.0-alpha.0', + '@storybook/preset-svelte-webpack': '8.1.0-alpha.0', + '@storybook/preset-vue3-webpack': '8.1.0-alpha.0', + '@storybook/preview': '8.1.0-alpha.0', + '@storybook/preview-api': '8.1.0-alpha.0', + '@storybook/react': '8.1.0-alpha.0', + '@storybook/react-dom-shim': '8.1.0-alpha.0', + '@storybook/react-vite': '8.1.0-alpha.0', + '@storybook/react-webpack5': '8.1.0-alpha.0', + '@storybook/router': '8.1.0-alpha.0', + '@storybook/server': '8.1.0-alpha.0', + '@storybook/server-webpack5': '8.1.0-alpha.0', + '@storybook/source-loader': '8.1.0-alpha.0', + '@storybook/svelte': '8.1.0-alpha.0', + '@storybook/svelte-vite': '8.1.0-alpha.0', + '@storybook/svelte-webpack5': '8.1.0-alpha.0', + '@storybook/sveltekit': '8.1.0-alpha.0', + '@storybook/telemetry': '8.1.0-alpha.0', + '@storybook/test': '8.1.0-alpha.0', + '@storybook/theming': '8.1.0-alpha.0', + '@storybook/types': '8.1.0-alpha.0', + '@storybook/vue3': '8.1.0-alpha.0', + '@storybook/vue3-vite': '8.1.0-alpha.0', + '@storybook/vue3-webpack5': '8.1.0-alpha.0', + '@storybook/web-components': '8.1.0-alpha.0', + '@storybook/web-components-vite': '8.1.0-alpha.0', + '@storybook/web-components-webpack5': '8.1.0-alpha.0', + sb: '8.1.0-alpha.0', + storybook: '8.1.0-alpha.0', }; diff --git a/code/lib/core-events/package.json b/code/lib/core-events/package.json index 8ada1c3ee9a4..2fda3e0eb626 100644 --- a/code/lib/core-events/package.json +++ b/code/lib/core-events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-events", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Event names used in storybook core", "keywords": [ "storybook" diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index 1d4f1d43c88b..2b44e68b8a22 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-server", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index 84199b59fc20..d1e6142601ea 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-webpack", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json index 7c69964a2bf5..1761eb435ae1 100644 --- a/code/lib/csf-plugin/package.json +++ b/code/lib/csf-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-plugin", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Enrich CSF files via static analysis", "keywords": [ "storybook" diff --git a/code/lib/csf-tools/package.json b/code/lib/csf-tools/package.json index 3aecb2b4c989..f8e58033aff3 100644 --- a/code/lib/csf-tools/package.json +++ b/code/lib/csf-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-tools", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Parse and manipulate CSF and Storybook config files", "keywords": [ "storybook" diff --git a/code/lib/docs-tools/package.json b/code/lib/docs-tools/package.json index faead07c757d..8ecc609ee401 100644 --- a/code/lib/docs-tools/package.json +++ b/code/lib/docs-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/docs-tools", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Shared utility functions for frameworks to implement docs", "keywords": [ "storybook" diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json index 29aafd117e78..c411b7c9138c 100644 --- a/code/lib/instrumenter/package.json +++ b/code/lib/instrumenter/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/instrumenter", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "", "keywords": [ "storybook" diff --git a/code/lib/manager-api/package.json b/code/lib/manager-api/package.json index 6ce5d7c94478..566511f21346 100644 --- a/code/lib/manager-api/package.json +++ b/code/lib/manager-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager-api", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Core Storybook Manager API & Context", "keywords": [ "storybook" @@ -65,7 +65,6 @@ "@types/qs": "^6", "@types/semver": "^7.3.4", "flush-promises": "^1.0.2", - "qs": "^6.10.0", "react": "^18.2.0", "react-dom": "^18.2.0", "semver": "^7.3.7", diff --git a/code/lib/manager-api/src/modules/refs.ts b/code/lib/manager-api/src/modules/refs.ts index bc4b94755a53..4a5fca881f48 100644 --- a/code/lib/manager-api/src/modules/refs.ts +++ b/code/lib/manager-api/src/modules/refs.ts @@ -43,7 +43,7 @@ export interface SubAPI { * @param {string} id - The ID of the composed ref. * @param {API_ComposedRefUpdate} ref - The update object for the composed ref. */ - updateRef: (id: string, ref: API_ComposedRefUpdate) => void; + updateRef: (id: string, ref: API_ComposedRefUpdate) => Promise; /** * Gets all composed refs. * @returns {API_Refs} - The composed refs object. @@ -60,7 +60,7 @@ export interface SubAPI { * @param {string} id - The ID of the composed ref. * @param {string} url - The new URL for the composed ref. */ - changeRefVersion: (id: string, url: string) => void; + changeRefVersion: (id: string, url: string) => Promise; /** * Changes the state of a composed ref by its ID and previewInitialized flag. * @param {string} id - The ID of the composed ref. @@ -168,12 +168,12 @@ export const init: ModuleFn = ( return Object.values(refs).find(({ url }: any) => url.match(source)); }, - changeRefVersion: (id, url) => { + changeRefVersion: async (id, url) => { const { versions, title } = api.getRefs()[id]; const ref: API_SetRefData = { id, url, versions, title, index: {}, expanded: true }; - api.setRef(id, { ...ref, type: 'unknown' }, false); - api.checkRef(ref); + await api.setRef(id, { ...ref, type: 'unknown' }, false); + await api.checkRef(ref); }, changeRefState: (id, previewInitialized) => { const { [id]: ref, ...updated } = api.getRefs(); @@ -276,7 +276,7 @@ export const init: ModuleFn = ( return refs; }, - setRef: (id, { storyIndex, setStoriesData, ...rest }, ready = false) => { + setRef: async (id, { storyIndex, setStoriesData, ...rest }, ready = false) => { if (singleStory) { return; } @@ -307,10 +307,10 @@ export const init: ModuleFn = ( index = addRefIds(index, ref); } - api.updateRef(id, { ...ref, ...rest, index, internal_index }); + await api.updateRef(id, { ...ref, ...rest, index, internal_index }); }, - updateRef: (id, data) => { + updateRef: async (id, data) => { const { [id]: ref, ...updated } = api.getRefs(); updated[id] = { ...ref, ...data }; @@ -320,7 +320,7 @@ export const init: ModuleFn = ( return obj; }, {}); - store.setState({ + await store.setState({ refs: ordered, }); }, @@ -331,8 +331,11 @@ export const init: ModuleFn = ( const initialState: SubState['refs'] = refs; if (runCheck) { - Object.entries(refs).forEach(([id, ref]) => { - api.checkRef({ ...ref!, stories: {} } as API_SetRefData); + new Promise(async (resolve) => { + for (const ref of Object.values(refs)) { + await api.checkRef({ ...ref!, stories: {} } as API_SetRefData); + } + resolve(undefined); }); } diff --git a/code/lib/manager-api/src/modules/whatsnew.ts b/code/lib/manager-api/src/modules/whatsnew.ts index eeeb9558a59f..8f465325d503 100644 --- a/code/lib/manager-api/src/modules/whatsnew.ts +++ b/code/lib/manager-api/src/modules/whatsnew.ts @@ -92,10 +92,10 @@ export const init: ModuleFn = ({ fullAPI, store, provider }) => { id: WHATS_NEW_NOTIFICATION_ID, link: '/settings/whats-new', content: { - headline: whatsNewData.excerpt, - subHeadline: "Click to learn what's new in Storybook", + headline: whatsNewData.title, + subHeadline: "Learn what's new in Storybook", }, - icon: { name: 'hearthollow' }, + icon: { name: 'storybook' }, onClear({ dismissed }: any) { if (dismissed) { setWhatsNewCache({ lastDismissedPost: whatsNewData.url }); diff --git a/code/lib/manager-api/src/tests/refs.test.ts b/code/lib/manager-api/src/tests/refs.test.ts index 791325c27337..950b5e3e7a63 100644 --- a/code/lib/manager-api/src/tests/refs.test.ts +++ b/code/lib/manager-api/src/tests/refs.test.ts @@ -171,6 +171,9 @@ describe('Refs API', () => { // given initRefs({ provider, store } as any); + // the `runCheck` is async, so we need to wait for it to finish + await vi.waitFor(() => fetchMock.mock.calls.length > 0); + expect(fetchMock.mock.calls).toMatchInlineSnapshot(` [ [ @@ -207,6 +210,9 @@ describe('Refs API', () => { }; initRefs({ provider, store } as any); + // the `runCheck` is async, so we need to wait for it to finish + await vi.waitFor(() => fetchMock.mock.calls.length > 0); + expect(fetchMock.mock.calls).toMatchInlineSnapshot(` [ [ diff --git a/code/lib/manager-api/src/tests/url.test.js b/code/lib/manager-api/src/tests/url.test.js index 02048e903c37..817cb118ff41 100644 --- a/code/lib/manager-api/src/tests/url.test.js +++ b/code/lib/manager-api/src/tests/url.test.js @@ -1,5 +1,4 @@ import { describe, beforeEach, it, expect, vi } from 'vitest'; -import qs from 'qs'; import { SET_CURRENT_STORY, GLOBALS_UPDATED, UPDATE_QUERY_PARAMS } from '@storybook/core-events'; @@ -15,7 +14,7 @@ describe('initial state', () => { describe('config query parameters', () => { it('handles full parameter', () => { const navigate = vi.fn(); - const location = { search: qs.stringify({ full: '1' }) }; + const location = { search: new URLSearchParams({ full: '1' }).toString() }; const { state: { layout }, @@ -30,7 +29,7 @@ describe('initial state', () => { it('handles nav parameter', () => { const navigate = vi.fn(); - const location = { search: qs.stringify({ nav: '0' }) }; + const location = { search: new URLSearchParams({ nav: '0' }).toString() }; const { state: { layout }, @@ -41,7 +40,7 @@ describe('initial state', () => { it('handles shortcuts parameter', () => { const navigate = vi.fn(); - const location = { search: qs.stringify({ shortcuts: '0' }) }; + const location = { search: new URLSearchParams({ shortcuts: '0' }).toString() }; const { state: { ui }, @@ -52,7 +51,7 @@ describe('initial state', () => { it('handles panel parameter, bottom', () => { const navigate = vi.fn(); - const location = { search: qs.stringify({ panel: 'bottom' }) }; + const location = { search: new URLSearchParams({ panel: 'bottom' }).toString() }; const { state: { layout }, @@ -63,7 +62,7 @@ describe('initial state', () => { it('handles panel parameter, right', () => { const navigate = vi.fn(); - const location = { search: qs.stringify({ panel: 'right' }) }; + const location = { search: new URLSearchParams({ panel: 'right' }).toString() }; const { state: { layout }, @@ -74,7 +73,7 @@ describe('initial state', () => { it('handles panel parameter, 0', () => { const navigate = vi.fn(); - const location = { search: qs.stringify({ panel: '0' }) }; + const location = { search: new URLSearchParams({ panel: '0' }).toString() }; const { state: { layout }, diff --git a/code/lib/manager-api/src/version.ts b/code/lib/manager-api/src/version.ts index 7900754c895d..f89e3528d2df 100644 --- a/code/lib/manager-api/src/version.ts +++ b/code/lib/manager-api/src/version.ts @@ -1 +1 @@ -export const version = '8.0.0-rc.2'; +export const version = '8.1.0-alpha.0'; diff --git a/code/lib/node-logger/package.json b/code/lib/node-logger/package.json index eab0c64bfa00..739cd0051874 100644 --- a/code/lib/node-logger/package.json +++ b/code/lib/node-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/node-logger", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "", "keywords": [ "storybook" diff --git a/code/lib/preview-api/package.json b/code/lib/preview-api/package.json index 8706fb1e6f0e..126be65d5e3a 100644 --- a/code/lib/preview-api/package.json +++ b/code/lib/preview-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview-api", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "", "keywords": [ "storybook" diff --git a/code/lib/preview-api/src/index.ts b/code/lib/preview-api/src/index.ts index 63d45114dc23..e47cdaa0a0dd 100644 --- a/code/lib/preview-api/src/index.ts +++ b/code/lib/preview-api/src/index.ts @@ -56,7 +56,6 @@ export { filterArgTypes, sanitizeStoryContextUpdate, setProjectAnnotations, - getPortableStoryWrapperId, inferControls, userOrAutoTitleFromSpecifier, userOrAutoTitle, diff --git a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts index 0974f0908526..bee091bfda4b 100644 --- a/code/lib/preview-api/src/modules/store/csf/portable-stories.ts +++ b/code/lib/preview-api/src/modules/store/csf/portable-stories.ts @@ -26,10 +26,6 @@ import { normalizeProjectAnnotations } from './normalizeProjectAnnotations'; let globalProjectAnnotations: ProjectAnnotations = {}; -export function getPortableStoryWrapperId(storyId: string) { - return `storybook-story-${storyId}`; -} - export function setProjectAnnotations( projectAnnotations: ProjectAnnotations | ProjectAnnotations[] ) { @@ -99,11 +95,7 @@ export function composeStory = { layout: 'fullscreen', }, // More on argTypes: https://storybook.js.org/docs/api/argtypes - argTypes: { - onLogin: { action: 'onLogin' }, - onLogout: { action: 'onLogout' }, - onCreateAccount: { action: 'onCreateAccount' }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), }, }; diff --git a/code/renderers/html/template/cli/ts-4-9/Header.stories.ts b/code/renderers/html/template/cli/ts-4-9/Header.stories.ts index 7570a625a869..189c6c8abebd 100644 --- a/code/renderers/html/template/cli/ts-4-9/Header.stories.ts +++ b/code/renderers/html/template/cli/ts-4-9/Header.stories.ts @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/html'; +import { fn } from '@storybook/test'; import type { HeaderProps } from './Header'; import { createHeader } from './Header'; @@ -12,10 +13,10 @@ const meta = { layout: 'fullscreen', }, // More on argTypes: https://storybook.js.org/docs/api/argtypes - argTypes: { - onLogin: { action: 'onLogin' }, - onLogout: { action: 'onLogout' }, - onCreateAccount: { action: 'onCreateAccount' }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), }, } satisfies Meta; diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index 964a280e875c..fe1df6ad774b 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook Preact renderer", "keywords": [ "storybook" diff --git a/code/renderers/preact/template/cli/Header.stories.jsx b/code/renderers/preact/template/cli/Header.stories.jsx index 58b353a57db2..160f7fdff166 100644 --- a/code/renderers/preact/template/cli/Header.stories.jsx +++ b/code/renderers/preact/template/cli/Header.stories.jsx @@ -1,3 +1,4 @@ +import { fn } from '@storybook/test'; import { Header } from './Header'; export default { @@ -9,10 +10,10 @@ export default { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, - argTypes: { - onLogin: { action: 'onLogin' }, - onLogout: { action: 'onLogout' }, - onCreateAccount: { action: 'onCreateAccount' }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), }, }; diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index a42882c38ebf..6abc64587845 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook React renderer", "keywords": [ "storybook" diff --git a/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap b/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap index 2779b21001ab..ce16b3dc224e 100644 --- a/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap +++ b/code/renderers/react/src/__test__/__snapshots__/portable-stories.test.tsx.snap @@ -3,17 +3,12 @@ exports[`Renders CSF2Secondary story 1`] = `
-
- -
+ Children coming from story args! +
`; @@ -21,17 +16,12 @@ exports[`Renders CSF2Secondary story 1`] = ` exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
-
- -
+ foo +
`; @@ -39,17 +29,12 @@ exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = ` exports[`Renders CSF3Button story 1`] = `
-
- -
+ foo +
`; @@ -57,23 +42,18 @@ exports[`Renders CSF3Button story 1`] = ` exports[`Renders CSF3ButtonWithRender story 1`] = `
-
-
-

- I am a custom render function -

- -
+
+

+ I am a custom render function +

+
@@ -82,14 +62,9 @@ exports[`Renders CSF3ButtonWithRender story 1`] = ` exports[`Renders CSF3InputFieldFilled story 1`] = `
-
- -
+
`; @@ -97,17 +72,12 @@ exports[`Renders CSF3InputFieldFilled story 1`] = ` exports[`Renders CSF3Primary story 1`] = `
-
- -
+ foo +
`; @@ -115,21 +85,16 @@ exports[`Renders CSF3Primary story 1`] = ` exports[`Renders LoaderStory story 1`] = `
-
-
-
- loaded data -
-
- mockFn return value -
+
+
+ loaded data +
+
+ mockFn return value
diff --git a/code/renderers/react/src/docs/jsxDecorator.test.tsx b/code/renderers/react/src/docs/jsxDecorator.test.tsx index bfb20fdd5f0d..6ed0f0eda179 100644 --- a/code/renderers/react/src/docs/jsxDecorator.test.tsx +++ b/code/renderers/react/src/docs/jsxDecorator.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable no-underscore-dangle */ import type { FC, PropsWithChildren } from 'react'; import React, { StrictMode, createElement, Profiler } from 'react'; import type { Mock } from 'vitest'; @@ -5,7 +6,7 @@ import { vi, describe, it, expect, beforeEach } from 'vitest'; import PropTypes from 'prop-types'; import { addons, useEffect } from '@storybook/preview-api'; import { SNIPPET_RENDERED } from '@storybook/docs-tools'; -import { renderJsx, jsxDecorator } from './jsxDecorator'; +import { renderJsx, jsxDecorator, getReactSymbolName } from './jsxDecorator'; vi.mock('@storybook/preview-api'); const mockedAddons = vi.mocked(addons); @@ -16,6 +17,18 @@ expect.addSnapshotSerializer({ test: (val) => typeof val === 'string', }); +describe('converts React Symbol to displayName string', () => { + const symbolCases = [ + ['react.suspense', 'React.Suspense'], + ['react.strict_mode', 'React.StrictMode'], + ['react.server_context.defaultValue', 'React.ServerContext.DefaultValue'], + ]; + + it.each(symbolCases)('"%s" to "%s"', (symbol, expectedValue) => { + expect(getReactSymbolName(Symbol(symbol))).toEqual(expectedValue); + }); +}); + describe('renderJsx', () => { it('basic', () => { expect(renderJsx(
hello
, {})).toMatchInlineSnapshot(` @@ -139,53 +152,71 @@ describe('renderJsx', () => { }); it('Profiler', () => { - function ProfilerComponent({ children }: any) { - return ( + expect( + renderJsx( {}}> -
{children}
-
- ); - } - - expect(renderJsx(createElement(ProfilerComponent, {}, 'I am Profiler'), {})) - .toMatchInlineSnapshot(` - - I am Profiler - +
I am in a Profiler
+ , + {} + ) + ).toMatchInlineSnapshot(` + {}} + > +
+ I am in a Profiler +
+
`); }); it('StrictMode', () => { - function StrictModeComponent({ children }: any) { - return ( - -
{children}
-
- ); + expect(renderJsx(I am StrictMode, {})).toMatchInlineSnapshot(` + + I am StrictMode + + `); + }); + + it('displayName coming from docgenInfo', () => { + function BasicComponent({ label }: any) { + return ; } + BasicComponent.__docgenInfo = { + description: 'Some description', + methods: [], + displayName: 'Button', + props: {}, + }; - expect(renderJsx(createElement(StrictModeComponent, {}, 'I am StrictMode'), {})) - .toMatchInlineSnapshot(` - - I am StrictMode - - `); + expect( + renderJsx( + createElement( + BasicComponent, + { + label:

Abcd

, + }, + undefined + ) + ) + ).toMatchInlineSnapshot(` -
+ label coming from story args! +
`; @@ -22,19 +17,14 @@ exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
-
- -
+ foo +
@@ -43,17 +33,12 @@ exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = ` exports[`Renders CSF3Button story 1`] = `
-
- -
+ foo +
`; @@ -61,23 +46,18 @@ exports[`Renders CSF3Button story 1`] = ` exports[`Renders CSF3ButtonWithRender story 1`] = `
-
-
-

- I am a custom render function -

- -
+
+

+ I am a custom render function +

+
@@ -86,14 +66,9 @@ exports[`Renders CSF3ButtonWithRender story 1`] = ` exports[`Renders CSF3InputFieldFilled story 1`] = `
-
- -
+
`; @@ -101,17 +76,12 @@ exports[`Renders CSF3InputFieldFilled story 1`] = ` exports[`Renders CSF3Primary story 1`] = `
-
- -
+ foo +
`; @@ -119,21 +89,16 @@ exports[`Renders CSF3Primary story 1`] = ` exports[`Renders LoaderStory story 1`] = `
-
-
-
- loaded data -
-
- mockFn return value -
+
+
+ loaded data +
+
+ mockFn return value
diff --git a/code/renderers/vue3/src/portable-stories.ts b/code/renderers/vue3/src/portable-stories.ts index 73c7991f16a6..dca738d205bf 100644 --- a/code/renderers/vue3/src/portable-stories.ts +++ b/code/renderers/vue3/src/portable-stories.ts @@ -2,7 +2,6 @@ import { composeStory as originalComposeStory, composeStories as originalComposeStories, setProjectAnnotations as originalSetProjectAnnotations, - getPortableStoryWrapperId, } from '@storybook/preview-api'; import type { Args, @@ -13,20 +12,10 @@ import type { } from '@storybook/types'; import { h } from 'vue'; -import * as vueProjectAnnotations from './entry-preview'; +import * as defaultProjectAnnotations from './entry-preview'; import type { Meta } from './public-types'; import type { VueRenderer } from './types'; -const defaultProjectAnnotations: ProjectAnnotations = { - ...vueProjectAnnotations, - decorators: [ - function (story, { id }) { - const wrapperProps = { 'data-story': true, id: getPortableStoryWrapperId(id) }; - return h('div', wrapperProps, h(story())); - }, - ], -}; - /** Function that sets the globalConfig of your Storybook. The global config is the preview module of your .storybook folder. * * It should be run a single time, so that your global config (e.g. decorators) is applied to your stories when using `composeStories` or `composeStory`. diff --git a/code/renderers/vue3/template/cli/js/Header.stories.js b/code/renderers/vue3/template/cli/js/Header.stories.js index 380492e24b24..6b0d1821f117 100644 --- a/code/renderers/vue3/template/cli/js/Header.stories.js +++ b/code/renderers/vue3/template/cli/js/Header.stories.js @@ -1,3 +1,4 @@ +import { fn } from '@storybook/test'; import MyHeader from './Header.vue'; export default { @@ -24,6 +25,11 @@ export default { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, }; export const LoggedIn = { diff --git a/code/renderers/vue3/template/cli/ts-3-8/Header.stories.ts b/code/renderers/vue3/template/cli/ts-3-8/Header.stories.ts index fd0ba06e9c5d..4982d99d85f3 100644 --- a/code/renderers/vue3/template/cli/ts-3-8/Header.stories.ts +++ b/code/renderers/vue3/template/cli/ts-3-8/Header.stories.ts @@ -1,3 +1,4 @@ +import { fn } from '@storybook/test'; import type { Meta, StoryObj } from '@storybook/vue3'; import MyHeader from './Header.vue'; @@ -21,6 +22,11 @@ const meta: Meta = { layout: 'fullscreen', }, // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, tags: ['autodocs'], }; diff --git a/code/renderers/vue3/template/cli/ts-4-9/Header.stories.ts b/code/renderers/vue3/template/cli/ts-4-9/Header.stories.ts index eb8fc1fcee56..350a5d22a48a 100644 --- a/code/renderers/vue3/template/cli/ts-4-9/Header.stories.ts +++ b/code/renderers/vue3/template/cli/ts-4-9/Header.stories.ts @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/vue3'; +import { fn } from '@storybook/test'; import MyHeader from './Header.vue'; @@ -20,6 +21,11 @@ const meta = { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs tags: ['autodocs'], } satisfies Meta; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/GlobalSetup.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/GlobalSetup.stories.ts index 5e01135e20c0..725b0e65ee93 100644 --- a/code/renderers/vue3/template/stories_vue3-vite-default-ts/GlobalSetup.stories.ts +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/GlobalSetup.stories.ts @@ -1,6 +1,5 @@ -import { expect } from '@storybook/test'; import type { Meta, StoryObj } from '@storybook/vue3'; -import { within } from '@storybook/testing-library'; +import { within, expect } from '@storybook/test'; import { inject } from 'vue'; import GlobalSetup from './GlobalSetup.vue'; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveArgs.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveArgs.stories.ts index 536c962c2ee1..ff076fcca733 100644 --- a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveArgs.stories.ts +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveArgs.stories.ts @@ -1,7 +1,6 @@ -import { expect } from '@storybook/test'; import { global as globalThis } from '@storybook/global'; import type { Meta, StoryObj, StoryFn } from '@storybook/vue3'; -import { within, userEvent } from '@storybook/testing-library'; +import { within, userEvent, expect } from '@storybook/test'; import { UPDATE_STORY_ARGS, STORY_ARGS_UPDATED, RESET_STORY_ARGS } from '@storybook/core-events'; import ReactiveArgs from './ReactiveArgs.vue'; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveDecorators.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveDecorators.stories.ts index 143cd1784559..d6a7e743d778 100644 --- a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveDecorators.stories.ts +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveDecorators.stories.ts @@ -1,5 +1,5 @@ import { global as globalThis } from '@storybook/global'; -import { userEvent, within } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/test'; import type { Meta, StoryObj } from '@storybook/vue3'; import { h } from 'vue'; import { RESET_STORY_ARGS, STORY_ARGS_UPDATED, UPDATE_STORY_ARGS } from '@storybook/core-events'; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveSlots.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveSlots.stories.ts index d0042b65a2a5..bde19efc07e8 100644 --- a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveSlots.stories.ts +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ReactiveSlots.stories.ts @@ -1,6 +1,5 @@ -import { expect } from '@storybook/test'; import { global as globalThis } from '@storybook/global'; -import { within } from '@storybook/testing-library'; +import { within, expect } from '@storybook/test'; import { STORY_ARGS_UPDATED, RESET_STORY_ARGS, UPDATE_STORY_ARGS } from '@storybook/core-events'; import { h } from 'vue'; import type { Meta, StoryObj } from '@storybook/vue3'; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ScopedSlots.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ScopedSlots.stories.ts index ef7a625ea413..b255be571d43 100644 --- a/code/renderers/vue3/template/stories_vue3-vite-default-ts/ScopedSlots.stories.ts +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/ScopedSlots.stories.ts @@ -1,7 +1,6 @@ -import { expect } from '@storybook/test'; import { global as globalThis } from '@storybook/global'; import type { Channel } from '@storybook/channels'; -import { within } from '@storybook/testing-library'; +import { within, expect } from '@storybook/test'; import { UPDATE_STORY_ARGS, STORY_ARGS_UPDATED, RESET_STORY_ARGS } from '@storybook/core-events'; import type { Meta, StoryObj } from '@storybook/vue3'; diff --git a/code/renderers/web-components/package.json b/code/renderers/web-components/package.json index 1483eb3de461..73fe293ad3e3 100644 --- a/code/renderers/web-components/package.json +++ b/code/renderers/web-components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook web-components renderer", "keywords": [ "lit", diff --git a/code/renderers/web-components/template/cli/js/Button.stories.js b/code/renderers/web-components/template/cli/js/Button.stories.js index d406b990ff7b..dfb4ad43ee74 100644 --- a/code/renderers/web-components/template/cli/js/Button.stories.js +++ b/code/renderers/web-components/template/cli/js/Button.stories.js @@ -1,3 +1,4 @@ +import { fn } from '@storybook/test'; import { Button } from './Button'; // More on how to set up stories at: https://storybook.js.org/docs/writing-stories @@ -7,12 +8,12 @@ export default { render: (args) => Button(args), argTypes: { backgroundColor: { control: 'color' }, - onClick: { action: 'onClick' }, size: { control: { type: 'select' }, options: ['small', 'medium', 'large'], }, }, + args: { onClick: fn() }, }; // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args diff --git a/code/renderers/web-components/template/cli/js/Header.stories.js b/code/renderers/web-components/template/cli/js/Header.stories.js index d399cb869950..cfb94e39fc0c 100644 --- a/code/renderers/web-components/template/cli/js/Header.stories.js +++ b/code/renderers/web-components/template/cli/js/Header.stories.js @@ -1,3 +1,4 @@ +import { fn } from '@storybook/test'; import { Header } from './Header'; export default { @@ -5,8 +6,12 @@ export default { // This component will have an automatically generated Autodocs entry: https://storybook.js.org/web-components/vue/writing-docs/autodocs tags: ['autodocs'], render: (args) => Header(args), + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, }; - export const LoggedIn = { args: { user: { diff --git a/code/renderers/web-components/template/cli/ts-3-8/Button.stories.ts b/code/renderers/web-components/template/cli/ts-3-8/Button.stories.ts index 62d561636779..e34857751666 100644 --- a/code/renderers/web-components/template/cli/ts-3-8/Button.stories.ts +++ b/code/renderers/web-components/template/cli/ts-3-8/Button.stories.ts @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/web-components'; +import { fn } from '@storybook/test'; import type { ButtonProps } from './Button'; import { Button } from './Button'; @@ -9,12 +10,12 @@ const meta: Meta = { render: (args) => Button(args), argTypes: { backgroundColor: { control: 'color' }, - onClick: { action: 'onClick' }, size: { control: { type: 'select' }, options: ['small', 'medium', 'large'], }, }, + args: { onClick: fn() }, }; export default meta; diff --git a/code/renderers/web-components/template/cli/ts-3-8/Header.stories.ts b/code/renderers/web-components/template/cli/ts-3-8/Header.stories.ts index aab89ba6a4b3..08b47d7692d8 100644 --- a/code/renderers/web-components/template/cli/ts-3-8/Header.stories.ts +++ b/code/renderers/web-components/template/cli/ts-3-8/Header.stories.ts @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/web-components'; +import { fn } from '@storybook/test'; import type { HeaderProps } from './Header'; import { Header } from './Header'; @@ -7,6 +8,11 @@ const meta: Meta = { // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs tags: ['autodocs'], render: (args: HeaderProps) => Header(args), + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, }; export default meta; diff --git a/code/renderers/web-components/template/cli/ts-4-9/Button.stories.ts b/code/renderers/web-components/template/cli/ts-4-9/Button.stories.ts index 03516d6c1abf..52f3ae8ebd62 100644 --- a/code/renderers/web-components/template/cli/ts-4-9/Button.stories.ts +++ b/code/renderers/web-components/template/cli/ts-4-9/Button.stories.ts @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/web-components'; +import { fn } from '@storybook/test'; import type { ButtonProps } from './Button'; import { Button } from './Button'; @@ -9,12 +10,12 @@ const meta = { render: (args) => Button(args), argTypes: { backgroundColor: { control: 'color' }, - onClick: { action: 'onClick' }, size: { control: { type: 'select' }, options: ['small', 'medium', 'large'], }, }, + args: { onClick: fn() }, } satisfies Meta; export default meta; diff --git a/code/renderers/web-components/template/cli/ts-4-9/Header.stories.ts b/code/renderers/web-components/template/cli/ts-4-9/Header.stories.ts index 628e199db1f4..be13bf07cde4 100644 --- a/code/renderers/web-components/template/cli/ts-4-9/Header.stories.ts +++ b/code/renderers/web-components/template/cli/ts-4-9/Header.stories.ts @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/web-components'; +import { fn } from '@storybook/test'; import type { HeaderProps } from './Header'; import { Header } from './Header'; @@ -7,6 +8,11 @@ const meta = { // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs tags: ['autodocs'], render: (args: HeaderProps) => Header(args), + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, } satisfies Meta; export default meta; diff --git a/code/ui/blocks/package.json b/code/ui/blocks/package.json index 790612807846..c32ad8074761 100644 --- a/code/ui/blocks/package.json +++ b/code/ui/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Storybook Doc Blocks", "keywords": [ "storybook" diff --git a/code/ui/blocks/src/components/Story.stories.tsx b/code/ui/blocks/src/components/Story.stories.tsx index ae9a277a9425..fa1767d747af 100644 --- a/code/ui/blocks/src/components/Story.stories.tsx +++ b/code/ui/blocks/src/components/Story.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; import type { Meta, ReactRenderer, StoryObj } from '@storybook/react'; -import { within } from '@storybook/testing-library'; +import { within } from '@storybook/test'; import type { PlayFunctionContext } from '@storybook/csf'; import type { WebRenderer, ModuleExport } from '@storybook/types'; import { RESET_STORY_ARGS, STORY_ARGS_UPDATED, UPDATE_STORY_ARGS } from '@storybook/core-events'; diff --git a/code/ui/blocks/src/controls/Boolean.stories.tsx b/code/ui/blocks/src/controls/Boolean.stories.tsx index e83338c41241..8f7c043701c6 100644 --- a/code/ui/blocks/src/controls/Boolean.stories.tsx +++ b/code/ui/blocks/src/controls/Boolean.stories.tsx @@ -1,6 +1,5 @@ -import { expect } from '@storybook/test'; import type { Meta, StoryObj } from '@storybook/react'; -import { within, fireEvent, waitFor } from '@storybook/testing-library'; +import { within, fireEvent, waitFor, expect } from '@storybook/test'; import { addons } from '@storybook/preview-api'; import { RESET_STORY_ARGS, STORY_ARGS_UPDATED } from '@storybook/core-events'; import { BooleanControl } from './Boolean'; diff --git a/code/ui/blocks/src/examples/Button.stories.tsx b/code/ui/blocks/src/examples/Button.stories.tsx index 7e22aef00064..d99917fdfee8 100644 --- a/code/ui/blocks/src/examples/Button.stories.tsx +++ b/code/ui/blocks/src/examples/Button.stories.tsx @@ -1,6 +1,5 @@ -import { expect } from '@storybook/test'; import type { Meta, StoryObj } from '@storybook/react'; -import { within, fireEvent } from '@storybook/testing-library'; +import { within, fireEvent, expect } from '@storybook/test'; import React from 'react'; import { Button } from './Button'; diff --git a/code/ui/components/package.json b/code/ui/components/package.json index fcb4235f18e1..0cb6cc2278d3 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/components", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/ui/components/src/components/tabs/tabs.stories.tsx b/code/ui/components/src/components/tabs/tabs.stories.tsx index 9312c70c8bec..46a332a87f1f 100644 --- a/code/ui/components/src/components/tabs/tabs.stories.tsx +++ b/code/ui/components/src/components/tabs/tabs.stories.tsx @@ -2,14 +2,7 @@ import { expect } from '@storybook/test'; import React, { Fragment } from 'react'; import { action } from '@storybook/addon-actions'; import type { Meta, StoryObj } from '@storybook/react'; -import { - within, - fireEvent, - waitFor, - screen, - userEvent, - findByText, -} from '@storybook/testing-library'; +import { within, fireEvent, waitFor, screen, userEvent, findByText } from '@storybook/test'; import { CPUIcon, MemoryIcon } from '@storybook/icons'; import { Tabs, TabsState, TabWrapper } from './tabs'; import type { ChildrenList } from './tabs.helpers'; diff --git a/code/ui/manager/package.json b/code/ui/manager/package.json index 05c4b076ed7b..1c2507505030 100644 --- a/code/ui/manager/package.json +++ b/code/ui/manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager", - "version": "8.0.0-rc.2", + "version": "8.1.0-alpha.0", "description": "Core Storybook UI", "keywords": [ "storybook" diff --git a/code/ui/manager/src/components/mobile/about/MobileAbout.stories.tsx b/code/ui/manager/src/components/mobile/about/MobileAbout.stories.tsx index 7ef6f9d89f92..b36e2e0854f7 100644 --- a/code/ui/manager/src/components/mobile/about/MobileAbout.stories.tsx +++ b/code/ui/manager/src/components/mobile/about/MobileAbout.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { ManagerContext } from '@storybook/manager-api'; import React, { useEffect } from 'react'; -import { within } from '@storybook/testing-library'; +import { within } from '@storybook/test'; import { MobileAbout } from './MobileAbout'; import { LayoutProvider, useLayout } from '../../layout/LayoutProvider'; diff --git a/code/ui/manager/src/components/mobile/navigation/MobileNavigation.stories.tsx b/code/ui/manager/src/components/mobile/navigation/MobileNavigation.stories.tsx index 7617574cdd4e..8978534f6890 100644 --- a/code/ui/manager/src/components/mobile/navigation/MobileNavigation.stories.tsx +++ b/code/ui/manager/src/components/mobile/navigation/MobileNavigation.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; import { ManagerContext } from '@storybook/manager-api'; -import { within } from '@storybook/testing-library'; +import { within } from '@storybook/test'; import { startCase } from 'lodash'; import { MobileNavigation } from './MobileNavigation'; import { LayoutProvider, useLayout } from '../../layout/LayoutProvider'; diff --git a/code/ui/manager/src/components/sidebar/Menu.stories.tsx b/code/ui/manager/src/components/sidebar/Menu.stories.tsx index 98788518db4b..ca57b4780a67 100644 --- a/code/ui/manager/src/components/sidebar/Menu.stories.tsx +++ b/code/ui/manager/src/components/sidebar/Menu.stories.tsx @@ -1,11 +1,10 @@ import type { ComponentProps } from 'react'; import React from 'react'; -import { expect } from '@storybook/test'; import type { Meta, StoryObj } from '@storybook/react'; import { TooltipLinkList } from '@storybook/components'; import { styled } from '@storybook/theming'; -import { screen, userEvent, within } from '@storybook/testing-library'; +import { screen, userEvent, within, expect } from '@storybook/test'; import type { State } from '@storybook/manager-api'; import { LinkIcon } from '@storybook/icons'; import { SidebarMenu } from './Menu'; diff --git a/code/ui/manager/src/components/sidebar/Tree.stories.tsx b/code/ui/manager/src/components/sidebar/Tree.stories.tsx index eb2aa83959fc..00036a574db5 100644 --- a/code/ui/manager/src/components/sidebar/Tree.stories.tsx +++ b/code/ui/manager/src/components/sidebar/Tree.stories.tsx @@ -4,9 +4,7 @@ import type { ComponentEntry, IndexHash } from '@storybook/manager-api'; import { action } from '@storybook/addon-actions'; import type { StoryObj, Meta } from '@storybook/react'; -import { within } from '@storybook/testing-library'; - -import { expect } from '@storybook/test'; +import { within, expect } from '@storybook/test'; import { Tree } from './Tree'; import { index } from './mockdata.large'; import { DEFAULT_REF_ID } from './Sidebar'; diff --git a/code/yarn.lock b/code/yarn.lock index a54c136d1ad2..ff44832f5327 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -522,26 +522,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.21.0, @babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/helper-create-class-features-plugin@npm:7.23.5" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-member-expression-to-functions": "npm:^7.23.0" - "@babel/helper-optimise-call-expression": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.20" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/a29bd03725630dcf2f094b7e3fe45c63984e63a5d092ceffec2da9d95c108afcc073863d6e9c0fb944d07f3cde5ebac4bba833473ca96af5e949f7d471154901 - languageName: node - linkType: hard - -"@babel/helper-create-class-features-plugin@npm:^7.24.0": +"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.21.0, @babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.5, @babel/helper-create-class-features-plugin@npm:^7.24.0": version: 7.24.0 resolution: "@babel/helper-create-class-features-plugin@npm:7.24.0" dependencies: @@ -656,14 +637,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.22.5 - resolution: "@babel/helper-plugin-utils@npm:7.22.5" - checksum: 10c0/d2c4bfe2fa91058bcdee4f4e57a3f4933aed7af843acfd169cd6179fab8d13c1d636474ecabb2af107dc77462c7e893199aa26632bac1c6d7e025a17cbb9d20d - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.24.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": version: 7.24.0 resolution: "@babel/helper-plugin-utils@npm:7.24.0" checksum: 10c0/90f41bd1b4dfe7226b1d33a4bb745844c5c63e400f9e4e8bf9103a7ceddd7d425d65333b564d9daba3cebd105985764d51b4bd4c95822b97c2e3ac1201a8a5da @@ -777,16 +751,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.11.5, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.4, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.23.6, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.4.5, @babel/parser@npm:^7.6.0, @babel/parser@npm:^7.9.6": - version: 7.23.9 - resolution: "@babel/parser@npm:7.23.9" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/7df97386431366d4810538db4b9ec538f4377096f720c0591c7587a16f6810e62747e9fbbfa1ff99257fd4330035e4fb1b5b77c7bd3b97ce0d2e3780a6618975 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.24.0": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.11.5, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.4, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.23.6, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.4.5, @babel/parser@npm:^7.6.0, @babel/parser@npm:^7.9.6": version: 7.24.0 resolution: "@babel/parser@npm:7.24.0" bin: @@ -843,22 +808,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-proposal-decorators@npm:^7.13.5": - version: 7.23.0 - resolution: "@babel/plugin-proposal-decorators@npm:7.23.0" - dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.22.15" - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.20" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/plugin-syntax-decorators": "npm:^7.22.10" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/983e7113f9ca3b2ae632869f71accec48cb652d68840697c3977071d44879657ca6b4427ed02e76e448e385d0feca9bd3d40edfaf1530c6c6c25fe8b97d46689 - languageName: node - linkType: hard - -"@babel/plugin-proposal-decorators@npm:^7.22.7": +"@babel/plugin-proposal-decorators@npm:^7.13.5, @babel/plugin-proposal-decorators@npm:^7.22.7": version: 7.24.0 resolution: "@babel/plugin-proposal-decorators@npm:7.24.0" dependencies: @@ -975,17 +925,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-decorators@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/plugin-syntax-decorators@npm:7.22.10" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/cf606ef13ed98b3adf560ede27a873c0ab37e884c762a6f15493c881f5a78b67f24dcdd5c70e8cd8f39dbe4b23475cb98619729812f29feb2dcc241130195e7c - languageName: node - linkType: hard - "@babel/plugin-syntax-decorators@npm:^7.24.0": version: 7.24.0 resolution: "@babel/plugin-syntax-decorators@npm:7.24.0" @@ -2250,16 +2189,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.8, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.23.6 - resolution: "@babel/runtime@npm:7.23.6" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/d886954e985ef8e421222f7a2848884d96a752e0020d3078b920dd104e672fdf23bcc6f51a44313a048796319f1ac9d09c2c88ec8cbb4e1f09174bcd3335b9ff - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.7.2": +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.8, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.24.0 resolution: "@babel/runtime@npm:7.24.0" dependencies: @@ -2288,25 +2218,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.9, @babel/traverse@npm:^7.4.5": - version: 7.23.9 - resolution: "@babel/traverse@npm:7.23.9" - dependencies: - "@babel/code-frame": "npm:^7.23.5" - "@babel/generator": "npm:^7.23.6" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.9" - "@babel/types": "npm:^7.23.9" - debug: "npm:^4.3.1" - globals: "npm:^11.1.0" - checksum: 10c0/d1615d1d02f04d47111a7ea4446a1a6275668ca39082f31d51f08380de9502e19862be434eaa34b022ce9a17dbb8f9e2b73a746c654d9575f3a680a7ffdf5630 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.16.0": +"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.16.0, @babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.9, @babel/traverse@npm:^7.4.5": version: 7.24.0 resolution: "@babel/traverse@npm:7.24.0" dependencies: @@ -2324,18 +2236,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.11.5, @babel/types@npm:^7.18.9, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.4, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.6.1, @babel/types@npm:^7.7.2, @babel/types@npm:^7.8.3, @babel/types@npm:^7.9.6": - version: 7.23.9 - resolution: "@babel/types@npm:7.23.9" - dependencies: - "@babel/helper-string-parser": "npm:^7.23.4" - "@babel/helper-validator-identifier": "npm:^7.22.20" - to-fast-properties: "npm:^2.0.0" - checksum: 10c0/edc7bb180ce7e4d2aea10c6972fb10474341ac39ba8fdc4a27ffb328368dfdfbf40fca18e441bbe7c483774500d5c05e222cec276c242e952853dcaf4eb884f7 - languageName: node - linkType: hard - -"@babel/types@npm:^7.24.0": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.11.5, @babel/types@npm:^7.18.9, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.4, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.24.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.6.1, @babel/types@npm:^7.7.2, @babel/types@npm:^7.8.3, @babel/types@npm:^7.9.6": version: 7.24.0 resolution: "@babel/types@npm:7.24.0" dependencies: @@ -2680,156 +2581,163 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm64@npm:0.18.20" +"@esbuild/aix-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/aix-ppc64@npm:0.20.1" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm64@npm:0.20.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm@npm:0.18.20" +"@esbuild/android-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm@npm:0.20.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-x64@npm:0.18.20" +"@esbuild/android-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-x64@npm:0.20.1" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-arm64@npm:0.18.20" +"@esbuild/darwin-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-arm64@npm:0.20.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-x64@npm:0.18.20" +"@esbuild/darwin-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-x64@npm:0.20.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-arm64@npm:0.18.20" +"@esbuild/freebsd-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-arm64@npm:0.20.1" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-x64@npm:0.18.20" +"@esbuild/freebsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-x64@npm:0.20.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm64@npm:0.18.20" +"@esbuild/linux-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm64@npm:0.20.1" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm@npm:0.18.20" +"@esbuild/linux-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm@npm:0.20.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ia32@npm:0.18.20" +"@esbuild/linux-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ia32@npm:0.20.1" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-loong64@npm:0.18.20" +"@esbuild/linux-loong64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-loong64@npm:0.20.1" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-mips64el@npm:0.18.20" +"@esbuild/linux-mips64el@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-mips64el@npm:0.20.1" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ppc64@npm:0.18.20" +"@esbuild/linux-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ppc64@npm:0.20.1" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-riscv64@npm:0.18.20" +"@esbuild/linux-riscv64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-riscv64@npm:0.20.1" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-s390x@npm:0.18.20" +"@esbuild/linux-s390x@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-s390x@npm:0.20.1" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-x64@npm:0.18.20" +"@esbuild/linux-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-x64@npm:0.20.1" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/netbsd-x64@npm:0.18.20" +"@esbuild/netbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/netbsd-x64@npm:0.20.1" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/openbsd-x64@npm:0.18.20" +"@esbuild/openbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/openbsd-x64@npm:0.20.1" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/sunos-x64@npm:0.18.20" +"@esbuild/sunos-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/sunos-x64@npm:0.20.1" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-arm64@npm:0.18.20" +"@esbuild/win32-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-arm64@npm:0.20.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-ia32@npm:0.18.20" +"@esbuild/win32-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-ia32@npm:0.20.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-x64@npm:0.18.20" +"@esbuild/win32-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-x64@npm:0.20.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2886,13 +2794,6 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.56.0": - version: 8.56.0 - resolution: "@eslint/js@npm:8.56.0" - checksum: 10c0/60b3a1cf240e2479cec9742424224465dc50e46d781da1b7f5ef240501b2d1202c225bd456207faac4b34a64f4765833345bc4ddffd00395e1db40fa8c426f5a - languageName: node - linkType: hard - "@eslint/js@npm:8.57.0": version: 8.57.0 resolution: "@eslint/js@npm:8.57.0" @@ -3405,7 +3306,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13, @humanwhocodes/config-array@npm:^0.11.14": +"@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: @@ -5337,7 +5238,7 @@ __metadata: "@storybook/instrumenter": "workspace:*" "@storybook/manager-api": "workspace:*" "@storybook/preview-api": "workspace:*" - "@storybook/testing-library": "npm:next" + "@storybook/test": "workspace:*" "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" "@types/node": "npm:^18.0.0" @@ -5439,7 +5340,6 @@ __metadata: "@storybook/react": "workspace:*" "@storybook/telemetry": "workspace:*" "@storybook/test": "workspace:*" - "@storybook/testing-library": "npm:next" "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" framer-motion: "npm:^11.0.3" @@ -5693,7 +5593,7 @@ __metadata: "@yarnpkg/esbuild-plugin-pnp": "npm:^3.0.0-rc.10" browser-assert: "npm:^1.2.1" ejs: "npm:^3.1.8" - esbuild: "npm:^0.18.0" + esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0" esbuild-plugin-alias: "npm:^0.2.1" express: "npm:^4.17.3" fs-extra: "npm:^11.1.0" @@ -5804,7 +5704,6 @@ __metadata: "@storybook/client-logger": "workspace:*" "@storybook/core-events": "workspace:*" "@storybook/global": "npm:^5.0.0" - qs: "npm:^6.10.0" telejson: "npm:^7.2.0" tiny-invariant: "npm:^1.3.1" typescript: "npm:^5.3.2" @@ -5960,7 +5859,7 @@ __metadata: "@yarnpkg/libzip": "npm:2.3.0" chalk: "npm:^4.1.0" cross-spawn: "npm:^7.0.3" - esbuild: "npm:^0.18.0" + esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0" esbuild-register: "npm:^3.5.0" execa: "npm:^5.0.0" file-system-cache: "npm:2.3.0" @@ -6325,7 +6224,6 @@ __metadata: flush-promises: "npm:^1.0.2" lodash: "npm:^4.17.21" memoizerific: "npm:^1.11.3" - qs: "npm:^6.10.0" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" semver: "npm:^7.3.7" @@ -6900,7 +6798,7 @@ __metadata: concurrently: "npm:^5.3.0" cross-env: "npm:^7.0.3" danger: "npm:^11.2.6" - esbuild: "npm:^0.18.0" + esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0" esbuild-loader: "npm:^3.0.0" esbuild-plugin-alias: "npm:^0.2.1" eslint: "npm:^8.56.0" @@ -7311,7 +7209,7 @@ __metadata: languageName: node linkType: hard -"@sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0, @sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0-next.0 || ^2.0.0": +"@sveltejs/vite-plugin-svelte-inspector@npm:^2.0.0": version: 2.0.0 resolution: "@sveltejs/vite-plugin-svelte-inspector@npm:2.0.0" dependencies: @@ -7324,25 +7222,7 @@ __metadata: languageName: node linkType: hard -"@sveltejs/vite-plugin-svelte@npm:^3.0.1": - version: 3.0.1 - resolution: "@sveltejs/vite-plugin-svelte@npm:3.0.1" - dependencies: - "@sveltejs/vite-plugin-svelte-inspector": "npm:^2.0.0-next.0 || ^2.0.0" - debug: "npm:^4.3.4" - deepmerge: "npm:^4.3.1" - kleur: "npm:^4.1.5" - magic-string: "npm:^0.30.5" - svelte-hmr: "npm:^0.15.3" - vitefu: "npm:^0.2.5" - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.0 - checksum: 10c0/889d41014d4cc5dfb578cb0a80e64f72c0f8c143e9a299c3a4e2372fd582d982ce118dad5e158e0b747d1df7354a909ed9490b1adcd1bf982b56c82fffd4652c - languageName: node - linkType: hard - -"@sveltejs/vite-plugin-svelte@npm:^3.0.2": +"@sveltejs/vite-plugin-svelte@npm:^3.0.1, @sveltejs/vite-plugin-svelte@npm:^3.0.2": version: 3.0.2 resolution: "@sveltejs/vite-plugin-svelte@npm:3.0.2" dependencies: @@ -7828,10 +7708,10 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.1": - version: 1.0.2 - resolution: "@types/estree@npm:1.0.2" - checksum: 10c0/4b5c601d435ea8e2205458de15fd1556b5ae6c9a8323bad8a940ea502d6c824664faca94234c0bf76bf9c87cbf6ac41abee550c9e20433256549d589c9b543bd +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.1, @types/estree@npm:^1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: 10c0/b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d languageName: node linkType: hard @@ -7842,13 +7722,6 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:^1.0.5": - version: 1.0.5 - resolution: "@types/estree@npm:1.0.5" - checksum: 10c0/b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d - languageName: node - linkType: hard - "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": version: 4.17.37 resolution: "@types/express-serve-static-core@npm:4.17.37" @@ -9791,16 +9664,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.0, acorn@npm:^8.10.0, acorn@npm:^8.11.2, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.11.2 - resolution: "acorn@npm:8.11.2" - bin: - acorn: bin/acorn - checksum: 10c0/a3ed76c761b75ec54b1ec3068fb7f113a182e95aea7f322f65098c2958d232e3d211cb6dac35ff9c647024b63714bc528a26d54a925d1fef2c25585b4c8e4017 - languageName: node - linkType: hard - -"acorn@npm:^8.11.3": +"acorn@npm:^8.0.0, acorn@npm:^8.10.0, acorn@npm:^8.11.2, acorn@npm:^8.11.3, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.11.3 resolution: "acorn@npm:8.11.3" bin: @@ -10556,7 +10420,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.6.0": +"axios@npm:^1.6.0, axios@npm:^1.6.1": version: 1.6.7 resolution: "axios@npm:1.6.7" dependencies: @@ -10567,17 +10431,6 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.6.1": - version: 1.6.2 - resolution: "axios@npm:1.6.2" - dependencies: - follow-redirects: "npm:^1.15.0" - form-data: "npm:^4.0.0" - proxy-from-env: "npm:^1.1.0" - checksum: 10c0/9b77e030e85e4f9cbcba7bb52fbff67d6ce906c92d213e0bd932346a50140faf83733bf786f55bd58301bd92f9973885c7b87d6348023e10f7eaf286d0791a1d - languageName: node - linkType: hard - "axobject-query@npm:^3.2.1": version: 3.2.1 resolution: "axobject-query@npm:3.2.1" @@ -14554,33 +14407,36 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.0": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": "npm:0.18.20" - "@esbuild/android-arm64": "npm:0.18.20" - "@esbuild/android-x64": "npm:0.18.20" - "@esbuild/darwin-arm64": "npm:0.18.20" - "@esbuild/darwin-x64": "npm:0.18.20" - "@esbuild/freebsd-arm64": "npm:0.18.20" - "@esbuild/freebsd-x64": "npm:0.18.20" - "@esbuild/linux-arm": "npm:0.18.20" - "@esbuild/linux-arm64": "npm:0.18.20" - "@esbuild/linux-ia32": "npm:0.18.20" - "@esbuild/linux-loong64": "npm:0.18.20" - "@esbuild/linux-mips64el": "npm:0.18.20" - "@esbuild/linux-ppc64": "npm:0.18.20" - "@esbuild/linux-riscv64": "npm:0.18.20" - "@esbuild/linux-s390x": "npm:0.18.20" - "@esbuild/linux-x64": "npm:0.18.20" - "@esbuild/netbsd-x64": "npm:0.18.20" - "@esbuild/openbsd-x64": "npm:0.18.20" - "@esbuild/sunos-x64": "npm:0.18.20" - "@esbuild/win32-arm64": "npm:0.18.20" - "@esbuild/win32-ia32": "npm:0.18.20" - "@esbuild/win32-x64": "npm:0.18.20" +"esbuild@npm:^0.20.1": + version: 0.20.1 + resolution: "esbuild@npm:0.20.1" + dependencies: + "@esbuild/aix-ppc64": "npm:0.20.1" + "@esbuild/android-arm": "npm:0.20.1" + "@esbuild/android-arm64": "npm:0.20.1" + "@esbuild/android-x64": "npm:0.20.1" + "@esbuild/darwin-arm64": "npm:0.20.1" + "@esbuild/darwin-x64": "npm:0.20.1" + "@esbuild/freebsd-arm64": "npm:0.20.1" + "@esbuild/freebsd-x64": "npm:0.20.1" + "@esbuild/linux-arm": "npm:0.20.1" + "@esbuild/linux-arm64": "npm:0.20.1" + "@esbuild/linux-ia32": "npm:0.20.1" + "@esbuild/linux-loong64": "npm:0.20.1" + "@esbuild/linux-mips64el": "npm:0.20.1" + "@esbuild/linux-ppc64": "npm:0.20.1" + "@esbuild/linux-riscv64": "npm:0.20.1" + "@esbuild/linux-s390x": "npm:0.20.1" + "@esbuild/linux-x64": "npm:0.20.1" + "@esbuild/netbsd-x64": "npm:0.20.1" + "@esbuild/openbsd-x64": "npm:0.20.1" + "@esbuild/sunos-x64": "npm:0.20.1" + "@esbuild/win32-arm64": "npm:0.20.1" + "@esbuild/win32-ia32": "npm:0.20.1" + "@esbuild/win32-x64": "npm:0.20.1" dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true "@esbuild/android-arm": optional: true "@esbuild/android-arm64": @@ -14627,7 +14483,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10c0/473b1d92842f50a303cf948a11ebd5f69581cd254d599dd9d62f9989858e0533f64e83b723b5e1398a5b488c0f5fd088795b4235f65ecaf4f007d4b79f04bc88 + checksum: 10c0/7e0303cb80defd55f3f7b85108081afc9c2f3852dda13bf70975a89210f20cd658fc02540d34247401806cb069c4ec489f7cf0df833e040ee361826484926c3a languageName: node linkType: hard @@ -15051,7 +14907,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.0.0": +"eslint@npm:^8.0.0, eslint@npm:^8.56.0": version: 8.57.0 resolution: "eslint@npm:8.57.0" dependencies: @@ -15099,54 +14955,6 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.56.0": - version: 8.56.0 - resolution: "eslint@npm:8.56.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.56.0" - "@humanwhocodes/config-array": "npm:^0.11.13" - "@humanwhocodes/module-importer": "npm:^1.0.1" - "@nodelib/fs.walk": "npm:^1.2.8" - "@ungap/structured-clone": "npm:^1.2.0" - ajv: "npm:^6.12.4" - chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" - debug: "npm:^4.3.2" - doctrine: "npm:^3.0.0" - escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.2" - eslint-visitor-keys: "npm:^3.4.3" - espree: "npm:^9.6.1" - esquery: "npm:^1.4.2" - esutils: "npm:^2.0.2" - fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" - find-up: "npm:^5.0.0" - glob-parent: "npm:^6.0.2" - globals: "npm:^13.19.0" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.0" - imurmurhash: "npm:^0.1.4" - is-glob: "npm:^4.0.0" - is-path-inside: "npm:^3.0.3" - js-yaml: "npm:^4.1.0" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" - lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.1.2" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.3" - strip-ansi: "npm:^6.0.1" - text-table: "npm:^0.2.0" - bin: - eslint: bin/eslint.js - checksum: 10c0/2be598f7da1339d045ad933ffd3d4742bee610515cd2b0d9a2b8b729395a01d4e913552fff555b559fccaefd89d7b37632825789d1b06470608737ae69ab43fb - languageName: node - linkType: hard - "esm-env@npm:^1.0.0": version: 1.0.0 resolution: "esm-env@npm:1.0.0" @@ -16098,17 +15906,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.0": - version: 1.15.3 - resolution: "follow-redirects@npm:1.15.3" - peerDependenciesMeta: - debug: - optional: true - checksum: 10c0/915a2cf22e667bdf47b1a43cc6b7dce14d95039e9bbf9a24d0e739abfbdfa00077dd43c86d4a7a19efefcc7a99af144920a175eedc3888d268af5df67c272ee5 - languageName: node - linkType: hard - -"follow-redirects@npm:^1.15.4": +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.4": version: 1.15.5 resolution: "follow-redirects@npm:1.15.5" peerDependenciesMeta: @@ -25380,20 +25178,7 @@ __metadata: languageName: node linkType: hard -"recast@npm:^0.23.1, recast@npm:^0.23.3": - version: 0.23.4 - resolution: "recast@npm:0.23.4" - dependencies: - assert: "npm:^2.0.0" - ast-types: "npm:^0.16.1" - esprima: "npm:~4.0.0" - source-map: "npm:~0.6.1" - tslib: "npm:^2.0.1" - checksum: 10c0/d719633be8029e28f23b8191d4a525c5dbdac721792ab3cb5e9dfcf1694fb93f3c147b186916195a9c7fa0711f1e4990ba457cdcee02faed3899d4a80da1bd1f - languageName: node - linkType: hard - -"recast@npm:^0.23.5": +"recast@npm:^0.23.1, recast@npm:^0.23.3, recast@npm:^0.23.5": version: 0.23.5 resolution: "recast@npm:0.23.5" dependencies: @@ -28430,14 +28215,7 @@ __metadata: languageName: node linkType: hard -"tiny-invariant@npm:^1.3.1": - version: 1.3.1 - resolution: "tiny-invariant@npm:1.3.1" - checksum: 10c0/5b87c1d52847d9452b60d0dcb77011b459044e0361ca8253bfe7b43d6288106e12af926adb709a6fc28900e3864349b91dad9a4ac93c39aa15f360b26c2ff4db - languageName: node - linkType: hard - -"tiny-invariant@npm:^1.3.3": +"tiny-invariant@npm:^1.3.1, tiny-invariant@npm:^1.3.3": version: 1.3.3 resolution: "tiny-invariant@npm:1.3.3" checksum: 10c0/65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a diff --git a/docs/addons/addons-api.md b/docs/addons/addons-api.md index 8bdc7d62367e..c2c1afad9edb 100644 --- a/docs/addons/addons-api.md +++ b/docs/addons/addons-api.md @@ -244,32 +244,32 @@ This method allows you to override the default Storybook UI configuration (e.g., The following table details how to use the API values: -| Name | Type | Description | Example Value | -| --------------------- | :-------------: | :-----------------------------------------------------: | :-----------------------------------: | -| **navSize** | Number (pixels) | The size of the sidebar that shows a list of stories | `300` | -| **bottomPanelHeight** | Number (pixels) | The size of the addon panel when in the bottom position | `200` | -| **rightPanelWidth** | Number (pixels) | The size of the addon panel when in the right position | `200` | -| **panelPosition** | String | Where to show the addon panel | `'bottom'` or `'right'` | -| **enableShortcuts** | Boolean | Enable/disable shortcuts | `true` | -| **showToolbar** | Boolean | Show/hide toolbar | `true` | -| **theme** | Object | Storybook Theme, see next section | `undefined` | -| **selectedPanel** | String | Id to select an addon panel | `storybook/actions/panel` | -| **initialActive** | String | Select the default active tab on Mobile | `sidebar` or `canvas` or `addons` | -| **sidebar** | Object | Sidebar options, see below | `{ showRoots: false }` | -| **toolbar** | Object | Modify the tools in the toolbar using the addon id | `{ fullscreen: { hidden: false } } }` | +| Name | Type | Description | Example Value | +| --------------------- | --------------- | ------------------------------------------------------- | ------------------------------------- | +| **navSize** | Number (pixels) | The size of the sidebar that shows a list of stories | `300` | +| **bottomPanelHeight** | Number (pixels) | The size of the addon panel when in the bottom position | `200` | +| **rightPanelWidth** | Number (pixels) | The size of the addon panel when in the right position | `200` | +| **panelPosition** | String | Where to show the addon panel | `'bottom'` or `'right'` | +| **enableShortcuts** | Boolean | Enable/disable shortcuts | `true` | +| **showToolbar** | Boolean | Show/hide toolbar | `true` | +| **theme** | Object | Storybook Theme, see next section | `undefined` | +| **selectedPanel** | String | Id to select an addon panel | `storybook/actions/panel` | +| **initialActive** | String | Select the default active tab on Mobile | `sidebar` or `canvas` or `addons` | +| **sidebar** | Object | Sidebar options, see below | `{ showRoots: false }` | +| **toolbar** | Object | Modify the tools in the toolbar using the addon id | `{ fullscreen: { hidden: false } } }` | The following options are configurable under the `sidebar` namespace: -| Name | Type | Description | Example Value | -| ------------------ | :------: | :-----------------------------------------------------------: | :----------------------------------------------: | -| **showRoots** | Boolean | Display the top-level nodes as a "root" in the sidebar | `false` | -| **collapsedRoots** | Array | Set of root node IDs to visually collapse by default | `['misc', 'other']` | +| Name | Type | Description | Example Value | +| ------------------ | -------- | ------------------------------------------------------------- | ------------------------------------------------ | +| **showRoots** | Boolean | Display the top-level nodes as a "root" in the sidebar | `false` | +| **collapsedRoots** | Array | Set of root node IDs to visually collapse by default | `['misc', 'other']` | | **renderLabel** | Function | Create a custom label for tree nodes; must return a ReactNode | `(item) => {item.name}` | The following options are configurable under the `toolbar` namespace: -| Name | Type | Description | Example Value | -| ------ | :----: | :--------------------------------: | :-----------------: | +| Name | Type | Description | Example Value | +| ------ | ------ | ---------------------------------- | ------------------- | | **id** | String | Toggle visibility for toolbar item | `{ hidden: false }` | --- diff --git a/docs/api/csf.md b/docs/api/csf.md index b91f45fd57a4..636195be3761 100644 --- a/docs/api/csf.md +++ b/docs/api/csf.md @@ -64,11 +64,11 @@ With CSF, every named export in the file represents a story object by default. The exported identifiers will be converted to "start case" using Lodash's [startCase](https://lodash.com/docs/#startCase) function. For example: -| Identifier | Transformation | -| ---------------- | :---------------: | -| name | Name | -| someName | Some Name | -| someNAME | Some NAME | +| Identifier | Transformation | +| ---------------- | ----------------- | +| name | Name | +| someName | Some Name | +| someNAME | Some NAME | | some_custom_NAME | Some Custom NAME | | someName1234 | Some Name 1 2 3 4 | diff --git a/docs/configure/features-and-behavior.md b/docs/configure/features-and-behavior.md index a81aa6a55c74..ebfe081a0645 100644 --- a/docs/configure/features-and-behavior.md +++ b/docs/configure/features-and-behavior.md @@ -16,44 +16,44 @@ To control the layout of Storybookโ€™s UI you can use `addons.setConfig` in your The following table details how to use the API values: -| Name | Type | Description | Example Value | -| --------------------- | :-------------: | :-----------------------------------------------------: | :-------------------------------------: | -| **navSize** | Number (pixels) | The size of the sidebar that shows a list of stories | `300` | -| **bottomPanelHeight** | Number (pixels) | The size of the addon panel when in the bottom position | `200` | -| **rightPanelWidth** | Number (pixels) | The size of the addon panel when in the right position | `200` | -| **panelPosition** | String | Where to show the addon panel | `'bottom'` or `'right'` | -| **enableShortcuts** | Boolean | Enable/disable shortcuts | `true` | -| **showToolbar** | Boolean | Show/hide tool bar | `true` | -| **theme** | Object | Storybook Theme, see next section | `undefined` | -| **selectedPanel** | String | Id to select an addon panel | `'storybook/actions/panel'` | -| **initialActive** | String | Select the default active tab on Mobile | `'sidebar'` or `'canvas'` or `'addons'` | -| **sidebar** | Object | Sidebar options, see below | `{ showRoots: false }` | -| **toolbar** | Object | Modify the tools in the toolbar using the addon id | `{ fullscreen: { hidden: false } } }` | +| Name | Type | Description | Example Value | +| --------------------- | --------------- | ------------------------------------------------------- | --------------------------------------- | +| **navSize** | Number (pixels) | The size of the sidebar that shows a list of stories | `300` | +| **bottomPanelHeight** | Number (pixels) | The size of the addon panel when in the bottom position | `200` | +| **rightPanelWidth** | Number (pixels) | The size of the addon panel when in the right position | `200` | +| **panelPosition** | String | Where to show the addon panel | `'bottom'` or `'right'` | +| **enableShortcuts** | Boolean | Enable/disable shortcuts | `true` | +| **showToolbar** | Boolean | Show/hide tool bar | `true` | +| **theme** | Object | Storybook Theme, see next section | `undefined` | +| **selectedPanel** | String | Id to select an addon panel | `'storybook/actions/panel'` | +| **initialActive** | String | Select the default active tab on Mobile | `'sidebar'` or `'canvas'` or `'addons'` | +| **sidebar** | Object | Sidebar options, see below | `{ showRoots: false }` | +| **toolbar** | Object | Modify the tools in the toolbar using the addon id | `{ fullscreen: { hidden: false } } }` | The following options are configurable under the `sidebar` namespace: -| Name | Type | Description | Example Value | -| ------------------ | :------: | :-----------------------------------------------------------: | :----------------------------------------------: | -| **showRoots** | Boolean | Display the top-level nodes as a "root" in the sidebar | `false` | -| **collapsedRoots** | Array | Set of root node IDs to visually collapse by default | `['misc', 'other']` | +| Name | Type | Description | Example Value | +| ------------------ | -------- | ------------------------------------------------------------- | ------------------------------------------------ | +| **showRoots** | Boolean | Display the top-level nodes as a "root" in the sidebar | `false` | +| **collapsedRoots** | Array | Set of root node IDs to visually collapse by default | `['misc', 'other']` | | **renderLabel** | Function | Create a custom label for tree nodes; must return a ReactNode | `(item) => {item.name}` | The following options are configurable under the `toolbar` namespace: -| Name | Type | Description | Example Value | -| ------ | :----: | :--------------------------------: | :-----------------: | +| Name | Type | Description | Example Value | +| ------ | ------ | ---------------------------------- | ------------------- | | **id** | String | Toggle visibility for toolbar item | `{ hidden: false }` | ## Configuring through URL parameters You can use URL parameters to configure some of the available features: -| Config option | Query param | Supported values | -| ------------------- | :----------: | :----------------------------: | -| **enableShortcuts** | `shortcuts` | `false` | -| --- (fullscreen) | `full` | `true`, `false` | -| --- (show sidebar) | `nav` | `true`, `false` | -| --- (show panel) | `panel` | `false`, `'right'`, `'bottom'` | -| **selectedPanel** | `addonPanel` | Any panel ID | -| **showTabs** | `tabs` | `true` | -| --- | `instrument` | `false`, `true` | +| Config option | Query param | Supported values | +| ------------------- | ------------ | ------------------------------ | +| **enableShortcuts** | `shortcuts` | `false` | +| --- (fullscreen) | `full` | `true`, `false` | +| --- (show sidebar) | `nav` | `true`, `false` | +| --- (show panel) | `panel` | `false`, `'right'`, `'bottom'` | +| **selectedPanel** | `addonPanel` | Any panel ID | +| **showTabs** | `tabs` | `true` | +| --- | `instrument` | `false`, `true` | diff --git a/docs/essentials/toolbars-and-globals.md b/docs/essentials/toolbars-and-globals.md index 125499681c61..9c33e952354b 100644 --- a/docs/essentials/toolbars-and-globals.md +++ b/docs/essentials/toolbars-and-globals.md @@ -144,13 +144,12 @@ By adding the configuration element `right`, the text will be displayed on the r Here's a list of the configuration options available. -| MenuItem | Type | Description | Required | -| --------- | :----: | :-------------------------------------------------------------: | :------: | -| **value** | String | The string value of the menu that gets set in the globals | Yes | -| **title** | String | The main text of the title | Yes | -| **left** | String | A string that gets shown on the left side of the menu | No | -| **right** | String | A string that gets displayed on the right side of the menu | No | -| **icon** | String | An icon that gets shown in the toolbar if this item is selected | No | +| MenuItem | Type | Description | Required | +| --------- | ------ | --------------------------------------------------------------- | -------- | +| **value** | String | The string value of the menu that gets set in the globals | Yes | +| **title** | String | The main text of the title | Yes | +| **right** | String | A string that gets displayed on the right side of the menu | No | +| **icon** | String | An icon that gets shown in the toolbar if this item is selected | No | ## Consuming globals from within a story diff --git a/docs/faq.md b/docs/faq.md index af3aa33158c9..aa597d0f4f57 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -339,9 +339,9 @@ Vue 2 entered [End of Life](https://v2.vuejs.org/lts/) (EOL) on December 31, 202 diff --git a/docs/get-started/angular.md b/docs/get-started/angular.md new file mode 100644 index 000000000000..e5c706acc1df --- /dev/null +++ b/docs/get-started/angular.md @@ -0,0 +1,445 @@ +--- +title: Storybook for Angular +--- + +export const SUPPORTED_RENDERER = 'angular'; + +Storybook for Angular is a [framework](../contribute/framework.md) that makes it easy to develop and test UI components in isolation for [Angular](https://angular.io/) applications. It includes: + +- ๐Ÿงฑ Uses Angular builders +- ๐ŸŽ›๏ธ Compodoc integration +- ๐Ÿ’ซ and more! + + + + + +Storybook for Angular is only supported in [Angular](?renderer=angular) projects. + + + + + + + + + +## Requirements + +- Angular โ‰ฅ 15.0 < 18.0 +- Webpack โ‰ฅ 5.0 +- Storybook โ‰ฅ 8.0 + +## Getting started + +### In a project without Storybook + +Follow the prompts after running this command in your Angular project's root directory: + + + + + + + +[More on getting started with Storybook.](./install.md) + +### In a project with Storybook + +This framework is designed to work with Storybook 7+. If youโ€™re not already using v7, upgrade with this command: + + + + + + + +#### Automatic migration + +When running the `upgrade` command above, you should get a prompt asking you to migrate to `@storybook/angular`, which should handle everything for you. In case that auto-migration does not work for your project, refer to the manual migration below. + +#### Manual migration + +First, install the framework: + + + + + + + +Then, update your `.storybook/main.js|ts` to change the framework property: + + + + + + + +Finally, update your `angular.json` to include the Storybook builder: + +```jsonc +// angular.json +{ + ... + "projects": { + ... + "your-project": { + ... + "architect": { + ... + "storybook": { + "builder": "@storybook/angular:start-storybook", + "options": { + // The path to the storybook config directory + "configDir": ".storybook", + // The build target of your project + "browserTarget": "your-project:build", + // The port you want to start Storybook on + "port": 6006 + // More options available, documented here: + // https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular/src/builders/start-storybook/schema.json + } + }, + "build-storybook": { + "builder": "@storybook/angular:build-storybook", + "options": { + "configDir": ".storybook", + "browserTarget": "your-project:build", + "outputDir": "dist/storybook/your-project" + // More options available, documented here: + // https://github.com/storybookjs/storybook/tree/next/code/frameworks/angular/src/builders/build-storybook/schema.json + } + } + } + } + } +} +``` + +## Run Storybook + +To run Storybook for a particular project, please run: + +```sh +ng run :storybook +``` + +To build Storybook, run: + +```sh +ng run :build-storybook +``` + +You will find the output in the configured `outputDir` (default is `dist/storybook/`). + +## Setup Compodoc + +You can include JSDoc comments above components, directives, and other parts of your Angular code to include documentation for those elements. Compodoc uses these comments to [generate documentation](../writing-docs/autodocs.md) for your application. In Storybook, it is useful to add explanatory comments above `@Inputs` and `@Outputs`, since these are the main elements that Storybook displays in its user interface. The `@Inputs` and `@Outputs` are the elements that you can interact with in Storybook, such as [controls](../essentials/controls.md). + +### Automatic setup + +When installing Storybook via `npx storybook@latest init`, you will be given the option to set up Compodoc automatically. + +### Manual setup + +If you have already installed Storybook, you can set up Compodoc manually. + +Install the following dependencies: + +```sh +npm install --save-dev @compodoc/compodoc +``` + +Add the following option to your Storybook Builder: + +```jsonc +// angular.json +{ + ... + "projects": { + ... + "your-project": { + ... + "architect": { + ... + "storybook": { + "builder": "@storybook/angular:start-storybook", + "options": { + ... + // ๐Ÿ‘‡ Add these + "compodoc": true, + "compodocArgs": [ + "-e", + "json", + "-d", + // Where to store the generated documentation. It's usually the root of your Angular project. It's not necessarily the root of your Angular Workspace! + "." + ], + } + }, + "build-storybook": { + "builder": "@storybook/angular:build-storybook", + "options": { + ... + // ๐Ÿ‘‡ Add these + "compodoc": true, + "compodocArgs": [ + "-e", + "json", + "-d", + "." + ], + } + } + } + } + } +} +``` + +Go to your `.storybook/preview.js` and add the following: + +```js +// .storybook/preview.js +// ๐Ÿ‘‡ Add these +import { setCompodocJson } from '@storybook/addon-docs/angular'; +import docJson from '../documentation.json'; +setCompodocJson(docJson); + +// ... rest of file +``` + +## `applicationConfig` decorator + +If your component relies on application-wide providers, like the ones defined by BrowserAnimationsModule or any other modules which use the forRoot pattern to provide a ModuleWithProviders, you can apply the `applicationConfig` [decorator](../writing-stories/decorators.md) to all stories for that component. This will provide them to the [bootstrapApplication function](https://angular.io/guide/standalone-components#configuring-dependency-injection), which is used to bootstrap the component in Storybook. + +```ts +// ChipsModule.stories.ts +import { Meta, applicationConfig, StoryObj } from '@storybook/angular'; +import { BrowserAnimationsModule, provideAnimations } from '@angular/platform-browser/animations'; +import { importProvidersFrom } from '@angular/core'; + +import { ChipsModule } from './angular-src/chips.module'; + +const meta: Meta = { + component: ChipsModule, + decorators: [ + // Apply application config to all stories + applicationConfig({ + // List of providers and environment providers that should be available to the root component and all its children. + providers: [ + ... + // Import application-wide providers from a module + importProvidersFrom(BrowserAnimationsModule) + // Or use provide-style functions if available instead, e.g. + provideAnimations() + ], + }), + ], +}; + +export default meta; + +type Story = StoryObj; + +export const WithCustomApplicationProvider: Story = { + render: () => ({ + // Apply application config to a specific story + applicationConfig: { + // The providers will be merged with the ones defined in the applicationConfig decorators providers array of the global meta object + providers: [...], + } + }) +} +``` + +## `moduleMetadata` decorator + +If your component has dependencies on other Angular directives and modules, these can be supplied using the `moduleMetadata` [decorator](../writing-stories/decorators.md) either for all stories of a component or for individual stories. + +```ts +// YourComponent.stories.ts +import { Meta, moduleMetadata, StoryObj } from '@storybook/angular'; + +import { YourComponent } from './your.component'; + +const meta: Meta = { + component: YourComponent, + decorators: [ + // Apply metadata to all stories + moduleMetadata({ + // import necessary ngModules or standalone components + imports: [...], + // declare components that are used in the template + declarations: [...], + // List of providers that should be available to the root component and all its children. + providers: [...], + }), + ], +}; +export default meta; + +type Story = StoryObj; + +export const Base: Story = {}; + +export const WithCustomProvider: Story = { + decorators: [ + // Apply metadata to a specific story + moduleMetadata({ + imports: [...], + declarations: [...], + providers: [...], + }), + ], +}; +``` + +## FAQ + +### How do I migrate to an Angular Storybook builder? + +The Storybook [Angular builder](https://angular.io/guide/glossary#builder) is a way to run Storybook in an Angular workspace. It is a drop-in replacement for running `storybook dev` and `storybook build` directly. + +You can run `npx storybook@next automigrate` to try let Storybook detect and automatically fix your configuration. Otherwise, you can follow the next steps to manually adjust your configuration. + +#### Do you have only one Angular project in your workspace? + +First, go to your `angular.json` and add `storybook` and `build-storybook` entries in `architect` section of your project like shown above. + +Second, adjust your `package.json` script section. Usually, it will look like this: + +```jsonc +{ + "scripts": { + "storybook": "start-storybook -p 6006", // or `storybook dev -p 6006` + "build-storybook": "build-storybook" // or `storybook build` + } +} +``` + +Now, you can run Storybook with `ng run :storybook` and build it with `ng run :build-storybook`. Adjust the scripts in your `package.json` accordingly. + +```json +{ + "scripts": { + "storybook": "ng run :storybook", + "build-storybook": "ng run :build-storybook" + } +} +``` + +Also compodoc is now built-in in `@storybook/angular` and you don't have to call it explicitly. If were running compodoc in your `package.json` scripts like this: + +```json +{ + "scripts": { + "docs:json": "compodoc -p tsconfig.json -e json -d ./documentation", + "storybook": "npm run docs:json && start-storybook -p 6006", + "build-storybook": "npm run docs:json && build-storybook" + } +} +``` + +Change it to: + +```json +{ + "scripts": { + "storybook": "ng run :storybook", + "build-storybook": "ng run :build-storybook" + } +} +``` + +#### I have multiple projects in my Angular workspace + +In this case you have to adjust your `angular.json` and `package.json` as described above for each project in which you want to use Storybook. Please note, that each project should have a dedicated `.storybook` folder, which should be placed in the root of the project. + +You can run `npx storybook@latest init` sequentially for each project to setup Storybook for each of them to automatically create the `.storybook` folder and create the necessary configuration in your `angular.json`. + +You can then use [Storybook composition](https://storybook.js.org/docs/angular/sharing/storybook-composition) to composite multiple Storybooks into one. + +### How do I configure Angular's builder for Storybook? + +These are common options you may need for the Angular builder: + +| Configuration element | Description | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `"browserTarget"` | Build target to be served using the following format.
`"example-project:builder:config"` | +| `"tsConfig"` | Location of the TypeScript configuration file, relative to the current workspace.
`"tsConfig": "./tsconfig.json"`. | +| `"port"` | Port used by Storybook.
`"port": 6006` | +| `"host"` | Set up a custom host for Storybook.
`"host": "http://my-custom-host"` | +| `"configDir"` | Storybook configuration directory location.
`"configDir": ".storybook"` | +| `"https"` | Starts Storybook with HTTPS enabled.
`"https": true`
Requires custom certificate information. | +| `"sslCa"` | Provides an SSL certificate authority.
`"sslCa": "your-custom-certificate-authority"`
Optional usage with `"https"` | +| `"sslCert"` | Provides an SSL certificate.
`"sslCert": "your-custom-certificate"`
Required for `https` | +| `"sslKey"` | Provides an SSL key to serve Storybook.
`"sslKey": "your-ssl-key"` | +| `"smokeTest"` | Exit Storybook after successful start.
`"smokeTest": true` | +| `"ci"` | Starts Storybook in CI mode (skips interactive prompts and will not open browser window).
`"ci": true` | +| `"quiet"` | Filters Storybook verbose build output.
`"quiet": true` | +| `"docs"` | Starts Storybook in [documentation mode](../writing-docs/build-documentation.md#preview-storybooks-documentation).
`"docs": true` | +| `"styles"` | Provide the location of the [application's styles](../configure/styling-and-css.md#importing-css-files) to be used with Storybook.
`"styles": ["src/styles.css", "src/styles.scss"]`
| +| `"stylePreprocessorOptions"` | Provides further customization for style preprocessors resolved to the workspace root.
`"stylePreprocessorOptions": { "includePaths": ["src/styles"] }` | + +The full list of options can be found in the Angular builder schemas: + +- [Build Storybook](https://github.com/storybookjs/storybook/blob/main/code/frameworks/angular/src/builders/build-storybook/schema.json) +- [Start Storybook](https://github.com/storybookjs/storybook/blob/main/code/frameworks/angular/src/builders/start-storybook/schema.json) + +## API + +### Options + +You can pass an options object for additional configuration if needed: + +```js +// .storybook/main.js +import * as path from 'path'; + +export default { + // ... + framework: { + name: '@storybook/angular', + options: { + // ... + }, + }, +}; +``` + +The available options are: + +#### `builder` + +Type: `Record` + +Configure options for the [framework's builder](../api/main-config-framework.md#optionsbuilder). For Angular, , available options can be found in the [Webpack builder docs](../builders/webpack.md). + + + +
diff --git a/docs/get-started/install.md b/docs/get-started/install.md index 70922d5c96e3..138c0164312b 100644 --- a/docs/get-started/install.md +++ b/docs/get-started/install.md @@ -203,9 +203,9 @@ Vue 2 entered [End of Life](https://v2.vuejs.org/lts/) (EOL) on December 31st, 2 diff --git a/docs/get-started/nextjs.md b/docs/get-started/nextjs.md index 9c765276058b..6cbd4ac91177 100644 --- a/docs/get-started/nextjs.md +++ b/docs/get-started/nextjs.md @@ -2,6 +2,8 @@ title: Storybook for Next.js --- +export const SUPPORTED_RENDERER = 'react'; + Storybook for Next.js is a [framework](../contribute/framework.md) that makes it easy to develop and test UI components in isolation for [Next.js](https://nextjs.org/) applications. It includes: - ๐Ÿ”€ Routing @@ -11,10 +13,24 @@ Storybook for Next.js is a [framework](../contribute/framework.md) that makes it - ๐ŸŽ› Webpack & Babel config - ๐Ÿ’ซ and more! + + + + +Storybook for Next.js is only supported in [React](?renderer=react) projects. + + + + + + + + + ## Requirements -- Next.js >= 13.5 -- Storybook >= 7.x +- Next.js โ‰ฅ 13.5 +- Storybook โ‰ฅ 7.0 ## Getting started @@ -38,7 +54,7 @@ Follow the prompts after running this command in your Next.js project's root dir ### In a project with Storybook -This framework is designed to work with Storybook 7. If youโ€™re not already using v7, upgrade with this command: +This framework is designed to work with Storybook 7+. If youโ€™re not already using v7, upgrade with this command: @@ -98,6 +114,14 @@ Finally, if you were using Storybook plugins to integrate with Next.js, those ar +## Run the Setup Wizard + +If all goes well, you should see a setup wizard that will help you get started with Storybook introducing you to the main concepts and features, including how the UI is organized, how to write your first story, and how to test your components' response to various inputs utilizing [controls](../essentials/controls). + +![Storybook onboarding](./example-onboarding-wizard.png) + +If you skipped the wizard, you can always run it again by adding the `?path=/onboarding` query parameter to the URL of your Storybook instance, provided that the example stories are still available. + ## Next.js's Image component This framework allows you to use Next.js's [next/image](https://nextjs.org/docs/pages/api-reference/components/image) with no configuration. @@ -920,7 +944,7 @@ The available options are: Type: `Record` -Configure options for the [framework's builder](../api/main-config-framework.md#optionsbuilder). For Next.js, that builder is Webpack 5. +Configure options for the [framework's builder](../api/main-config-framework.md#optionsbuilder). For Next.js, available options can be found in the [Webpack builder docs](../builders/webpack.md). #### `image` @@ -933,3 +957,7 @@ Props to pass to every instance of `next/image`. See [next/image docs](https://n Type: `string` The absolute path to the `next.config.js` file. This is necessary if you have a custom `next.config.js` file that is not in the root directory of your project. + + + + diff --git a/docs/get-started/react-vite.md b/docs/get-started/react-vite.md new file mode 100644 index 000000000000..9fbe5eca53af --- /dev/null +++ b/docs/get-started/react-vite.md @@ -0,0 +1,140 @@ +--- +title: Storybook for React & Vite +--- + +export const SUPPORTED_RENDERER = 'react'; + +Storybook for React & Vite is a [framework](../contribute/framework.md) that makes it easy to develop and test UI components in isolation for [React](https://react.dev/) applications built with [Vite](https://vitejs.dev/). It includes: + +- ๐ŸŽ๏ธ Pre-bundled for performance +- ๐Ÿช„ Zero config +- ๐Ÿ’ซ and more! + + + + + +Storybook for React & Vite is only supported in [React](?renderer=react) projects. + + + + + + + + + +## Requirements + +- React โ‰ฅ 16.8 +- Vite โ‰ฅ 4.0 +- Storybook โ‰ฅ 8.0 + +## Getting started + +### In a project without Storybook + +Follow the prompts after running this command in your React project's root directory: + + + + + + + +[More on getting started with Storybook.](./install.md) + +### In a project with Storybook + +This framework is designed to work with Storybook 7+. If youโ€™re not already using v7, upgrade with this command: + + + + + + + +#### Automatic migration + +When running the `upgrade` command above, you should get a prompt asking you to migrate to `@storybook/react-vite`, which should handle everything for you. In case that auto-migration does not work for your project, refer to the manual migration below. + +#### Manual migration + +First, install the framework: + + + + + + + +Then, update your `.storybook/main.js|ts` to change the framework property: + + + + + + + +## Run the Setup Wizard + +If all goes well, you should see a setup wizard that will help you get started with Storybook introducing you to the main concepts and features, including how the UI is organized, how to write your first story, and how to test your components' response to various inputs utilizing [controls](../essentials/controls). + +![Storybook onboarding](./example-onboarding-wizard.png) + +If you skipped the wizard, you can always run it again by adding the `?path=/onboarding` query parameter to the URL of your Storybook instance, provided that the example stories are still available. + +## API + +### Options + +You can pass an options object for additional configuration if needed: + +```ts +// .storybook/main.ts +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/react-vite', + options: { + // ... + }, + }, +}; + +export default config; +``` + +#### `builder` + +Type: `Record` + +Configure options for the [framework's builder](../api/main-config-framework.md#optionsbuilder). For this framework, available options can be found in the [Vite builder docs](../builders/vite.md). + + + + diff --git a/docs/get-started/react-webpack5.md b/docs/get-started/react-webpack5.md new file mode 100644 index 000000000000..769aa82a0f2d --- /dev/null +++ b/docs/get-started/react-webpack5.md @@ -0,0 +1,180 @@ +--- +title: Storybook for React & Webpack +--- + +export const SUPPORTED_RENDERER = 'react'; + +Storybook for React & Webpack is a [framework](../contribute/framework.md) that makes it easy to develop and test UI components in isolation for [React](https://react.dev/) applications built with [Webpack](https://webpack.js.org/). + + + + + +Storybook for React & Webpack is only supported in [React](?renderer=react) projects. + + + + + + + + + +## Requirements + +- React โ‰ฅ 16.8 +- Webpack โ‰ฅ 5.0 +- Storybook โ‰ฅ 8.0 + +## Getting started + +### In a project without Storybook + +Follow the prompts after running this command in your React project's root directory: + + + + + + + +[More on getting started with Storybook.](./install.md) + +### In a project with Storybook + +This framework is designed to work with Storybook 7+. If youโ€™re not already using v7, upgrade with this command: + + + + + + + +#### Automatic migration + +When running the `upgrade` command above, you should get a prompt asking you to migrate to `@storybook/react-webpack5`, which should handle everything for you. In case that auto-migration does not work for your project, refer to the manual migration below. + +#### Manual migration + +First, install the framework: + + + + + + + +Next, install and register your appropriate compiler addon, depending on whether you're using SWC (recommended) or Babel: + + + +If your project is using [Create React App](#create-react-app-cra), you can skip this step. + + + + + + + + + +or + + + + + + + +More details can be found in the [Webpack builder docs](../builders/webpack.md#compiler-support). + +Finally, update your `.storybook/main.js|ts` to change the framework property: + + + + + + + +## Run the Setup Wizard + +If all goes well, you should see a setup wizard that will help you get started with Storybook introducing you to the main concepts and features, including how the UI is organized, how to write your first story, and how to test your components' response to various inputs utilizing [controls](../essentials/controls). + +![Storybook onboarding](./example-onboarding-wizard.png) + +If you skipped the wizard, you can always run it again by adding the `?path=/onboarding` query parameter to the URL of your Storybook instance, provided that the example stories are still available. + +## Create React App (CRA) + +Support for [Create React App](https://create-react-app.dev/) is handled by [`@storybook/preset-create-react-app`](https://github.com/storybookjs/presets/tree/master/packages/preset-create-react-app). + +This preset enables support for all CRA features, including Sass/SCSS and TypeScript. + +If you're working on an app that was initialized manually (i.e., without the use of CRA), ensure that your app has [react-dom](https://www.npmjs.com/package/react-dom) included as a dependency. Failing to do so can lead to unforeseen issues with Storybook and your project. + +## API + +### Options + +You can pass an options object for additional configuration if needed: + +```ts +// .storybook/main.ts +import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/react-webpack5', + options: { + // ... + }, + }, +}; + +export default config; +``` + +#### `builder` + +Type: `Record` + +Configure options for the [framework's builder](../api/main-config-framework.md#optionsbuilder). For this framework, available options can be found in the [Webpack builder docs](../builders/webpack.md). + + + + diff --git a/docs/get-started/svelte-vite.md b/docs/get-started/svelte-vite.md new file mode 100644 index 000000000000..2069a18d66ee --- /dev/null +++ b/docs/get-started/svelte-vite.md @@ -0,0 +1,153 @@ +--- +title: Storybook for Svelte & Vite +--- + +export const SUPPORTED_RENDERER = 'svelte'; + +Storybook for Svelte & Vite is a [framework](../contribute/framework.md) that makes it easy to develop and test UI components in isolation for applications using [Svelte](https://svelte.dev/) built with [Vite](https://vitejs.dev/). + + + + + +Storybook for Svelte & Vite is only supported in [Svelte](?renderer=svelte) projects. + + + + + + + + + +## Requirements + +- Svelte โ‰ฅ 4.0 +- Vite โ‰ฅ 4.0 +- Storybook โ‰ฅ 8.0 + +## Getting started + +### In a project without Storybook + +Follow the prompts after running this command in your Sveltekit project's root directory: + + + + + + + +[More on getting started with Storybook.](./install.md) + +### In a project with Storybook + +This framework is designed to work with Storybook 7+. If youโ€™re not already using v7, upgrade with this command: + + + + + + + +#### Automatic migration + +When running the `upgrade` command above, you should get a prompt asking you to migrate to `@storybook/sveltekit`, which should handle everything for you. In case that auto-migration does not work for your project, refer to the manual migration below. + +#### Manual migration + +First, install the framework: + + + + + + + +Then, update your `.storybook/main.js|ts` to change the framework property: + + + + + + + +## Writing native Svelte stories + +Storybook provides a Svelte addon maintained by the community, enabling you to write stories for your Svelte components using the template syntax. You'll need to take some additional steps to enable this feature. + +Run the following command to install the addon. + + + + + + + + + +The community actively maintains the Svelte CSF addon but still lacks some features currently available in the official Storybook Svelte framework support. For more information, see [addon's documentation](https://github.com/storybookjs/addon-svelte-csf). + + + +## API + +### Options + +You can pass an options object for additional configuration if needed: + +```js +// .storybook/main.js +import * as path from 'path'; + +export default { + // ... + framework: { + name: '@storybook/svelte-vite', + options: { + // ... + }, + }, +}; +``` + +The available options are: + +#### `builder` + +Type: `Record` + +Configure options for the [framework's builder](../api/main-config-framework.md#optionsbuilder). For this framework, available options can be found in the [Vite builder docs](../builders/vite.md). + + + + diff --git a/docs/get-started/vue-component-meta-event-types-controls.png b/docs/get-started/vue-component-meta-event-types-controls.png new file mode 100644 index 000000000000..093b2da0911a Binary files /dev/null and b/docs/get-started/vue-component-meta-event-types-controls.png differ diff --git a/docs/get-started/vue-component-meta-exposed-types-controls.png b/docs/get-started/vue-component-meta-exposed-types-controls.png new file mode 100644 index 000000000000..d725615e58b6 Binary files /dev/null and b/docs/get-started/vue-component-meta-exposed-types-controls.png differ diff --git a/docs/get-started/vue-component-meta-prop-types-controls.png b/docs/get-started/vue-component-meta-prop-types-controls.png new file mode 100644 index 000000000000..049bc595c2e9 Binary files /dev/null and b/docs/get-started/vue-component-meta-prop-types-controls.png differ diff --git a/docs/get-started/vue-component-meta-slot-types-controls.png b/docs/get-started/vue-component-meta-slot-types-controls.png new file mode 100644 index 000000000000..72b41db2dff8 Binary files /dev/null and b/docs/get-started/vue-component-meta-slot-types-controls.png differ diff --git a/docs/get-started/vue3-vite.md b/docs/get-started/vue3-vite.md new file mode 100644 index 000000000000..e79cc1f3b6fc --- /dev/null +++ b/docs/get-started/vue3-vite.md @@ -0,0 +1,346 @@ +--- +title: Storybook for Vue & Vite +--- + +export const SUPPORTED_RENDERER = 'vue'; + +Storybook for Vue & Vite is a [framework](../contribute/framework.md) that makes it easy to develop and test UI components in isolation for [Vue](https://vuejs.org/) applications built with [Vite](https://vitejs.dev/). It includes: + +- ๐ŸŽ๏ธ Pre-bundled for performance +- ๐Ÿช„ Zero config +- ๐Ÿง  Comprehensive docgen +- ๐Ÿ’ซ and more! + + + + + +Storybook for Vue & Vite is only supported in [Vue](?renderer=vue) projects. + + + + + + + + + +## Requirements + +- Vue โ‰ฅ 3 +- Vite โ‰ฅ 3.0 (4.X recommended) +- Storybook โ‰ฅ 7.0 + +## Getting started + +### In a project without Storybook + +Follow the prompts after running this command in your Vue project's root directory: + + + + + + + +[More on getting started with Storybook.](./install.md) + +### In a project with Storybook + +This framework is designed to work with Storybook 7+. If youโ€™re not already using v7, upgrade with this command: + + + + + + + +#### Automatic migration + +When running the `upgrade` command above, you should get a prompt asking you to migrate to `@storybook/vue3-vite`, which should handle everything for you. In case that auto-migration does not work for your project, refer to the manual migration below. + +#### Manual migration + +First, install the framework: + + + + + + + +Then, update your `.storybook/main.js|ts` to change the framework property: + + + + + + + +## Extending the Vue application + +Storybook creates a [Vue 3 application](https://vuejs.org/api/application.html#application-api) for your component preview. +When using global custom components (`app.component`), directives (`app.directive`), extensions (`app.use`), or other application methods, you will need to configure those in the `./storybook/preview.js` file. + +Therefore, Storybook provides you with a `setup` function exported from this package, which receives as a callback your Storybook instance, which you can interact with and add your custom configuration. + +```js +// .storybook/preview.js +import { setup } from '@storybook/vue3'; + +setup((app) => { + app.use(MyPlugin); + app.component('my-component', MyComponent); + app.mixin({ + /* My mixin */ + }); +}); + +// Rest of the file... +``` + +## Using `vue-component-meta` + + + +`vue-component-meta` is only available in Storybook โ‰ฅ 8. It is currently opt-in, but will become the default in a future version of Storybook. + + + +[`vue-component-meta`](https://github.com/vuejs/language-tools/tree/master/packages/component-meta) is a tool maintained by the Vue team that extracts metadata from Vue components. Storybook can use it to generate the [controls](../essentials/controls.md) for your stories and documentation. It's a more full-featured alternative to `vue-docgen-api` and is recommended for most projects. + +If you want to use `vue-component-meta`, you can configure it in your `.storybook/main.js|ts` file: + +```ts +// .storybook/main.ts +import type { StorybookConfig } from '@storybook/vue3-vite'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/vue3-vite', + options: { + docgen: 'vue-component-meta', + }, + }, +}; + +export default config; +``` + +`vue-component-meta` comes with many benefits and enables more documentation features, such as: + +### Support for multiple component types + +`vue-component-meta` supports all types of Vue components (including SFC, functional, composition / options API components) from `.vue`, `.ts`, `.tsx`, `.js`, and `.jsx` files. + +It also supports both default and named component exports. + +### Prop description and JSDoc tag annotations + +To provide a description for a prop, including tags, you can use JSDoc comments in your component's props definition: + +```html + + +``` + +The props definition above will generate the following controls: + +![Controls generated from props](./vue-component-meta-prop-types-controls.png) + +### Events types extraction + +To provide a type for an emitted event, you can use TypeScript types (including JSDoc comments) in your component's `defineEmits` call: + +```html + + +``` + +Which will generate the following controls: + +![Controls generated from events](./vue-component-meta-event-types-controls.png) + +### Slots types extraction + +The slot types are automatically extracted from your component definition and displayed in the controls panel. + +```html + + + + +``` + +If you use `defineSlots`, you can provide a description for each slot using JSDoc comments in your component's slots definition: + +```ts +defineSlots<{ + /** Example description for default */ + default(props: { num: number }): any; + /** Example description for named */ + named(props: { str: string }): any; + /** Example description for no-bind */ + noBind(props: {}): any; + /** Example description for vbind */ + vbind(props: { num: number; str: string }): any; +}>(); +``` + +The definition above will generate the following controls: + +![Controls generated from slots](./vue-component-meta-slot-types-controls.png) + +### Exposed properties and methods + +The properties and methods exposed by your component are automatically extracted and displayed in the controls panel. + +```html + + +``` + +The definition above will generate the following controls: + +![Controls generated from exposed properties and methods](./vue-component-meta-exposed-types-controls.png) + +### Limitations + +`vue-component-meta` cannot currently reference types from an import alias. You will need to replace any aliased imports with relative ones, as in the example below. See [this issue](https://github.com/vuejs/language-tools/issues/3896) for more information. + +```ts +// YourComponent.ts +import type { MyProps } from '@/types'; // โŒ Cannot be resolved +import type { MyProps } from '../types'; // โœ… Can be resolved +``` + +## Troubleshooting + +### Storybook doesn't work with my Vue 2 project + +[Vue 2 entered End of Life](https://v2.vuejs.org/lts/) (EOL) on December 31st, 2023, and is no longer maintained by the Vue team. As a result, Storybook no longer supports Vue 2. We recommend you upgrade your project to Vue 3, which Storybook fully supports. If that's not an option, you can still use Storybook with Vue 2 by installing the latest version of Storybook 7 with the following command: + + + + + + + +## API + +### Options + +You can pass an options object for additional configuration if needed: + +```ts +// .storybook/main.ts +import type { StorybookConfig } from '@storybook/vue3-vite'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/vue3-vite', + options: { + docgen: 'vue-component-meta', + }, + }, +}; + +export default config; +``` + +#### `builder` + +Type: `Record` + +Configure options for the [framework's builder](../api/main-config-framework.md#optionsbuilder). For this framework, available options can be found in the [Vite builder docs](../builders/vite.md). + +#### `docgen` + +Type: `'vue-docgen-api' | 'vue-component-meta'` + +Default: `'vue-docgen-api'` + +Since: `8.0` + +Choose which docgen tool to use when generating controls for your components. See [Using `vue-component-meta`](#using-vue-component-meta) for more information. + + + + diff --git a/docs/migration-guide/from-older-version.md b/docs/migration-guide/from-older-version.md index b3740aa2f854..c368c48e39be 100644 --- a/docs/migration-guide/from-older-version.md +++ b/docs/migration-guide/from-older-version.md @@ -2,11 +2,16 @@ title: 'Migration guide from Storybook 6.x to 8.0' --- -Storybook 8 focuses on performance and stability. - -- ๐Ÿ’จ [2-4x faster test builds](/blog/optimize-storybook-7-6/#2-4x-faster-builds-with-thetest-flag), [25-50% faster React docgen](/blog/optimize-storybook-7-6/#22x-faster-react-docgen), and [SWC support for Webpack projects](/blog/optimize-storybook-7-6/#using-webpack-enable-swc) -- โœจ Improved framework support: you no longer need to install React as a peer dependency when using a non-React renderer -- ๐ŸŒ [Support for React Server Components (RSC)](/blog/storybook-react-server-components/): our experimental solution renders async RSC in the browser and mocks Node code +Storybook 8 focuses on improving performance, compatibility, and stability. Key features include: + +- ๐Ÿฉป A new visual testing workflow via [the Visual Tests addon](https://www.chromatic.com/docs/visual-tests-addon/) +- ๐Ÿ’จ [2-4x faster test builds](https://storybook.js.org/blog/optimize-storybook-7-6/#2-4x-faster-builds-with-thetest-flag), [25-50% faster React docgen](https://storybook.js.org/blog/optimize-storybook-7-6/#22x-faster-react-docgen), and [SWC support for Webpack projects](https://storybook.js.org/blog/optimize-storybook-7-6/#using-webpack-enable-swc) +- ๐Ÿงฉ Improved framework support: you no longer need to install React as a peer dependency when using a non-React renderer +- ๐ŸŽ›๏ธย Strengthened control generation in [React](https://storybook.js.org/blog/storybook-8-beta/#major-performance-improvements +) and [Vue](https://storybook.js.org/blog/first-class-vue-support-storybook-8/) projects +- โšก๏ธ Improved Vite architecture, Vitest testing, and Vite 5 support +- ๐ŸŒ [Support for React Server Components (RSC)](https://storybook.js.org/blog/storybook-react-server-components/): our experimental solution renders async RSC in the browser and mocks Node code +- โœจ A refreshed desktop UI & mobile UX - โž• Much, much more This guide is meant to help you **upgrade from Storybook 6.x to 8.0** successfully! @@ -79,6 +84,10 @@ If you are using the `storiesOf` API (which requires `storyStoreV7: false` in St Storybook 8 uses MDX 3. If you're coming from MDX 1 (used by Storybook 6), there were significant breaking changes in MDX 2. Please reference our [guidance on upgrading successfully](../../release-7-6/docs/migration-guide.md#upgrade-mdx1-to-mdx2). +#### Missing `vite.config.js` file + +If you are using Vite, you may now need to create a `vite.config.js` file in your project root to allow newer versions of Vite to work with Storybook. Additionally, you may need to install and configure a Vite plugin for your framework. More information is available in the [full migration notes](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#framework-specific-vite-plugins-have-to-be-explicitly-added). + ## Troubleshooting The automatic upgrade should get your Storybook into a working state. If you encounter an error running Storybook after upgrading, hereโ€™s what to do: diff --git a/docs/migration-guide/index.md b/docs/migration-guide/index.md index 70510a941d86..51962ca7b88d 100644 --- a/docs/migration-guide/index.md +++ b/docs/migration-guide/index.md @@ -2,11 +2,16 @@ title: 'Migration guide for Storybook 8.0' --- -Storybook 8 focuses on performance and stability. - -- ๐Ÿ’จ [2-4x faster test builds](/blog/optimize-storybook-7-6/#2-4x-faster-builds-with-thetest-flag), [25-50% faster React docgen](/blog/optimize-storybook-7-6/#22x-faster-react-docgen), and [SWC support for Webpack projects](/blog/optimize-storybook-7-6/#using-webpack-enable-swc) -- โœจ Improved framework support: you no longer need to install React as a peer dependency when using a non-React renderer -- ๐ŸŒ [Support for React Server Components (RSC)](/blog/storybook-react-server-components/): our experimental solution renders async RSC in the browser and mocks Node code +Storybook 8 focuses on improving performance, compatibility, and stability. Key features include: + +- ๐Ÿฉป A new visual testing workflow via [the Visual Tests addon](https://www.chromatic.com/docs/visual-tests-addon/) +- ๐Ÿ’จ [2-4x faster test builds](https://storybook.js.org/blog/optimize-storybook-7-6/#2-4x-faster-builds-with-thetest-flag), [25-50% faster React docgen](https://storybook.js.org/blog/optimize-storybook-7-6/#22x-faster-react-docgen), and [SWC support for Webpack projects](https://storybook.js.org/blog/optimize-storybook-7-6/#using-webpack-enable-swc) +- ๐Ÿงฉ Improved framework support: you no longer need to install React as a peer dependency when using a non-React renderer +- ๐ŸŽ›๏ธย Strengthened control generation in [React](https://storybook.js.org/blog/storybook-8-beta/#major-performance-improvements +) and [Vue](https://storybook.js.org/blog/first-class-vue-support-storybook-8/) projects +- โšก๏ธ Improved Vite architecture, Vitest testing, and Vite 5 support +- ๐ŸŒ [Support for React Server Components (RSC)](https://storybook.js.org/blog/storybook-react-server-components/): our experimental solution renders async RSC in the browser and mocks Node code +- โœจ A refreshed desktop UI & mobile UX - โž• Much, much more This guide is meant to help you **upgrade from Storybook 7.x to 8.0** successfully! @@ -79,6 +84,10 @@ If you have `storyStoreV7: false` in your `.storybook/main.js`, you will need to If you are using the `storiesOf` API (which requires `storyStoreV7: false` in Storybook 7), you will need to either [migrate your stories to CSF](../../release-7-6/docs/migration-guide.md#storiesof-to-csf) or use the [new indexer API to continue creating stories dynamically](../../release-7-6/docs/migration-guide.md#storiesof-to-dynamically-created-stories). +#### Missing `vite.config.js` file + +If you are using Vite, you may now need to create a `vite.config.js` file in your project root to allow newer versions of Vite to work with Storybook. Additionally, you may need to install and configure a Vite plugin for your framework. More information is available in the [full migration notes](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#framework-specific-vite-plugins-have-to-be-explicitly-added). + ## New projects To add Storybook to a project that isnโ€™t currently using Storybook: diff --git a/docs/snippets/angular/angular-add-framework.js.mdx b/docs/snippets/angular/angular-add-framework.js.mdx new file mode 100644 index 000000000000..00e5c2474ab6 --- /dev/null +++ b/docs/snippets/angular/angular-add-framework.js.mdx @@ -0,0 +1,7 @@ +```js +// .storybook/main.js +export default { + // ... + framework: '@storybook/angular', // ๐Ÿ‘ˆ Add this +}; +``` diff --git a/docs/snippets/angular/angular-add-framework.ts.mdx b/docs/snippets/angular/angular-add-framework.ts.mdx new file mode 100644 index 000000000000..cdc3c6ccd1e3 --- /dev/null +++ b/docs/snippets/angular/angular-add-framework.ts.mdx @@ -0,0 +1,11 @@ +```ts +// .storybook/main.ts +import { StorybookConfig } from '@storybook/angular'; + +const config: StorybookConfig = { + // ... + framework: '@storybook/angular', // ๐Ÿ‘ˆ Add this +}; + +export default config; +``` diff --git a/docs/snippets/angular/angular-install.npm.js.mdx b/docs/snippets/angular/angular-install.npm.js.mdx new file mode 100644 index 000000000000..c8728d58c565 --- /dev/null +++ b/docs/snippets/angular/angular-install.npm.js.mdx @@ -0,0 +1,3 @@ +```shell +npm install --save-dev @storybook/angular +``` diff --git a/docs/snippets/angular/angular-install.pnpm.js.mdx b/docs/snippets/angular/angular-install.pnpm.js.mdx new file mode 100644 index 000000000000..5467721722b2 --- /dev/null +++ b/docs/snippets/angular/angular-install.pnpm.js.mdx @@ -0,0 +1,3 @@ +```shell +pnpm install --save-dev @storybook/angular +``` diff --git a/docs/snippets/angular/angular-install.yarn.js.mdx b/docs/snippets/angular/angular-install.yarn.js.mdx new file mode 100644 index 000000000000..9943e0163db2 --- /dev/null +++ b/docs/snippets/angular/angular-install.yarn.js.mdx @@ -0,0 +1,3 @@ +```shell +yarn add --dev @storybook/angular +``` diff --git a/docs/snippets/common/individual-snapshot-tests-portable-stories.jest.js.mdx b/docs/snippets/common/individual-snapshot-tests-portable-stories.jest.js.mdx new file mode 100644 index 000000000000..e9523fa3b322 --- /dev/null +++ b/docs/snippets/common/individual-snapshot-tests-portable-stories.jest.js.mdx @@ -0,0 +1,69 @@ +```js +// storybook.test.js +import path from 'path'; +import * as glob from 'glob'; + +//๐Ÿ‘‡ Augment expect with jest-specific-snapshot +import 'jest-specific-snapshot'; + +import { describe, test, expect } from '@jest/globals'; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +const compose = (entry) => { + try { + return composeStories(entry); + } catch (e) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${e}`, + ); + } +}; + +function getAllStoryFiles() { + // Place the glob you want to match your stories files + const storyFiles = glob.sync( + path.join(__dirname, 'stories/**/*.{stories,story}.{js,jsx,mjs,ts,tsx}'), + ); + + return storyFiles.map((filePath) => { + const storyFile = require(filePath); + const storyDir = path.dirname(filePath); + const componentName = path.basename(filePath).replace(/\.(stories|story)\.[^/.]+$/, ''); + + return { filePath, storyFile, storyDir, componentName }; + }); +} + +describe('Stories Snapshots', () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map(([name, story]) => ({ name, story })); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.`, + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + // Defines the custom snapshot path location and file name + const customSnaphotPath = `./__snapshots__/${componentName}.test.js.snap`; + expect(mounted.container).toMatchSpecificSnapshot(customSnaphotPath); + }); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/individual-snapshot-tests-portable-stories.jest.ts.mdx b/docs/snippets/common/individual-snapshot-tests-portable-stories.jest.ts.mdx new file mode 100644 index 000000000000..e245ec4c1ee9 --- /dev/null +++ b/docs/snippets/common/individual-snapshot-tests-portable-stories.jest.ts.mdx @@ -0,0 +1,82 @@ +```ts +// storybook.test.ts +// Replace your-framework with one of the supported Storybook frameworks (react, vue3) +import type { Meta, StoryFn } from '@storybook/your-framework'; + +import path from "path"; +import * as glob from "glob"; + +//๐Ÿ‘‡ Augment expect with jest-specific-snapshot +import "jest-specific-snapshot"; + +import { describe, test, expect } from "@jest/globals"; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +type StoryFile = { + default: Meta; + [name: string]: StoryFn | Meta; +}; + +const compose = ( + entry: StoryFile +): ReturnType> => { + try { + return composeStories(entry); + } catch (e) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${e}` + ); + } +}; + +function getAllStoryFiles() { + // Place the glob you want to match your stories files + const storyFiles = glob.sync( + path.join(__dirname, 'stories/**/*.{stories,story}.{js,jsx,mjs,ts,tsx}'), + ); + + return storyFiles.map((filePath) => { + const storyFile = require(filePath); + const storyDir = path.dirname(filePath); + const componentName = path + .basename(filePath) + .replace(/\.(stories|story)\.[^/.]+$/, ""); + + return { filePath, storyFile, storyDir, componentName }; + }); +} + +describe("Stories Snapshots", () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map( + ([name, story]) => ({ name, story }) + ); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.` + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + // Defines the custom snapshot path location and file name + const customSnaphotPath = `./__snapshots__/${componentName}.test.ts.snap`; + expect(mounted.container).toMatchSpecificSnapshot(customSnaphotPath); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/individual-snapshot-tests-portable-stories.vitest.js.mdx b/docs/snippets/common/individual-snapshot-tests-portable-stories.vitest.js.mdx new file mode 100644 index 000000000000..111149d958bb --- /dev/null +++ b/docs/snippets/common/individual-snapshot-tests-portable-stories.vitest.js.mdx @@ -0,0 +1,64 @@ +```js +// storybook.test.js +// @vitest-environment jsdom + +import path from 'path'; +import { describe, expect, test } from 'vitest'; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +const compose = (entry) => { + try { + return composeStories(entry); + } catch (error) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${error}`, + ); + } +}; +function getAllStoryFiles() { + // Place the glob you want to match your story files + const storyFiles = Object.entries( + import.meta.glob('./stories/**/*.(stories|story).@(js|jsx|mjs|ts|tsx)', { + eager: true, + }), + ); + + return storyFiles.map(([filePath, storyFile]) => { + const storyDir = path.dirname(filePath); + const componentName = path.basename(filePath).replace(/\.(stories|story)\.[^/.]+$/, ''); + return { filePath, storyFile, componentName, storyDir }; + }); +} +describe('Stories Snapshots', () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map(([name, story]) => ({ name, story })); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.`, + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + // Defines the custom snapshot path location and file name + const customSnaphotPath = `./__snapshots__/${componentName}.spec.js.snap`; + expect(mounted.container).toMatchFileSnapshot(customSnaphotPath); + }); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/individual-snapshot-tests-portable-stories.vitest.ts.mdx b/docs/snippets/common/individual-snapshot-tests-portable-stories.vitest.ts.mdx new file mode 100644 index 000000000000..5c3f6097dae8 --- /dev/null +++ b/docs/snippets/common/individual-snapshot-tests-portable-stories.vitest.ts.mdx @@ -0,0 +1,74 @@ +```ts +// storybook.test.ts +// @vitest-environment jsdom + +// Replace your-framework with one of the supported Storybook frameworks (react, vue3) +import type { Meta, StoryFn } from '@storybook/your-framework'; + +import path from 'path'; +import { describe, expect, test } from 'vitest'; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +type StoryFile = { + default: Meta; + [name: string]: StoryFn | Meta; +}; + +const compose = (entry: StoryFile): ReturnType> => { + try { + return composeStories(entry); + } catch (e) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${e}`, + ); + } +}; + +function getAllStoryFiles() { + // Place the glob you want to match your story files + const storyFiles = Object.entries( + import.meta.glob('./stories/**/*.(stories|story).@(js|jsx|mjs|ts|tsx)', { + eager: true, + }), + ); + + return storyFiles.map(([filePath, storyFile]) => { + const storyDir = path.dirname(filePath); + const componentName = path.basename(filePath).replace(/\.(stories|story)\.[^/.]+$/, ''); + return { filePath, storyFile, componentName, storyDir }; + }); +} + +describe('Stories Snapshots', () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map(([name, story]) => ({ name, story })); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.`, + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + // Defines the custom snapshot path location and file name + const customSnaphotPath = `./__snapshots__/${componentName}.spec.ts.snap`; + expect(mounted.container).toMatchFileSnapshot(customSnaphotPath); + }); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/init-command-specific-version.npx.js.mdx b/docs/snippets/common/init-command-specific-version.npx.js.mdx deleted file mode 100644 index fd10b63fb0ce..000000000000 --- a/docs/snippets/common/init-command-specific-version.npx.js.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```shell -npx storybook@7.6.6 init -``` diff --git a/docs/snippets/common/init-command-specific-version.pnpm.js.mdx b/docs/snippets/common/init-command-specific-version.pnpm.js.mdx deleted file mode 100644 index 351ed4eda295..000000000000 --- a/docs/snippets/common/init-command-specific-version.pnpm.js.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```shell -pnpm dlx storybook@7.6.6 init -``` diff --git a/docs/snippets/common/init-command-specific-version.yarn.js.mdx b/docs/snippets/common/init-command-specific-version.yarn.js.mdx deleted file mode 100644 index af093e4f96dd..000000000000 --- a/docs/snippets/common/init-command-specific-version.yarn.js.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```shell -yarn dlx storybook@7.6.6 init -``` diff --git a/docs/snippets/common/snapshot-tests-portable-stories.jest.js.mdx b/docs/snippets/common/snapshot-tests-portable-stories.jest.js.mdx new file mode 100644 index 000000000000..eddd82a08227 --- /dev/null +++ b/docs/snippets/common/snapshot-tests-portable-stories.jest.js.mdx @@ -0,0 +1,64 @@ +```js +// storybook.test.js +import path from 'path'; +import * as glob from 'glob'; + +import { describe, test, expect } from '@jest/globals'; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +const compose = (entry) => { + try { + return composeStories(entry); + } catch (e) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${e}`, + ); + } +}; + +function getAllStoryFiles() { + // Place the glob you want to match your stories files + const storyFiles = glob.sync( + path.join(__dirname, 'stories/**/*.{stories,story}.{js,jsx,mjs,ts,tsx}'), + ); + + return storyFiles.map((filePath) => { + const storyFile = require(filePath); + const storyDir = path.dirname(filePath); + const componentName = path.basename(filePath).replace(/\.(stories|story)\.[^/.]+$/, ''); + + return { filePath, storyFile, storyDir, componentName }; + }); +} + +describe('Stories Snapshots', () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map(([name, story]) => ({ name, story })); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.`, + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + expect(mounted.container).toMatchSnapshot(); + }); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/snapshot-tests-portable-stories.jest.ts.mdx b/docs/snippets/common/snapshot-tests-portable-stories.jest.ts.mdx new file mode 100644 index 000000000000..1cfbe1bdbb35 --- /dev/null +++ b/docs/snippets/common/snapshot-tests-portable-stories.jest.ts.mdx @@ -0,0 +1,72 @@ +```ts +// storybook.test.ts +// Replace your-framework with one of the supported Storybook frameworks (react, vue3) +import type { Meta, StoryFn } from '@storybook/your-framework'; + +import path from 'path'; +import * as glob from 'glob'; + +import { describe, test, expect } from '@jest/globals'; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +type StoryFile = { + default: Meta; + [name: string]: StoryFn | Meta; +}; + +const compose = (entry: StoryFile): ReturnType> => { + try { + return composeStories(entry); + } catch (e) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${e}`, + ); + } +}; + +function getAllStoryFiles() { + // Place the glob you want to match your stories files + const storyFiles = glob.sync( + path.join(__dirname, 'stories/**/*.{stories,story}.{js,jsx,mjs,ts,tsx}'), + ); + + return storyFiles.map((filePath) => { + const storyFile = require(filePath); + const storyDir = path.dirname(filePath); + const componentName = path.basename(filePath).replace(/\.(stories|story)\.[^/.]+$/, ''); + + return { filePath, storyFile, storyDir, componentName }; + }); +} + +describe('Stories Snapshots', () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map(([name, story]) => ({ name, story })); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.`, + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + expect(mounted.container).toMatchSnapshot(); + }); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/snapshot-tests-portable-stories.vitest.js.mdx b/docs/snippets/common/snapshot-tests-portable-stories.vitest.js.mdx new file mode 100644 index 000000000000..dbaa397f1bb3 --- /dev/null +++ b/docs/snippets/common/snapshot-tests-portable-stories.vitest.js.mdx @@ -0,0 +1,62 @@ +```js +// storybook.test.js +// @vitest-environment jsdom + +import path from 'path'; +import { describe, expect, test } from 'vitest'; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +const compose = (entry) => { + try { + return composeStories(entry); + } catch (error) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${error}`, + ); + } +}; +function getAllStoryFiles() { + // Place the glob you want to match your story files + const storyFiles = Object.entries( + import.meta.glob('./stories/**/*.(stories|story).@(js|jsx|mjs|ts|tsx)', { + eager: true, + }), + ); + + return storyFiles.map(([filePath, storyFile]) => { + const storyDir = path.dirname(filePath); + const componentName = path.basename(filePath).replace(/\.(stories|story)\.[^/.]+$/, ''); + return { filePath, storyFile, componentName, storyDir }; + }); +} +describe('Stories Snapshots', () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map(([name, story]) => ({ name, story })); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.`, + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + expect(mounted.container).toMatchSnapshot(); + }); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/snapshot-tests-portable-stories.vitest.ts.mdx b/docs/snippets/common/snapshot-tests-portable-stories.vitest.ts.mdx new file mode 100644 index 000000000000..456bf5a1ae9d --- /dev/null +++ b/docs/snippets/common/snapshot-tests-portable-stories.vitest.ts.mdx @@ -0,0 +1,72 @@ +```ts +// storybook.test.ts +// @vitest-environment jsdom + +// Replace your-framework with one of the supported Storybook frameworks (react, vue3) +import type { Meta, StoryFn } from '@storybook/your-framework'; + +import path from 'path'; +import { describe, expect, test } from 'vitest'; + +// Replace your-testing-library with one of the supported testing libraries (e.g., react, vue) +import { render } from '@testing-library/your-testing-library'; + +// Adjust the import based on the supported framework or Storybook's testing libraries (e.g., react, vue3) +import { composeStories } from '@storybook/your-framework'; + +type StoryFile = { + default: Meta; + [name: string]: StoryFn | Meta; +}; + +const compose = (entry: StoryFile): ReturnType> => { + try { + return composeStories(entry); + } catch (e) { + throw new Error( + `There was an issue composing stories for the module: ${JSON.stringify(entry)}, ${e}`, + ); + } +}; + +function getAllStoryFiles() { + // Place the glob you want to match your story files + const storyFiles = Object.entries( + import.meta.glob('./stories/**/*.(stories|story).@(js|jsx|mjs|ts|tsx)', { + eager: true, + }), + ); + + return storyFiles.map(([filePath, storyFile]) => { + const storyDir = path.dirname(filePath); + const componentName = path.basename(filePath).replace(/\.(stories|story)\.[^/.]+$/, ''); + return { filePath, storyFile, componentName, storyDir }; + }); +} + +describe('Stories Snapshots', () => { + getAllStoryFiles().forEach(({ storyFile, componentName }) => { + const meta = storyFile.default; + const title = meta.title || componentName; + + describe(title, () => { + const stories = Object.entries(compose(storyFile)).map(([name, story]) => ({ name, story })); + + if (stories.length <= 0) { + throw new Error( + `No stories found for this module: ${title}. Make sure there is at least one valid story for this module.`, + ); + } + + stories.forEach(({ name, story }) => { + test(name, async () => { + const mounted = render(story()); + // Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot. + await new Promise((resolve) => setTimeout(resolve, 1)); + expect(mounted.container).toMatchSnapshot(); + }); + }); + }); + }); +}); +``` diff --git a/docs/snippets/common/storybook-init-v7.npx.js.mdx b/docs/snippets/common/storybook-init-v7.npx.js.mdx new file mode 100644 index 000000000000..33a0a5b19737 --- /dev/null +++ b/docs/snippets/common/storybook-init-v7.npx.js.mdx @@ -0,0 +1,3 @@ +```shell +npx storybook@^7 init +``` diff --git a/docs/snippets/common/storybook-init-v7.pnpm.js.mdx b/docs/snippets/common/storybook-init-v7.pnpm.js.mdx new file mode 100644 index 000000000000..19ae54c8d049 --- /dev/null +++ b/docs/snippets/common/storybook-init-v7.pnpm.js.mdx @@ -0,0 +1,3 @@ +```shell +pnpm dlx storybook@^7 init +``` diff --git a/docs/snippets/common/storybook-init-v7.yarn.js.mdx b/docs/snippets/common/storybook-init-v7.yarn.js.mdx new file mode 100644 index 000000000000..8001609fe3ca --- /dev/null +++ b/docs/snippets/common/storybook-init-v7.yarn.js.mdx @@ -0,0 +1,3 @@ +```shell +yarn dlx storybook@^7 init +``` diff --git a/docs/snippets/common/test-runner-snapshot-resolver-custom-directory.js.mdx b/docs/snippets/common/test-runner-snapshot-resolver-custom-directory.js.mdx new file mode 100644 index 000000000000..203c8d30cbb2 --- /dev/null +++ b/docs/snippets/common/test-runner-snapshot-resolver-custom-directory.js.mdx @@ -0,0 +1,19 @@ +```js +// ./snapshot-resolver.js +import path from 'path'; + +export default { + resolveSnapshotPath: (testPath) => { + const fileName = path.basename(testPath); + const fileNameWithoutExtension = fileName.replace(/\.[^/.]+$/, ''); + // Defines the file extension for the snapshot file + const modifiedFileName = `${fileNameWithoutExtension}.snap`; + + // Configure Jest to generate snapshot files using the following convention (./src/test/__snapshots__/Button.stories.snap) + return path.join('./src/test/__snapshots__', modifiedFileName); + }, + resolveTestPath: (snapshotFilePath, snapshotExtension) => + path.basename(snapshotFilePath, snapshotExtension), + testPathForConsistencyCheck: 'example', +}; +``` diff --git a/docs/snippets/react/button-snapshot-test-portable-stories.jest.js.mdx b/docs/snippets/react/button-snapshot-test-portable-stories.jest.js.mdx new file mode 100644 index 000000000000..335eb461d736 --- /dev/null +++ b/docs/snippets/react/button-snapshot-test-portable-stories.jest.js.mdx @@ -0,0 +1,14 @@ +```js +// test/Button.test.js|ts +import { render } from '@testing-library/react'; + +import { composeStories } from '@storybook/react'; + +import * as stories from '../stories/Button.stories'; + +const { Primary } = composeStories(stories); +test('Button snapshot', async () => { + const mounted = render(); + expect(mounted.container).toMatchSnapshot(); +}); +``` diff --git a/docs/snippets/react/button-snapshot-test-portable-stories.vitest.js.mdx b/docs/snippets/react/button-snapshot-test-portable-stories.vitest.js.mdx new file mode 100644 index 000000000000..982992cc65aa --- /dev/null +++ b/docs/snippets/react/button-snapshot-test-portable-stories.vitest.js.mdx @@ -0,0 +1,18 @@ +```js +// test/Button.test.js|ts +// @vitest-environment jsdom + +import { expect, test } from 'vitest'; + +import { render } from '@testing-library/react'; + +import { composeStories } from '@storybook/react'; + +import * as stories from '../stories/Button.stories'; + +const { Primary } = composeStories(stories); +test('Button snapshot', async () => { + const mounted = render(Primary()); + expect(mounted.container).toMatchSnapshot(); +}); +``` diff --git a/docs/snippets/react/react-vite-add-framework.js.mdx b/docs/snippets/react/react-vite-add-framework.js.mdx new file mode 100644 index 000000000000..7a268b5768f0 --- /dev/null +++ b/docs/snippets/react/react-vite-add-framework.js.mdx @@ -0,0 +1,8 @@ +```js +// .storybook/main.js +export default { + // ... + // framework: '@storybook/react-webpack5', ๐Ÿ‘ˆ Remove this + framework: '@storybook/react-vite', // ๐Ÿ‘ˆ Add this +}; +``` diff --git a/docs/snippets/react/react-vite-add-framework.ts.mdx b/docs/snippets/react/react-vite-add-framework.ts.mdx new file mode 100644 index 000000000000..c407f12cc0a7 --- /dev/null +++ b/docs/snippets/react/react-vite-add-framework.ts.mdx @@ -0,0 +1,12 @@ +```ts +// .storybook/main.ts +import { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + // ... + // framework: '@storybook/react-webpack5', ๐Ÿ‘ˆ Remove this + framework: '@storybook/react-vite', // ๐Ÿ‘ˆ Add this +}; + +export default config; +``` diff --git a/docs/snippets/react/react-vite-install.npm.js.mdx b/docs/snippets/react/react-vite-install.npm.js.mdx new file mode 100644 index 000000000000..6a9b052c19bb --- /dev/null +++ b/docs/snippets/react/react-vite-install.npm.js.mdx @@ -0,0 +1,3 @@ +```shell +npm install --save-dev @storybook/react-vite +``` diff --git a/docs/snippets/react/react-vite-install.pnpm.js.mdx b/docs/snippets/react/react-vite-install.pnpm.js.mdx new file mode 100644 index 000000000000..10b128bb0b31 --- /dev/null +++ b/docs/snippets/react/react-vite-install.pnpm.js.mdx @@ -0,0 +1,3 @@ +```shell +pnpm install --save-dev @storybook/react-vite +``` diff --git a/docs/snippets/react/react-vite-install.yarn.js.mdx b/docs/snippets/react/react-vite-install.yarn.js.mdx new file mode 100644 index 000000000000..a566adef61ba --- /dev/null +++ b/docs/snippets/react/react-vite-install.yarn.js.mdx @@ -0,0 +1,3 @@ +```shell +yarn add --dev @storybook/react-vite +``` diff --git a/docs/snippets/react/react-webpack5-add-framework.js.mdx b/docs/snippets/react/react-webpack5-add-framework.js.mdx new file mode 100644 index 000000000000..cbacf99bd80a --- /dev/null +++ b/docs/snippets/react/react-webpack5-add-framework.js.mdx @@ -0,0 +1,7 @@ +```js +// .storybook/main.js +export default { + // ... + framework: '@storybook/react-webpack5', // ๐Ÿ‘ˆ Add this +}; +``` diff --git a/docs/snippets/react/react-webpack5-add-framework.ts.mdx b/docs/snippets/react/react-webpack5-add-framework.ts.mdx new file mode 100644 index 000000000000..2417fd5ea98a --- /dev/null +++ b/docs/snippets/react/react-webpack5-add-framework.ts.mdx @@ -0,0 +1,11 @@ +```ts +// .storybook/main.ts +import { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { + // ... + framework: '@storybook/react-webpack5', // ๐Ÿ‘ˆ Add this +}; + +export default config; +``` diff --git a/docs/snippets/react/react-webpack5-install.npm.js.mdx b/docs/snippets/react/react-webpack5-install.npm.js.mdx new file mode 100644 index 000000000000..8b54052f3f28 --- /dev/null +++ b/docs/snippets/react/react-webpack5-install.npm.js.mdx @@ -0,0 +1,3 @@ +```shell +npm install --save-dev @storybook/react-webpack5 +``` diff --git a/docs/snippets/react/react-webpack5-install.pnpm.js.mdx b/docs/snippets/react/react-webpack5-install.pnpm.js.mdx new file mode 100644 index 000000000000..840d64ae06c9 --- /dev/null +++ b/docs/snippets/react/react-webpack5-install.pnpm.js.mdx @@ -0,0 +1,3 @@ +```shell +pnpm install --save-dev @storybook/react-webpack5 +``` diff --git a/docs/snippets/react/react-webpack5-install.yarn.js.mdx b/docs/snippets/react/react-webpack5-install.yarn.js.mdx new file mode 100644 index 000000000000..b4f143c8a120 --- /dev/null +++ b/docs/snippets/react/react-webpack5-install.yarn.js.mdx @@ -0,0 +1,3 @@ +```shell +yarn add --dev @storybook/react-webpack5 +``` diff --git a/docs/snippets/react/storybook-testing-addon-optional-config.vite.js.mdx b/docs/snippets/react/storybook-testing-addon-optional-config.vite.js.mdx new file mode 100644 index 000000000000..a50bd78cb49b --- /dev/null +++ b/docs/snippets/react/storybook-testing-addon-optional-config.vite.js.mdx @@ -0,0 +1,20 @@ +```js +// vitest.config.js + +import { defineConfig } from 'vitest/config'; +import { mergeConfig } from 'vite'; + +import viteConfig from './vite.config'; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + globals: true, + environment: 'jsdom', + clearMocks: true, + setupFiles: './src/setupTests.js', //๐Ÿ‘ˆ Our configuration file enabled here + }, + }), +); +``` diff --git a/docs/snippets/react/storybook-testing-addon-optional-config.vite.ts.mdx b/docs/snippets/react/storybook-testing-addon-optional-config.vite.ts.mdx new file mode 100644 index 000000000000..3161eb45448c --- /dev/null +++ b/docs/snippets/react/storybook-testing-addon-optional-config.vite.ts.mdx @@ -0,0 +1,21 @@ +```ts +// vitest.config.ts + +/// +import { defineConfig } from 'vitest/config'; +import { mergeConfig } from 'vite'; + +import viteConfig from './vite.config'; + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + globals: true, + environment: 'jsdom', + clearMocks: true, + setupFiles: './src/setupTests.ts', //๐Ÿ‘ˆ Our configuration file enabled here + }, + }), +); +``` diff --git a/docs/snippets/svelte/svelte-csf-addon-install.npm.js.mdx b/docs/snippets/svelte/svelte-csf-addon-install.npm.js.mdx index 574d63651863..3889ca8909c4 100644 --- a/docs/snippets/svelte/svelte-csf-addon-install.npm.js.mdx +++ b/docs/snippets/svelte/svelte-csf-addon-install.npm.js.mdx @@ -1,3 +1,3 @@ ```shell -npm install @storybook/addon-svelte-csf --save-dev +npx storybook@latest add @storybook/addon-svelte-csf ``` diff --git a/docs/snippets/svelte/svelte-csf-addon-install.pnpm.js.mdx b/docs/snippets/svelte/svelte-csf-addon-install.pnpm.js.mdx index 4ff9be66f107..eb8c09e0708c 100644 --- a/docs/snippets/svelte/svelte-csf-addon-install.pnpm.js.mdx +++ b/docs/snippets/svelte/svelte-csf-addon-install.pnpm.js.mdx @@ -1,3 +1,3 @@ ```shell -pnpm add --save-dev @storybook/addon-svelte-csf +pnpm dlx storybook@latest add @storybook/addon-svelte-csf ``` diff --git a/docs/snippets/svelte/svelte-csf-addon-install.yarn.js.mdx b/docs/snippets/svelte/svelte-csf-addon-install.yarn.js.mdx index 5b3e6dff23f6..52ecff831d4c 100644 --- a/docs/snippets/svelte/svelte-csf-addon-install.yarn.js.mdx +++ b/docs/snippets/svelte/svelte-csf-addon-install.yarn.js.mdx @@ -1,3 +1,3 @@ ```shell -yarn add --dev @storybook/addon-svelte-csf +yarn storybook@latest add @storybook/addon-svelte-csf ``` diff --git a/docs/snippets/svelte/svelte-vite-add-framework.js.mdx b/docs/snippets/svelte/svelte-vite-add-framework.js.mdx new file mode 100644 index 000000000000..a16370254866 --- /dev/null +++ b/docs/snippets/svelte/svelte-vite-add-framework.js.mdx @@ -0,0 +1,7 @@ +```js +// .storybook/main.js +export default { + // ... + framework: '@storybook/svelte-vite', // ๐Ÿ‘ˆ Add this +}; +``` diff --git a/docs/snippets/svelte/svelte-vite-add-framework.ts.mdx b/docs/snippets/svelte/svelte-vite-add-framework.ts.mdx new file mode 100644 index 000000000000..920d91ae6d13 --- /dev/null +++ b/docs/snippets/svelte/svelte-vite-add-framework.ts.mdx @@ -0,0 +1,11 @@ +```ts +// .storybook/main.ts +import { StorybookConfig } from '@storybook/svelte-vite'; + +const config: StorybookConfig = { + // ... + framework: '@storybook/svelte-vite', // ๐Ÿ‘ˆ Add this +}; + +export default config; +``` diff --git a/docs/snippets/svelte/svelte-vite-install.npm.js.mdx b/docs/snippets/svelte/svelte-vite-install.npm.js.mdx new file mode 100644 index 000000000000..8b6986b5ecfa --- /dev/null +++ b/docs/snippets/svelte/svelte-vite-install.npm.js.mdx @@ -0,0 +1,3 @@ +```shell +npm install --save-dev @storybook/svelte-vite +``` diff --git a/docs/snippets/svelte/svelte-vite-install.pnpm.js.mdx b/docs/snippets/svelte/svelte-vite-install.pnpm.js.mdx new file mode 100644 index 000000000000..585bc12393ca --- /dev/null +++ b/docs/snippets/svelte/svelte-vite-install.pnpm.js.mdx @@ -0,0 +1,3 @@ +```shell +pnpm install --save-dev @storybook/svelte-vite +``` diff --git a/docs/snippets/svelte/svelte-vite-install.yarn.js.mdx b/docs/snippets/svelte/svelte-vite-install.yarn.js.mdx new file mode 100644 index 000000000000..7a8b11a4d500 --- /dev/null +++ b/docs/snippets/svelte/svelte-vite-install.yarn.js.mdx @@ -0,0 +1,3 @@ +```shell +yarn add --dev @storybook/svelte-vite +``` diff --git a/docs/snippets/vue/button-snapshot-test-portable-stories.js.mdx b/docs/snippets/vue/button-snapshot-test-portable-stories.js.mdx new file mode 100644 index 000000000000..06d28200e454 --- /dev/null +++ b/docs/snippets/vue/button-snapshot-test-portable-stories.js.mdx @@ -0,0 +1,18 @@ +```js +// __tests__/Button.spec.js|ts +// @vitest-environment jsdom + +import { expect, test } from 'vitest'; + +import { render } from '@testing-library/vue'; + +import { composeStories } from '@storybook/vue3'; + +import * as stories from '../stories/Button.stories'; + +const { Primary } = composeStories(stories); +test('Button snapshot', async () => { + const mounted = render(Primary()); + expect(mounted.container).toMatchSnapshot(); +}); +``` diff --git a/docs/snippets/vue/vue3-vite-add-framework.js.mdx b/docs/snippets/vue/vue3-vite-add-framework.js.mdx new file mode 100644 index 000000000000..009f6f74b579 --- /dev/null +++ b/docs/snippets/vue/vue3-vite-add-framework.js.mdx @@ -0,0 +1,7 @@ +```js +// .storybook/main.js +export default { + // ... + framework: '@storybook/vue3-vite', // ๐Ÿ‘ˆ Add this +}; +``` diff --git a/docs/snippets/vue/vue3-vite-add-framework.ts.mdx b/docs/snippets/vue/vue3-vite-add-framework.ts.mdx new file mode 100644 index 000000000000..c02ed2ed0b3b --- /dev/null +++ b/docs/snippets/vue/vue3-vite-add-framework.ts.mdx @@ -0,0 +1,11 @@ +```ts +// .storybook/main.ts +import { StorybookConfig } from '@storybook/nextjs'; + +const config: StorybookConfig = { + // ... + framework: '@storybook/vue3-vite', // ๐Ÿ‘ˆ Add this +}; + +export default config; +``` diff --git a/docs/snippets/vue/vue3-vite-install.npm.js.mdx b/docs/snippets/vue/vue3-vite-install.npm.js.mdx new file mode 100644 index 000000000000..1d023d6e253c --- /dev/null +++ b/docs/snippets/vue/vue3-vite-install.npm.js.mdx @@ -0,0 +1,3 @@ +```shell +npm install --save-dev @storybook/vue3-vite +``` diff --git a/docs/snippets/vue/vue3-vite-install.pnpm.js.mdx b/docs/snippets/vue/vue3-vite-install.pnpm.js.mdx new file mode 100644 index 000000000000..3c8db13088d7 --- /dev/null +++ b/docs/snippets/vue/vue3-vite-install.pnpm.js.mdx @@ -0,0 +1,3 @@ +```shell +pnpm install --save-dev @storybook/vue3-vite +``` diff --git a/docs/snippets/vue/vue3-vite-install.yarn.js.mdx b/docs/snippets/vue/vue3-vite-install.yarn.js.mdx new file mode 100644 index 000000000000..427eb154d182 --- /dev/null +++ b/docs/snippets/vue/vue3-vite-install.yarn.js.mdx @@ -0,0 +1,3 @@ +```shell +yarn add --dev @storybook/vue3-vite +``` diff --git a/docs/toc.js b/docs/toc.js index b7ee152fb8c6..5b660a93cce5 100644 --- a/docs/toc.js +++ b/docs/toc.js @@ -23,11 +23,36 @@ module.exports = { title: 'Frameworks', type: 'menu', children: [ + { + pathSegment: 'angular', + title: 'Angular', + type: 'link', + }, { pathSegment: 'nextjs', title: 'Next.js', type: 'link', }, + { + pathSegment: 'react-vite', + title: 'React & Vite', + type: 'link', + }, + { + pathSegment: 'react-webpack5', + title: 'React & Webpack', + type: 'link', + }, + { + pathSegment: 'svelte-vite', + title: 'Svelte & Vite', + type: 'link', + }, + { + pathSegment: 'vue3-vite', + title: 'Vue & Vite', + type: 'link', + }, ], }, { @@ -173,12 +198,12 @@ module.exports = { children: [ { pathSegment: 'snapshot-testing', - title: 'Storyshots', + title: 'Write', type: 'link', }, { pathSegment: 'storyshots-migration-guide', - title: 'Migration guide', + title: 'Storyshots migration guide', type: 'link', }, ], diff --git a/docs/versions/next.json b/docs/versions/next.json index aefc27f51f56..e522ee4c40f2 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.0.0-rc.2","info":{"plain":"- CLI: Add @storybook/addons automigration - [#26295](https://github.com/storybookjs/storybook/pull/26295), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- CLI: Fix vite config automigration to resolve from project root - [#26262](https://github.com/storybookjs/storybook/pull/26262), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- CLI: Improve `add` command & add tests - [#26298](https://github.com/storybookjs/storybook/pull/26298), thanks [@ndelangen](https://github.com/ndelangen)!\n- CLI: Update minimum Node.js version requirement - [#26312](https://github.com/storybookjs/storybook/pull/26312), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- CSF-tools/Codemods: Upgrade recast - [#26286](https://github.com/storybookjs/storybook/pull/26286), thanks [@43081j](https://github.com/43081j)!\n- Controls: Fix type summary when table.type unset - [#26283](https://github.com/storybookjs/storybook/pull/26283), thanks [@shilman](https://github.com/shilman)!\n- Core: Add event when serverChannel disconnects - [#26322](https://github.com/storybookjs/storybook/pull/26322), thanks [@ndelangen](https://github.com/ndelangen)!\n- Core: Fix composition of storybooks on same origin - [#26304](https://github.com/storybookjs/storybook/pull/26304), thanks [@ndelangen](https://github.com/ndelangen)!\n- Portable stories: Improve existing APIs, add loaders support - [#26267](https://github.com/storybookjs/storybook/pull/26267), thanks [@yannbf](https://github.com/yannbf)!\n- React: Handle TypeScript path aliases in react-docgen loader - [#26273](https://github.com/storybookjs/storybook/pull/26273), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- Svelte: Support `5.0.0-next.65` prerelease - [#26188](https://github.com/storybookjs/storybook/pull/26188), thanks [@JReinhold](https://github.com/JReinhold)!\n- Upgrade: Add missing isUpgrade parameter to automigrate function - [#26293](https://github.com/storybookjs/storybook/pull/26293), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- Vue: Return component from `composeStory` - [#26317](https://github.com/storybookjs/storybook/pull/26317), thanks [@JReinhold](https://github.com/JReinhold)!"}} +{"version":"8.0.0-rc.5","info":{"plain":"- CLI: Automigration fix version detection of upgrading related packages - [#26410](https://github.com/storybookjs/storybook/pull/26410), thanks @ndelangen!"}} diff --git a/docs/writing-stories/naming-components-and-hierarchy.md b/docs/writing-stories/naming-components-and-hierarchy.md index 5757a2eda12a..b29b1135e2d5 100644 --- a/docs/writing-stories/naming-components-and-hierarchy.md +++ b/docs/writing-stories/naming-components-and-hierarchy.md @@ -146,12 +146,12 @@ The `storySort` can also accept a configuration object. -| Field | Type | Description | Required | Default Value | Example | -| ---------------- | :-----: | :------------------------------------------------------: | :------: | :---------------------: | :-----------------------: | -| **method** | String | Tells Storybook in which order the stories are displayed | No | Storybook configuration | `'alphabetical'` | -| **order** | Array | The stories to be shown, ordered by supplied name | No | Empty Array `[]` | `['Intro', 'Components']` | -| **includeNames** | Boolean | Include story name in sort calculation | No | `false` | `true` | -| **locales** | String | The locale required to be displayed | No | System locale | `en-US` | +| Field | Type | Description | Required | Default Value | Example | +| ---------------- | ------- | -------------------------------------------------------- | -------- | ----------------------- | ------------------------- | +| **method** | String | Tells Storybook in which order the stories are displayed | No | Storybook configuration | `'alphabetical'` | +| **order** | Array | The stories to be shown, ordered by supplied name | No | Empty Array `[]` | `['Intro', 'Components']` | +| **includeNames** | Boolean | Include story name in sort calculation | No | `false` | `true` | +| **locales** | String | The locale required to be displayed | No | System locale | `en-US` | To sort your stories alphabetically, set `method` to `'alphabetical'` and optionally set the `locales` string. To sort your stories using a custom list, use the `order` array; stories that don't match an item in the `order` list will appear after the items in the list. diff --git a/docs/writing-tests/snapshot-testing.md b/docs/writing-tests/snapshot-testing.md index 438258b36adb..36616674380d 100644 --- a/docs/writing-tests/snapshot-testing.md +++ b/docs/writing-tests/snapshot-testing.md @@ -1,5 +1,5 @@ --- -title: 'Snapshot testing with Storyshots' +title: 'Write snapshot tests' --- Snapshot tests compare the rendered markup of every story against known baselines. Itโ€™s a way to identify markup changes that trigger rendering errors and warnings. @@ -8,118 +8,195 @@ Storybook is a helpful tool for snapshot testing because every story is essentia ![Example Snapshot test](./snapshot-test.png) -## Migrating Tests + -The Storyshots addon was the original testing solution for Storybook, offering a highly extensible API and a wide range of configuration options for testing. However, it was difficult to set up and maintain, and it needed to be compatible with the latest version of Storybook, which introduced some significant architectural changes, including a high-performance [on-demand story loading](../configure/index.md#on-demand-story-loading) feature. As a result, Storyshots is now officially deprecated, is no longer being maintained, and will be removed in the next major release of Storybook. We recommend following the [migration guide](./storyshots-migration-guide.md) we've prepared to help you during this transition period. +If you're [upgrading](../configure/upgrading.md) to Storybook 8.0 and were using the Storyshots addon for snapshot testing, it was officially deprecated and removed with this release. See the [migration guide](./storyshots-migration-guide.md) for more information. -## Set up Storyshots + + +## Automate snapshot tests with the test-runner + +Storybook test-runner turns all of your stories into executable tests. Powered by [Jest](https://jestjs.io/) and [Playwright](https://playwright.dev/). It's a standalone, framework-agnostic utility that runs parallel to your Storybook. It enables you to run multiple testing patterns in a multi-browser environment, including interaction testing with the [play function](./interaction-testing.md), DOM snapshot, and [accessibility testing](./accessibility-testing.md). - +### Setup -The Storyshots addon was deprecated and has been removed in Storybook 8. See the [migration guide](./storyshots-migration-guide.md) for more information. +To enable snapshot testing with the test-runner, you'll need to take additional steps to set it up properly. We recommend you go through the [test-runner documentation](./test-runner.md) before proceeding with the rest of the required configuration to learn more about the available options and APIs. + +Add a new [configuration file](./test-runner.md#test-hook-api) inside your Storybook directory with the following inside: + + + + + + + + + +The `postVisit` hook allows you to extend the test runner's default configuration. Read more about them [here](./test-runner.md#test-hook-api). -[Storyshots](https://storybook.js.org/addons/@storybook/addon-storyshots/) is a Storybook addon that enables snapshot testing, powered by [Jest](https://jestjs.io/docs/getting-started). +When you execute the test-runner (for example, with `yarn test-storybook`), it will run through all of your stories and run the snapshot tests, generating a snapshot file for each story in your project located in the `__snapshots__` directory. + +### Configure -Run the following command to install Storyshots: +Out of the box, the test-runner provides an inbuilt snapshot testing configuration covering most use cases. You can also fine-tune the configuration to fit your needs via `test-storybook --eject` or by creating a `test-runner-jest.config.js` file at the root of your project. + +#### Override the default snapshot directory + +The test-runner uses a specific naming convention and path for the generated snapshot files by default. If you need to customize the snapshot directory, you can define a custom snapshot resolver to specify the directory where the snapshots are stored. + +Create a `snapshot-resolver.js` file to implement a custom snapshot resolver: -Add a test file to your environment with the following contents to configure Storyshots: +Update the `test-runner-jest.config.js` file and enable the `snapshotResolver` option to use the custom snapshot resolver: - +When the test-runner is executed, it will cycle through all of your stories and run the snapshot tests, generating a snapshot file for each story in your project located in the custom directory you specified. -You can name the test file differently to suit your needs. Bear in mind that it requires to be picked up by Jest. +#### Customize snapshot serialization - +By default, the test-runner uses [`jest-serializer-html`](https://github.com/algolia/jest-serializer-html) to serialize HTML snapshots. This may cause issues if you use specific CSS-in-JS libraries like [Emotion](https://emotion.sh/docs/introduction), Angular's `ng` attributes, or similar libraries that generate hash-based identifiers for CSS classes. If you need to customize the serialization of your snapshots, you can define a custom snapshot serializer to specify how the snapshots are serialized. -Run your first test. Storyshots will recognize your stories (based on [.storybook/main.js's setup](../configure/story-rendering.md)) and save them in the **snapshots** directory. +Create a `snapshot-serializer.js` file to implement a custom snapshot serializer: -```shell -npm test storybook.test.js -``` + -![Successful snapshot tests](./storyshots-pass.png) + -When you make changes to your components or stories, rerun the test to identify the changes to the rendered markup. + -![Failing snapshots](./storyshots-fail.png) +Update the `test-runner-jest.config.js` file and enable the `snapshotSerializers` option to use the custom snapshot resolver: -If they're intentional, accept them as new baselines. If the changes are bugs, fix the underlying code, then rerun the snapshot tests. + -### Configure the snapshot's directory + -If your project has a custom setup for snapshot testing, you'll need to take additional steps to run Storyshots. You'll need to install both [@storybook/addon-storyshots-puppeteer](https://storybook.js.org/addons/@storybook/addon-storyshots-puppeteer) and [puppeteer](https://github.com/puppeteer/puppeteer): + + +When the test-runner executes your tests, it will introspect the resulting HTML, replacing the dynamically generated attributes with the static ones provided by the regular expression in the custom serializer file before snapshotting the component. This ensures that the snapshots are consistent across different test runs. + + + + -```shell -# With npm -npm i -D @storybook/addon-storyshots-puppeteer puppeteer +## Snapshot tests with Portable Stories -# With yarn -yarn add @storybook/addon-storyshots-puppeteer puppeteer -``` +Storybook provides a `composeStories` utility that helps convert stories from a test file into renderable elements that can be reused in your Node tests with JSDOM. It also allows you to apply other Storybook features that you have enabled your project (e.g., [decorators](../writing-stories/decorators.md), [args](../writing-stories/args.md)) into your tests, enabling you to reuse your stories in your testing environment of choice (e.g., [Jest](https://jestjs.io/), [Vitest](https://vitest.dev/)), ensuring your tests are always in sync with your stories without having to rewrite them. This is what we refer to as portable stories in Storybook. -Next, update your test file (for example, `storybook.test.js`) to the following: +### Configure + +By default, Storybook offers a zero-config setup for React, Vue, and other frameworks via addons, allowing you to run your stories as tests with your testing environment of choice. However, if you're running tests and you've set up specific configurations in your Storybook instance (e.g., global [decorators](../writing-stories/decorators.md#global-decorators), [parameters](../writing-stories/parameters.md#global-parameters)) that you want to use in your tests, you'll need to extend your test setup to include these configurations. To do so, create a `setup.js|ts` file as follows: - +Update your test configuration file (e.g., `vite.config.js|ts`) if you're using [Vitest](https://vitest.dev/) or your test script if you're using [Jest](https://jestjs.io/): -Don't forget to replace your-custom-directory with your own. + - + -When you run your tests, the snapshots will be available in your specified directory. + -### Framework configuration +### Run tests on a single story -By default, Storyshots detects your project's framework. If you encounter a situation where this is not the case, you can adjust the configuration object and specify your framework. For example, if you wanted to configure the addon for a Vue 3 project: +If you need to run tests on a single story, you can use the `composeStories` function from the appropriate framework to process it and apply any configuration you've defined in your stories (e.g., [decorators](../writing-stories/decorators.md), [args](../writing-stories/args.md)) and combine it with your testing environment to generate a snapshot file. For example, if you're working on a component and you want to test its default state, ensuring the expected DOM structure doesn't change, here's how you could write your test: -These are the frameworks currently supported by Storyshots: `angular`, `html`, `preact`, `react`, `react-native`, `svelte`, `vue`, `vue3`, and `web-components`. +### Execute tests on multiple stories -### Additional customization +You can also use the `composeStories` function to test multiple stories. This is useful when you want to extend your test coverage to generate snapshots for the different states of the components in your project. To do so, you can write your test as follows: -Storyshots is highly customizable and includes options for various advanced use cases. You can read more in the [addonโ€™s documentation](https://github.com/storybookjs/storybook/tree/master/addons/storyshots/storyshots-core#options). + ---- + + + + +When your tests are executed in your testing environment, they will generate a single snapshot file with all the stories in your project (i.e.,`storybook.test.ts|js.snap`). However, if you need, you can extend your test file to generate individual snapshot files for each story in your project with Vitest's [`toMatchFileSnapshot`](https://vitest.dev/guide/snapshot.html#file-snapshots) API or Jest's [`jest-specific-snapshot`](https://github.com/igor-dv/jest-specific-snapshot) package. For example: + + + + + + + + #### Whatโ€™s the difference between snapshot tests and visual tests? diff --git a/docs/writing-tests/storyshots-fail.png b/docs/writing-tests/storyshots-fail.png deleted file mode 100644 index 1cf3677509f5..000000000000 Binary files a/docs/writing-tests/storyshots-fail.png and /dev/null differ diff --git a/docs/writing-tests/storyshots-pass.png b/docs/writing-tests/storyshots-pass.png deleted file mode 100644 index b93d218c8f34..000000000000 Binary files a/docs/writing-tests/storyshots-pass.png and /dev/null differ diff --git a/scripts/package.json b/scripts/package.json index d7b47d1d4a12..c45d99b47092 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -55,7 +55,7 @@ }, "resolutions": { "@testing-library/jest-dom": "^5.11.9", - "esbuild": "^0.18.0", + "esbuild": "^0.20.1", "serialize-javascript": "^3.1.0", "type-fest": "~2.19" }, @@ -122,7 +122,7 @@ "detect-port": "^1.3.0", "ejs": "^3.1.8", "ejs-lint": "^2.0.0", - "esbuild": "^0.18.0", + "esbuild": "^0.20.1", "esbuild-plugin-alias": "^0.2.1", "esbuild-register": "^3.5.0", "eslint": "^8.56.0", diff --git a/scripts/yarn.lock b/scripts/yarn.lock index 1ab286a67aaa..7fa824fc3654 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -1490,156 +1490,163 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm64@npm:0.18.20" +"@esbuild/aix-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/aix-ppc64@npm:0.20.1" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm64@npm:0.20.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm@npm:0.18.20" +"@esbuild/android-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-arm@npm:0.20.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-x64@npm:0.18.20" +"@esbuild/android-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/android-x64@npm:0.20.1" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-arm64@npm:0.18.20" +"@esbuild/darwin-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-arm64@npm:0.20.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-x64@npm:0.18.20" +"@esbuild/darwin-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/darwin-x64@npm:0.20.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-arm64@npm:0.18.20" +"@esbuild/freebsd-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-arm64@npm:0.20.1" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-x64@npm:0.18.20" +"@esbuild/freebsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/freebsd-x64@npm:0.20.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm64@npm:0.18.20" +"@esbuild/linux-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm64@npm:0.20.1" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm@npm:0.18.20" +"@esbuild/linux-arm@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-arm@npm:0.20.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ia32@npm:0.18.20" +"@esbuild/linux-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ia32@npm:0.20.1" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-loong64@npm:0.18.20" +"@esbuild/linux-loong64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-loong64@npm:0.20.1" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-mips64el@npm:0.18.20" +"@esbuild/linux-mips64el@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-mips64el@npm:0.20.1" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ppc64@npm:0.18.20" +"@esbuild/linux-ppc64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-ppc64@npm:0.20.1" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-riscv64@npm:0.18.20" +"@esbuild/linux-riscv64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-riscv64@npm:0.20.1" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-s390x@npm:0.18.20" +"@esbuild/linux-s390x@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-s390x@npm:0.20.1" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-x64@npm:0.18.20" +"@esbuild/linux-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/linux-x64@npm:0.20.1" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/netbsd-x64@npm:0.18.20" +"@esbuild/netbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/netbsd-x64@npm:0.20.1" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/openbsd-x64@npm:0.18.20" +"@esbuild/openbsd-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/openbsd-x64@npm:0.20.1" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/sunos-x64@npm:0.18.20" +"@esbuild/sunos-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/sunos-x64@npm:0.20.1" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-arm64@npm:0.18.20" +"@esbuild/win32-arm64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-arm64@npm:0.20.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-ia32@npm:0.18.20" +"@esbuild/win32-ia32@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-ia32@npm:0.20.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-x64@npm:0.18.20" +"@esbuild/win32-x64@npm:0.20.1": + version: 0.20.1 + resolution: "@esbuild/win32-x64@npm:0.20.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2763,7 +2770,7 @@ __metadata: detect-port: "npm:^1.3.0" ejs: "npm:^3.1.8" ejs-lint: "npm:^2.0.0" - esbuild: "npm:^0.18.0" + esbuild: "npm:^0.20.1" esbuild-plugin-alias: "npm:^0.2.1" esbuild-register: "npm:^3.5.0" eslint: "npm:^8.56.0" @@ -6555,33 +6562,36 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.0": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": "npm:0.18.20" - "@esbuild/android-arm64": "npm:0.18.20" - "@esbuild/android-x64": "npm:0.18.20" - "@esbuild/darwin-arm64": "npm:0.18.20" - "@esbuild/darwin-x64": "npm:0.18.20" - "@esbuild/freebsd-arm64": "npm:0.18.20" - "@esbuild/freebsd-x64": "npm:0.18.20" - "@esbuild/linux-arm": "npm:0.18.20" - "@esbuild/linux-arm64": "npm:0.18.20" - "@esbuild/linux-ia32": "npm:0.18.20" - "@esbuild/linux-loong64": "npm:0.18.20" - "@esbuild/linux-mips64el": "npm:0.18.20" - "@esbuild/linux-ppc64": "npm:0.18.20" - "@esbuild/linux-riscv64": "npm:0.18.20" - "@esbuild/linux-s390x": "npm:0.18.20" - "@esbuild/linux-x64": "npm:0.18.20" - "@esbuild/netbsd-x64": "npm:0.18.20" - "@esbuild/openbsd-x64": "npm:0.18.20" - "@esbuild/sunos-x64": "npm:0.18.20" - "@esbuild/win32-arm64": "npm:0.18.20" - "@esbuild/win32-ia32": "npm:0.18.20" - "@esbuild/win32-x64": "npm:0.18.20" +"esbuild@npm:^0.20.1": + version: 0.20.1 + resolution: "esbuild@npm:0.20.1" + dependencies: + "@esbuild/aix-ppc64": "npm:0.20.1" + "@esbuild/android-arm": "npm:0.20.1" + "@esbuild/android-arm64": "npm:0.20.1" + "@esbuild/android-x64": "npm:0.20.1" + "@esbuild/darwin-arm64": "npm:0.20.1" + "@esbuild/darwin-x64": "npm:0.20.1" + "@esbuild/freebsd-arm64": "npm:0.20.1" + "@esbuild/freebsd-x64": "npm:0.20.1" + "@esbuild/linux-arm": "npm:0.20.1" + "@esbuild/linux-arm64": "npm:0.20.1" + "@esbuild/linux-ia32": "npm:0.20.1" + "@esbuild/linux-loong64": "npm:0.20.1" + "@esbuild/linux-mips64el": "npm:0.20.1" + "@esbuild/linux-ppc64": "npm:0.20.1" + "@esbuild/linux-riscv64": "npm:0.20.1" + "@esbuild/linux-s390x": "npm:0.20.1" + "@esbuild/linux-x64": "npm:0.20.1" + "@esbuild/netbsd-x64": "npm:0.20.1" + "@esbuild/openbsd-x64": "npm:0.20.1" + "@esbuild/sunos-x64": "npm:0.20.1" + "@esbuild/win32-arm64": "npm:0.20.1" + "@esbuild/win32-ia32": "npm:0.20.1" + "@esbuild/win32-x64": "npm:0.20.1" dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true "@esbuild/android-arm": optional: true "@esbuild/android-arm64": @@ -6628,7 +6638,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10c0/473b1d92842f50a303cf948a11ebd5f69581cd254d599dd9d62f9989858e0533f64e83b723b5e1398a5b488c0f5fd088795b4235f65ecaf4f007d4b79f04bc88 + checksum: 10c0/7e0303cb80defd55f3f7b85108081afc9c2f3852dda13bf70975a89210f20cd658fc02540d34247401806cb069c4ec489f7cf0df833e040ee361826484926c3a languageName: node linkType: hard @@ -7548,17 +7558,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.9": - version: 1.15.3 - resolution: "follow-redirects@npm:1.15.3" - peerDependenciesMeta: - debug: - optional: true - checksum: 10c0/915a2cf22e667bdf47b1a43cc6b7dce14d95039e9bbf9a24d0e739abfbdfa00077dd43c86d4a7a19efefcc7a99af144920a175eedc3888d268af5df67c272ee5 - languageName: node - linkType: hard - -"follow-redirects@npm:^1.15.4": +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.4": version: 1.15.5 resolution: "follow-redirects@npm:1.15.5" peerDependenciesMeta: @@ -14545,14 +14545,7 @@ __metadata: languageName: node linkType: hard -"tiny-invariant@npm:^1.3.1": - version: 1.3.1 - resolution: "tiny-invariant@npm:1.3.1" - checksum: 10c0/5b87c1d52847d9452b60d0dcb77011b459044e0361ca8253bfe7b43d6288106e12af926adb709a6fc28900e3864349b91dad9a4ac93c39aa15f360b26c2ff4db - languageName: node - linkType: hard - -"tiny-invariant@npm:^1.3.3": +"tiny-invariant@npm:^1.3.1, tiny-invariant@npm:^1.3.3": version: 1.3.3 resolution: "tiny-invariant@npm:1.3.3" checksum: 10c0/65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a