diff --git a/.circleci/config.yml b/.circleci/config.yml
index cd966b042091..3e5c0b499cc6 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -403,7 +403,7 @@ jobs:
parallelism:
type: integer
executor:
- class: large
+ class: xlarge
name: sb_playwright
parallelism: << parameters.parallelism >>
steps:
@@ -723,7 +723,7 @@ workflows:
requires:
- build-sandboxes
- vitest-integration:
- parallelism: 4
+ parallelism: 5
requires:
- create-sandboxes
- bench:
@@ -789,7 +789,7 @@ workflows:
requires:
- build-sandboxes
- vitest-integration:
- parallelism: 4
+ parallelism: 5
requires:
- create-sandboxes
- test-portable-stories:
@@ -856,7 +856,7 @@ workflows:
requires:
- build-sandboxes
- vitest-integration:
- parallelism: 8
+ parallelism: 11
requires:
- create-sandboxes
- test-portable-stories:
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 61566b49d5bb..45c580300e1c 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -159,8 +159,8 @@ jobs:
run: |
git checkout next
git pull
- git push --force origin latest-release
- git push --force origin main
+ git push origin --force next:latest-release
+ git push origin --force next:main
- name: Sync CHANGELOG.md from `main` to `next`
if: steps.target.outputs.target == 'main'
@@ -174,6 +174,7 @@ jobs:
git commit -m "Update CHANGELOG.md for v${{ steps.version.outputs.current-version }} [skip ci]" || true
git push origin next
+ # TODO: remove this step - @JReinhold
- name: Sync version JSONs from `next-release` to `main`
if: github.ref_name == 'next-release'
working-directory: .
diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md
index e2c5c5f10725..212933922023 100644
--- a/CHANGELOG.prerelease.md
+++ b/CHANGELOG.prerelease.md
@@ -1,3 +1,10 @@
+## 8.3.0-alpha.7
+
+- Addon Vitest: Set screenshotFailures to false by default - [#28908](https://github.com/storybookjs/storybook/pull/28908), thanks @yannbf!
+- Addon Vitest: Fix error message logic in set up file - [#28906](https://github.com/storybookjs/storybook/pull/28906), thanks @yannbf!
+- Core: Add Rsbuild frameworks to known frameworks - [#28694](https://github.com/storybookjs/storybook/pull/28694), thanks @fi3ework!
+- Test: Fix support for TS < 4.7 - [#28887](https://github.com/storybookjs/storybook/pull/28887), thanks @ndelangen!
+
## 8.3.0-alpha.6
- Addon Vitest: Add experimental vitest integration - [#28768](https://github.com/storybookjs/storybook/pull/28768), thanks @kasperpeulen!
@@ -21,7 +28,7 @@
- CSF: Allow overridding globals at the story level - [#26654](https://github.com/storybookjs/storybook/pull/26654), thanks @tmeasday!
- Core: Introduce run over play in portable stories, and revert back play changes of 8.2 - [#28764](https://github.com/storybookjs/storybook/pull/28764), thanks @kasperpeulen!
-- Core: Split Storybook CLI - [#28519](https://github.com/storybookjs/storybook/pull/28519), thanks @kasperpeulen!
+- Core: Split Storybook CLI - [#28519](https://github.com/storybookjs/storybook/pull/28519), thanks @kasperpeulen!
- Fix: Invariant failed: Expected package.json#version to be defined in the "undefined" package - [#28752](https://github.com/storybookjs/storybook/pull/28752), thanks @abcdmku!
- Next.js: Make RSC portable-stories compatible - [#28756](https://github.com/storybookjs/storybook/pull/28756), thanks @valentinpalkovic!
- UI: Fix collapse/expand all functionality - [#28582](https://github.com/storybookjs/storybook/pull/28582), thanks @filipemelo2002!
@@ -71,7 +78,6 @@
## 8.3.0-alpha.0
-
## 8.2.0-beta.3
- Addon Controls: Fix saving on Windows - [#28485](https://github.com/storybookjs/storybook/pull/28485), thanks @ghengeveld!
@@ -213,7 +219,6 @@
## 8.2.0-alpha.0
-
## 8.1.0-beta.1
- API: Add API access to sidebar renderLabel - [#27099](https://github.com/storybookjs/storybook/pull/27099), thanks @shilman!
@@ -259,7 +264,7 @@
- Portable Stories: Warn when rendering stories without cleaning up first - [#27008](https://github.com/storybookjs/storybook/pull/27008), thanks @JReinhold!
- React: Support v19 in `react-dom-shim` - [#26898](https://github.com/storybookjs/storybook/pull/26898), thanks @Tobbe!
- Test: Remove chai as dependency of @storybook/test - [#26852](https://github.com/storybookjs/storybook/pull/26852), thanks @kasperpeulen!
-- Test: Support module mocking with conditional subpath imports in `package.json` - [#26688](https://github.com/storybookjs/storybook/pull/26688), thanks @kasperpeulen!
+- Test: Support module mocking with conditional subpath imports in `package.json` - [#26688](https://github.com/storybookjs/storybook/pull/26688), thanks @kasperpeulen!
- UI: Fix not re-rendering tabs on state change - [#26899](https://github.com/storybookjs/storybook/pull/26899), thanks @lifeiscontent!
- UI: Fix sidebar search hanging when selecting a story in touch mode - [#26807](https://github.com/storybookjs/storybook/pull/26807), thanks @JReinhold!
- Vite: Merge assetsInclude property with Storybook default values - [#26860](https://github.com/storybookjs/storybook/pull/26860), thanks @yuemori!
@@ -333,11 +338,10 @@
## 8.1.0-alpha.1
-- Maintenance: Fix performance regressions - [#26411](https://github.com/storybookjs/storybook/pull/26411), thanks @kasperpeulen!
+- Maintenance: Fix performance regressions - [#26411](https://github.com/storybookjs/storybook/pull/26411), thanks @kasperpeulen!
## 8.1.0-alpha.0
-
## 8.0.0-rc.5
- CLI: Automigration fix version detection of upgrading related packages - [#26410](https://github.com/storybookjs/storybook/pull/26410), thanks @ndelangen!
@@ -348,7 +352,7 @@
- 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: 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!
diff --git a/code/.storybook/preview.tsx b/code/.storybook/preview.tsx
index 3fbae06f064f..638217cad31d 100644
--- a/code/.storybook/preview.tsx
+++ b/code/.storybook/preview.tsx
@@ -16,7 +16,7 @@ import {
import { DocsContext } from '@storybook/blocks';
import { global } from '@storybook/global';
-import type { Decorator, ReactRenderer } from '@storybook/react';
+import type { Decorator, Loader, ReactRenderer } from '@storybook/react';
import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport';
@@ -95,7 +95,6 @@ const StackContainer = ({ children, layout }) => (
height: '100%',
display: 'flex',
flexDirection: 'column',
- // margin: layout === 'fullscreen' ? 0 : '-1rem',
}}
>
@@ -124,15 +123,21 @@ const preview = (window as any).__STORYBOOK_PREVIEW__ as PreviewWeb {
- if (!relativeCsfPaths) return {};
+ if (!relativeCsfPaths) {
+ return {};
+ }
const csfFiles = await Promise.all(
(relativeCsfPaths as string[]).map(async (blocksRelativePath) => {
const projectRelativePath = `./lib/blocks/src/${blocksRelativePath.replace(
@@ -185,7 +190,8 @@ export const decorators = [
),
/**
- * This decorator renders the stories side-by-side, stacked or default based on the theme switcher in the toolbar
+ * This decorator renders the stories side-by-side, stacked or default based on the theme switcher
+ * in the toolbar
*/
(StoryFn, { globals, playFunction, args, storyGlobals, parameters }) => {
let theme = globals.sb_theme;
@@ -267,9 +273,9 @@ export const decorators = [
}
},
/**
- * This decorator shows the current state of the arg named in the
- * parameters.withRawArg property, by updating the arg in the onChange function
- * this also means that the arg will sync with the control panel
+ * This decorator shows the current state of the arg named in the parameters.withRawArg property,
+ * by updating the arg in the onChange function this also means that the arg will sync with the
+ * control panel
*
* If parameters.withRawArg is not set, this decorator will do nothing
*/
diff --git a/code/.storybook/vitest.config.ts b/code/.storybook/vitest.config.ts
index a9e26b6ddbae..4e7c8fdd87d2 100644
--- a/code/.storybook/vitest.config.ts
+++ b/code/.storybook/vitest.config.ts
@@ -33,7 +33,7 @@ export default mergeConfig(
include: [
// TODO: test all core and addon stories later
// './core/**/components/**/*.{story,stories}.?(c|m)[jt]s?(x)',
- '../addons/interactions/src/**/*.{story,stories}.?(c|m)[jt]s?(x)',
+ '../addons/**/src/**/*.{story,stories}.?(c|m)[jt]s?(x)',
],
exclude: [
...defaultExclude,
diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json
index 44044e8a3f31..f063e0ddfe0f 100644
--- a/code/addons/a11y/package.json
+++ b/code/addons/a11y/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-a11y",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Test component compliance with web accessibility standards",
"keywords": [
"a11y",
diff --git a/code/addons/a11y/src/a11yRunner.ts b/code/addons/a11y/src/a11yRunner.ts
index e1cae2ec96b2..5e45a20ac7b0 100644
--- a/code/addons/a11y/src/a11yRunner.ts
+++ b/code/addons/a11y/src/a11yRunner.ts
@@ -15,10 +15,7 @@ let activeStoryId: string | undefined;
const defaultParameters = { config: {}, options: {} };
-/**
- * Handle A11yContext events.
- * Because the event are sent without manual check, we split calls
- */
+/** Handle A11yContext events. Because the event are sent without manual check, we split calls */
const handleRequest = async (storyId: string, input: A11yParameters | null) => {
if (!input?.manual) {
await run(storyId, input ?? defaultParameters);
diff --git a/code/addons/a11y/src/components/A11yContext.tsx b/code/addons/a11y/src/components/A11yContext.tsx
index 35bc476328b1..5dd11bd456f2 100644
--- a/code/addons/a11y/src/components/A11yContext.tsx
+++ b/code/addons/a11y/src/components/A11yContext.tsx
@@ -105,7 +105,9 @@ export const A11yContextProvider: React.FC
typeof initialArgs[name] === 'undefined' && !(name in initialArgs);
/**
- * Automatically add action args for argTypes whose name
- * matches a regex, such as `^on.*` for react-style `onClick` etc.
+ * Automatically add action args for argTypes whose name matches a regex, such as `^on.*` for
+ * react-style `onClick` etc.
*/
export const inferActionsFromArgTypesRegex: ArgsEnhancer = (context) => {
@@ -39,9 +39,7 @@ export const inferActionsFromArgTypesRegex: ArgsEnhancer = (context) =
}, {} as Args);
};
-/**
- * Add action args for list of strings.
- */
+/** Add action args for list of strings. */
export const addActionsFromArgTypes: ArgsEnhancer = (context) => {
const {
initialArgs,
diff --git a/code/addons/actions/src/components/ActionLogger/index.tsx b/code/addons/actions/src/components/ActionLogger/index.tsx
index 25ab0da611ac..59e4a559fb9c 100644
--- a/code/addons/actions/src/components/ActionLogger/index.tsx
+++ b/code/addons/actions/src/components/ActionLogger/index.tsx
@@ -48,7 +48,11 @@ export const ActionLogger = ({ actions, onClear }: ActionLoggerProps) => {
useEffect(() => {
// Scroll to bottom, when the action panel was already scrolled down
- if (wasAtBottom) wrapperRef.current.scrollTop = wrapperRef.current.scrollHeight;
+
+ // Scroll to bottom, when the action panel was already scrolled down
+ if (wasAtBottom) {
+ wrapperRef.current.scrollTop = wrapperRef.current.scrollHeight;
+ }
}, [wasAtBottom, actions.length]);
return (
diff --git a/code/addons/actions/src/loaders.ts b/code/addons/actions/src/loaders.ts
index 585d8e3815b7..118d5c0b1b7e 100644
--- a/code/addons/actions/src/loaders.ts
+++ b/code/addons/actions/src/loaders.ts
@@ -12,7 +12,10 @@ const logActionsWhenMockCalled: LoaderFunction = (context) => {
const {
parameters: { actions },
} = context;
- if (actions?.disable) return;
+
+ if (actions?.disable) {
+ return;
+ }
if (
!subscribed &&
@@ -22,7 +25,10 @@ const logActionsWhenMockCalled: LoaderFunction = (context) => {
const onMockCall = global.__STORYBOOK_TEST_ON_MOCK_CALL__ as typeof onMockCallType;
onMockCall((mock, args) => {
const name = mock.getMockName();
- if (name === 'spy') return;
+
+ if (name === 'spy') {
+ return;
+ }
// TODO: Make this a configurable API in 8.2
if (
diff --git a/code/addons/actions/src/runtime/action.ts b/code/addons/actions/src/runtime/action.ts
index 00295c007e8d..6fea0cb90a74 100644
--- a/code/addons/actions/src/runtime/action.ts
+++ b/code/addons/actions/src/runtime/action.ts
@@ -14,7 +14,10 @@ import { config } from './configureActions';
type SyntheticEvent = any; // import('react').SyntheticEvent;
const findProto = (obj: unknown, callback: (proto: any) => boolean): Function | null => {
const proto = Object.getPrototypeOf(obj);
- if (!proto || callback(proto)) return proto;
+
+ if (!proto || callback(proto)) {
+ return proto;
+ }
return findProto(proto, callback);
};
const isReactSyntheticEvent = (e: unknown): e is SyntheticEvent =>
diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json
index 0314cf79a70f..43285cee9823 100644
--- a/code/addons/backgrounds/package.json
+++ b/code/addons/backgrounds/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-backgrounds",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"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 37f7d074a975..f6ddb0a4ff85 100644
--- a/code/addons/controls/package.json
+++ b/code/addons/controls/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-controls",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Interact with component inputs dynamically in the Storybook UI",
"keywords": [
"addon",
diff --git a/code/addons/controls/src/ControlsPanel.tsx b/code/addons/controls/src/ControlsPanel.tsx
index a84591aefb41..fa30d4a1c7db 100644
--- a/code/addons/controls/src/ControlsPanel.tsx
+++ b/code/addons/controls/src/ControlsPanel.tsx
@@ -61,16 +61,21 @@ export const ControlsPanel = ({ saveStory, createStory }: ControlsPanelProps) =>
// If the story is prepared, then show the args table
// and reset the loading states
useEffect(() => {
- if (previewInitialized) setIsLoading(false);
+ if (previewInitialized) {
+ setIsLoading(false);
+ }
}, [previewInitialized]);
const hasControls = Object.values(rows).some((arg) => arg?.control);
const withPresetColors = Object.entries(rows).reduce((acc, [key, arg]) => {
const control = arg?.control;
- if (typeof control !== 'object' || control?.type !== 'color' || control?.presetColors)
+
+ if (typeof control !== 'object' || control?.type !== 'color' || control?.presetColors) {
acc[key] = arg;
- else acc[key] = { ...arg, control: { ...control, presetColors } };
+ } else {
+ acc[key] = { ...arg, control: { ...control, presetColors } };
+ }
return acc;
}, {} as ArgTypes);
diff --git a/code/addons/controls/src/SaveStory.tsx b/code/addons/controls/src/SaveStory.tsx
index 56e50a0f0326..69f646b678e5 100644
--- a/code/addons/controls/src/SaveStory.tsx
+++ b/code/addons/controls/src/SaveStory.tsx
@@ -105,7 +105,9 @@ export const SaveStory = ({ saveStory, createStory, resetArgs }: SaveStoryProps)
const [errorMessage, setErrorMessage] = React.useState(null);
const onSaveStory = async () => {
- if (saving) return;
+ if (saving) {
+ return;
+ }
setSaving(true);
await saveStory().catch(() => {});
setSaving(false);
@@ -125,7 +127,10 @@ export const SaveStory = ({ saveStory, createStory, resetArgs }: SaveStoryProps)
};
const onSubmitForm = async (event: React.FormEvent) => {
event.preventDefault();
- if (saving) return;
+
+ if (saving) {
+ return;
+ }
try {
setErrorMessage(null);
setSaving(true);
diff --git a/code/addons/controls/src/manager.tsx b/code/addons/controls/src/manager.tsx
index b745bad9eb16..5863159f79db 100644
--- a/code/addons/controls/src/manager.tsx
+++ b/code/addons/controls/src/manager.tsx
@@ -41,7 +41,9 @@ function Title() {
const stringifyArgs = (args: Record) =>
JSON.stringify(args, (_, value) => {
- if (typeof value === 'function') return '__sb_empty_function_arg__';
+ if (typeof value === 'function') {
+ return '__sb_empty_function_arg__';
+ }
return value;
});
@@ -50,7 +52,10 @@ addons.register(ADDON_ID, (api) => {
const saveStory = async () => {
const data = api.getCurrentStoryData();
- if (data.type !== 'story') throw new Error('Not a story');
+
+ if (data.type !== 'story') {
+ throw new Error('Not a story');
+ }
try {
const response = await experimental_requestResponse<
@@ -60,7 +65,9 @@ addons.register(ADDON_ID, (api) => {
// Only send updated args
args: stringifyArgs(
Object.entries(data.args || {}).reduce((acc, [key, value]) => {
- if (!deepEqual(value, data.initialArgs?.[key])) acc[key] = value;
+ if (!deepEqual(value, data.initialArgs?.[key])) {
+ acc[key] = value;
+ }
return acc;
}, {})
),
@@ -98,7 +105,10 @@ addons.register(ADDON_ID, (api) => {
const createStory = async (name: string) => {
const data = api.getCurrentStoryData();
- if (data.type !== 'story') throw new Error('Not a story');
+
+ if (data.type !== 'story') {
+ throw new Error('Not a story');
+ }
const response = await experimental_requestResponse<
SaveStoryRequestPayload,
@@ -146,9 +156,14 @@ addons.register(ADDON_ID, (api) => {
});
channel.on(SAVE_STORY_RESPONSE, (data: ResponseData) => {
- if (!data.success) return;
+ if (!data.success) {
+ return;
+ }
const story = api.getCurrentStoryData();
- if (story.type !== 'story') return;
+
+ if (story.type !== 'story') {
+ return;
+ }
api.resetStoryArgs(story);
if (data.payload.newStoryId) {
diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json
index b06374bbcaf7..23e63535db89 100644
--- a/code/addons/docs/package.json
+++ b/code/addons/docs/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-docs",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Document component usage and properties in Markdown",
"keywords": [
"addon",
@@ -98,7 +98,6 @@
"prep": "jiti ../../../scripts/prepare/bundle.ts"
},
"dependencies": {
- "@babel/core": "^7.24.4",
"@mdx-js/react": "^3.0.0",
"@storybook/blocks": "workspace:*",
"@storybook/csf-plugin": "workspace:*",
diff --git a/code/addons/docs/src/plugins/mdx-plugin.ts b/code/addons/docs/src/plugins/mdx-plugin.ts
index 2e2112a91a88..40d8e88c3f3a 100644
--- a/code/addons/docs/src/plugins/mdx-plugin.ts
+++ b/code/addons/docs/src/plugins/mdx-plugin.ts
@@ -28,7 +28,9 @@ export async function mdxPlugin(options: Options): Promise {
name: 'storybook:mdx-plugin',
enforce: 'pre',
async transform(src, id) {
- if (!filter(id)) return undefined;
+ if (!filter(id)) {
+ return undefined;
+ }
const mdxLoaderOptions: CompileOptions = await presets.apply('mdxLoaderOptions', {
...mdxPluginOptions,
diff --git a/code/addons/docs/src/preset.ts b/code/addons/docs/src/preset.ts
index 90933f7d8a9c..e418b5e2e8aa 100644
--- a/code/addons/docs/src/preset.ts
+++ b/code/addons/docs/src/preset.ts
@@ -11,9 +11,8 @@ import rehypeSlug from 'rehype-slug';
import type { CompileOptions } from './compiler';
/**
- * Get the resolvedReact preset, which points either to
- * the user's react dependencies or the react dependencies shipped with addon-docs
- * if the user has not installed react explicitly.
+ * Get the resolvedReact preset, which points either to the user's react dependencies or the react
+ * dependencies shipped with addon-docs if the user has not installed react explicitly.
*/
const getResolvedReact = async (options: Options) => {
const resolvedReact = (await options.presets.apply('resolvedReact', {})) as any;
@@ -66,10 +65,13 @@ async function webpack(
let alias;
- /** Add aliases for `@storybook/addon-docs` & `@storybook/blocks`
- * These must be singletons to avoid multiple instances of react & emotion being loaded, both would cause the components to fail to render.
+ /**
+ * Add aliases for `@storybook/addon-docs` & `@storybook/blocks` These must be singletons to avoid
+ * multiple instances of react & emotion being loaded, both would cause the components to fail to
+ * render.
*
- * In the future the `@storybook/theming` and `@storybook/components` can be removed, as they should be singletons in the future due to the peerDependency on `storybook` package.
+ * In the future the `@storybook/theming` and `@storybook/components` can be removed, as they
+ * should be singletons in the future due to the peerDependency on `storybook` package.
*/
const cliPath = dirname(require.resolve('storybook/package.json'));
const themingPath = join(cliPath, 'core', 'theming', 'index.js');
@@ -193,10 +195,14 @@ export const viteFinal = async (config: any, options: Options) => {
...(isAbsolute(reactDom) && { 'react-dom/server': `${reactDom}/server.browser.js` }),
'react-dom': reactDom,
'@mdx-js/react': mdx,
- /** Add aliases for `@storybook/addon-docs` & `@storybook/blocks`
- * These must be singletons to avoid multiple instances of react & emotion being loaded, both would cause the components to fail to render.
+ /**
+ * Add aliases for `@storybook/addon-docs` & `@storybook/blocks` These must be singletons
+ * to avoid multiple instances of react & emotion being loaded, both would cause the
+ * components to fail to render.
*
- * In the future the `@storybook/theming` and `@storybook/components` can be removed, as they should be singletons in the future due to the peerDependency on `storybook` package.
+ * In the future the `@storybook/theming` and `@storybook/components` can be removed, as
+ * they should be singletons in the future due to the peerDependency on `storybook`
+ * package.
*/
'@storybook/theming/create': themingCreatePath,
'@storybook/theming': themingPath,
@@ -224,11 +230,10 @@ const webpackX = webpack as any;
const docsX = docs as any;
/**
- * If the user has not installed react explicitly in their project,
- * the resolvedReact preset will not be set.
- * We then set it here in addon-docs to use addon-docs's react version that always exists.
- * This is just a fallback that never overrides the existing preset,
- * but ensures that there is always a resolved react.
+ * If the user has not installed react explicitly in their project, the resolvedReact preset will
+ * not be set. We then set it here in addon-docs to use addon-docs's react version that always
+ * exists. This is just a fallback that never overrides the existing preset, but ensures that there
+ * is always a resolved react.
*/
export const resolvedReact = async (existing: any) => ({
react: existing?.react ?? dirname(require.resolve('react/package.json')),
diff --git a/code/addons/docs/template/stories/docs2/UtfSymbolScroll.mdx b/code/addons/docs/template/stories/docs2/UtfSymbolScroll.mdx
new file mode 100644
index 000000000000..11c902ce3baa
--- /dev/null
+++ b/code/addons/docs/template/stories/docs2/UtfSymbolScroll.mdx
@@ -0,0 +1,14 @@
+import { Meta } from '@storybook/addon-docs';
+
+
+
+## Instruction
+
+> Instruction below works only in iframe.html. Unknown code in normal mode (with manager) removes hash from url.
+
+Click on [link](#anchor-with-utf-symbols-абвг). That will jump scroll to anchor after green block below. Then reload page and
+it should smooth-scroll to that anchor.
+
+
Space for scroll test
+
+## Anchor with utf symbols (абвг)
\ No newline at end of file
diff --git a/code/addons/docs/template/stories/docs2/resolved-react.stories.ts b/code/addons/docs/template/stories/docs2/resolved-react.stories.ts
index 331b7e1dfd89..00fed804cebb 100644
--- a/code/addons/docs/template/stories/docs2/resolved-react.stories.ts
+++ b/code/addons/docs/template/stories/docs2/resolved-react.stories.ts
@@ -5,15 +5,18 @@ import * as ReactDomServer from 'react-dom/server';
import { expect, within } from '@storybook/test';
/**
- * This component is used to display the resolved version of React and its related packages.
- * As long as `@storybook/addon-docs` is installed, `react` and `react-dom` should be available to import from and should resolve to the same version.
+ * This component is used to display the resolved version of React and its related packages. As long
+ * as `@storybook/addon-docs` is installed, `react` and `react-dom` should be available to import
+ * from and should resolve to the same version.
*
* The autodocs here ensures that it also works in the generated documentation.
*
* - See the [MDX docs](/docs/addons-docs-docs2-resolvedreact--mdx) for how it resolves in MDX.
- * - See the [Story](/story/addons-docs-docs2-resolvedreact--story) for how it resolves in the actual story.
+ * - See the [Story](/story/addons-docs-docs2-resolvedreact--story) for how it resolves in the actual
+ * story.
*
- * **Note: There appears to be a bug in the _production_ build of `react-dom`, where it reports version `18.2.0-next-9e3b772b8-20220608` while in fact version `18.2.0` is installed.**
+ * **Note: There appears to be a bug in the _production_ build of `react-dom`, where it reports
+ * version `18.2.0-next-9e3b772b8-20220608` while in fact version `18.2.0` is installed.**
*/
export default {
title: 'Docs2/ResolvedReact',
diff --git a/code/addons/docs/template/stories/docspage/basic.stories.ts b/code/addons/docs/template/stories/docspage/basic.stories.ts
index 9982b444a487..3dc35191d7b7 100644
--- a/code/addons/docs/template/stories/docspage/basic.stories.ts
+++ b/code/addons/docs/template/stories/docspage/basic.stories.ts
@@ -8,24 +8,18 @@ export default {
parameters: { chromatic: { disable: true } },
};
-/**
- * A basic button
- */
+/** A basic button */
export const Basic = {
args: { label: 'Basic' },
};
-/**
- * Won't show up in DocsPage
- */
+/** Won't show up in DocsPage */
export const Disabled = {
args: { label: 'Disabled in DocsPage' },
parameters: { docs: { disable: true } },
};
-/**
- * Another button, just to show multiple stories
- */
+/** Another button, just to show multiple stories */
export const Another = {
args: { label: 'Another' },
parameters: {
diff --git a/code/addons/docs/template/stories/docspage/error.stories.ts b/code/addons/docs/template/stories/docspage/error.stories.ts
index ad24bc585f68..eae587a16bde 100644
--- a/code/addons/docs/template/stories/docspage/error.stories.ts
+++ b/code/addons/docs/template/stories/docspage/error.stories.ts
@@ -7,9 +7,7 @@ export default {
parameters: { chromatic: { disable: true } },
};
-/**
- * A story that throws
- */
+/** A story that throws */
export const ErrorStory = {
decorators: [
() => {
diff --git a/code/addons/docs/web-components/README.md b/code/addons/docs/web-components/README.md
index c5417be88e43..7edf06fe9989 100644
--- a/code/addons/docs/web-components/README.md
+++ b/code/addons/docs/web-components/README.md
@@ -14,7 +14,7 @@
```js
import { setCustomElementsManifest } from '@storybook/web-components';
import customElements from '../custom-elements.json';
-
+
setCustomElementsManifest(customElements);
```
diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json
index 026d8ab9fe18..5ff4778a58b8 100644
--- a/code/addons/essentials/package.json
+++ b/code/addons/essentials/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-essentials",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Curated addons to bring out the best of Storybook",
"keywords": [
"addon",
diff --git a/code/addons/essentials/src/index.ts b/code/addons/essentials/src/index.ts
index ce80fc37634e..5809420bc1b8 100644
--- a/code/addons/essentials/src/index.ts
+++ b/code/addons/essentials/src/index.ts
@@ -6,52 +6,60 @@ import { logger } from 'storybook/internal/node-logger';
interface PresetOptions {
/**
* Allow to use @storybook/addon-actions
- * @see https://storybook.js.org/addons/@storybook/addon-actions
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-actions
*/
actions?: boolean;
/**
* Allow to use @storybook/addon-backgrounds
- * @see https://storybook.js.org/addons/@storybook/addon-backgrounds
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-backgrounds
*/
backgrounds?: boolean;
configDir: string;
/**
* Allow to use @storybook/addon-controls
- * @see https://storybook.js.org/addons/@storybook/addon-controls
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-controls
*/
controls?: boolean;
/**
* Allow to use @storybook/addon-docs
- * @see https://storybook.js.org/addons/@storybook/addon-docs
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-docs
*/
docs?: boolean;
/**
* Allow to use @storybook/addon-measure
- * @see https://storybook.js.org/addons/@storybook/addon-measure
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-measure
*/
measure?: boolean;
/**
* Allow to use @storybook/addon-outline
- * @see https://storybook.js.org/addons/@storybook/addon-outline
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-outline
*/
outline?: boolean;
themes?: boolean;
/**
* Allow to use @storybook/addon-toolbars
- * @see https://storybook.js.org/addons/@storybook/addon-toolbars
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-toolbars
*/
toolbars?: boolean;
/**
* Allow to use @storybook/addon-viewport
- * @see https://storybook.js.org/addons/@storybook/addon-viewport
+ *
* @default true
+ * @see https://storybook.js.org/addons/@storybook/addon-viewport
*/
viewport?: boolean;
}
diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json
index 97d12556c4f6..9ccb8d6d0ca6 100644
--- a/code/addons/gfm/package.json
+++ b/code/addons/gfm/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-mdx-gfm",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "GitHub Flavored Markdown in Storybook",
"keywords": [
"addon",
diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json
index 7fb4460df5e9..fe1d559c6744 100644
--- a/code/addons/highlight/package.json
+++ b/code/addons/highlight/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-highlight",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Highlight DOM nodes within your stories",
"keywords": [
"storybook-addons",
diff --git a/code/addons/highlight/src/preview.ts b/code/addons/highlight/src/preview.ts
index 7d7d43bd14d4..6b2f6b1e8cad 100644
--- a/code/addons/highlight/src/preview.ts
+++ b/code/addons/highlight/src/preview.ts
@@ -17,7 +17,7 @@ const highlightStyle = (color = '#FF4785', style: OutlineStyle = 'dashed') => `
`;
interface HighlightInfo {
- /** html selector of the element */
+ /** HTML selector of the element */
elements: string[];
color: string;
style: OutlineStyle;
diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json
index c2383755e2e4..ca0bc1832ea2 100644
--- a/code/addons/interactions/package.json
+++ b/code/addons/interactions/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-interactions",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Automate, test and debug user interactions",
"keywords": [
"storybook-addons",
diff --git a/code/addons/interactions/src/Panel.tsx b/code/addons/interactions/src/Panel.tsx
index eec7d8a80e96..b26860b6c71f 100644
--- a/code/addons/interactions/src/Panel.tsx
+++ b/code/addons/interactions/src/Panel.tsx
@@ -123,7 +123,10 @@ export const Panel = memo<{ storyId: string }>(function PanelMemoized({ storyId
([end]: any) => setScrollTarget(end.isIntersecting ? undefined : end.target),
{ root: global.document.querySelector('#panel-tab-content') }
);
- if (endRef.current) observer.observe(endRef.current);
+
+ if (endRef.current) {
+ observer.observe(endRef.current);
+ }
}
return () => observer?.disconnect();
}, []);
diff --git a/code/addons/interactions/src/components/EmptyState.tsx b/code/addons/interactions/src/components/EmptyState.tsx
index 5c0ee95a1bc7..0768a9864946 100644
--- a/code/addons/interactions/src/components/EmptyState.tsx
+++ b/code/addons/interactions/src/components/EmptyState.tsx
@@ -40,7 +40,9 @@ export const Empty = () => {
return () => clearTimeout(load);
}, []);
- if (isLoading) return null;
+ if (isLoading) {
+ return null;
+ }
return (
diff --git a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx
index c2fb2b9af2ac..b9273b5a04f7 100644
--- a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx
+++ b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx
@@ -60,7 +60,9 @@ export const Passing: Story = {
interactions: getInteractions(CallStates.DONE),
},
play: async ({ args, canvasElement }) => {
- if (isChromatic()) return;
+ if (isChromatic()) {
+ return;
+ }
const canvas = within(canvasElement);
await waitFor(async () => {
diff --git a/code/addons/interactions/src/components/MatcherResult.tsx b/code/addons/interactions/src/components/MatcherResult.tsx
index a56f96abf627..beae8b2146ff 100644
--- a/code/addons/interactions/src/components/MatcherResult.tsx
+++ b/code/addons/interactions/src/components/MatcherResult.tsx
@@ -6,9 +6,15 @@ import { Node } from './MethodCall';
const getParams = (line: string, fromIndex = 0): string => {
for (let i = fromIndex, depth = 1; i < line.length; i += 1) {
- if (line[i] === '(') depth += 1;
- else if (line[i] === ')') depth -= 1;
- if (depth === 0) return line.slice(fromIndex, i);
+ if (line[i] === '(') {
+ depth += 1;
+ } else if (line[i] === ')') {
+ depth -= 1;
+ }
+
+ if (depth === 0) {
+ return line.slice(fromIndex, i);
+ }
}
return '';
};
diff --git a/code/addons/interactions/src/components/MethodCall.tsx b/code/addons/interactions/src/components/MethodCall.tsx
index 8e19ea9e6549..fbe5ee038afb 100644
--- a/code/addons/interactions/src/components/MethodCall.tsx
+++ b/code/addons/interactions/src/components/MethodCall.tsx
@@ -69,7 +69,9 @@ const useThemeColors = () => {
const special = /[^A-Z0-9]/i;
const trimEnd = /[\s.,…]+$/gm;
const ellipsize = (string: string, maxlength: number): string => {
- if (string.length <= maxlength) return string;
+ if (string.length <= maxlength) {
+ return string;
+ }
for (let i = maxlength - 1; i >= 0; i -= 1) {
if (special.test(string[i]) && i > 10) {
return `${string.slice(0, i).replace(trimEnd, '')}…`;
@@ -102,10 +104,7 @@ export const Node = ({
}: {
value: any;
nested?: boolean;
- /**
- * Shows an object inspector instead of just printing the object.
- * Only available for Objects
- */
+ /** Shows an object inspector instead of just printing the object. Only available for Objects */
showObjectInspector?: boolean;
callsById?: Map;
[props: string]: any;
@@ -422,7 +421,9 @@ export const MethodCall = ({
callsById: Map;
}) => {
// Call might be undefined during initial render, can be safely ignored.
- if (!call) return null;
+ if (!call) {
+ return null;
+ }
if (call.method === 'step' && call.path.length === 0) {
return ;
diff --git a/code/addons/interactions/src/theme.ts b/code/addons/interactions/src/theme.ts
index 2c4eb0da3430..8e6a63c5ed6d 100644
--- a/code/addons/interactions/src/theme.ts
+++ b/code/addons/interactions/src/theme.ts
@@ -1,7 +1,4 @@
-/**
- * Interaction Testing Theme
- * PLACEHOLDER until SB is updated <3
- */
+/** Interaction Testing Theme PLACEHOLDER until SB is updated <3 */
interface Colors {
pure?: {
gray?: any;
diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json
index d59fe5e011d2..59184f8ad3a7 100644
--- a/code/addons/jest/package.json
+++ b/code/addons/jest/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-jest",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "React storybook addon that show component jest report",
"keywords": [
"addon",
diff --git a/code/addons/jest/src/components/Message.tsx b/code/addons/jest/src/components/Message.tsx
index 2fdfcd41e46a..b373c01f91c5 100644
--- a/code/addons/jest/src/components/Message.tsx
+++ b/code/addons/jest/src/components/Message.tsx
@@ -73,7 +73,9 @@ const colorizeText: (msg: string, type: string) => MsgElement[] = (msg: string,
const getConvertedText: (msg: string) => MsgElement[] = (msg: string) => {
let elementArray: MsgElement[] = [];
- if (!msg) return elementArray;
+ if (!msg) {
+ return elementArray;
+ }
const splitText = msg.split(/\[2m/).join('').split(/\[22m/);
diff --git a/code/addons/links/package.json b/code/addons/links/package.json
index 58401f764f9c..3c1b8c073866 100644
--- a/code/addons/links/package.json
+++ b/code/addons/links/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-links",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"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 aeb019bee43e..7dcf4a976332 100644
--- a/code/addons/measure/package.json
+++ b/code/addons/measure/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-measure",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Inspect layouts by visualizing the box model",
"keywords": [
"storybook-addons",
diff --git a/code/addons/measure/src/box-model/labels.ts b/code/addons/measure/src/box-model/labels.ts
index acdee3f2e69d..7926c826e3bd 100644
--- a/code/addons/measure/src/box-model/labels.ts
+++ b/code/addons/measure/src/box-model/labels.ts
@@ -40,8 +40,13 @@ function roundedRect(context: CanvasRenderingContext2D, { x, y, w, h, r }: Round
x = x - w / 2;
y = y - h / 2;
- if (w < 2 * r) r = w / 2;
- if (h < 2 * r) r = h / 2;
+ if (w < 2 * r) {
+ r = w / 2;
+ }
+
+ if (h < 2 * r) {
+ r = h / 2;
+ }
context.beginPath();
context.moveTo(x + r, y);
@@ -81,10 +86,8 @@ function positionCoordinate(
}
/**
- * Offset the label based on how many layers appear before it
- * For example:
- * margin labels will shift further outwards if there are
- * padding labels
+ * Offset the label based on how many layers appear before it For example: margin labels will shift
+ * further outwards if there are padding labels
*/
function offset(
type: LabelType,
diff --git a/code/addons/measure/src/box-model/visualizer.ts b/code/addons/measure/src/box-model/visualizer.ts
index 00b1425f7f13..349516e05f4b 100644
--- a/code/addons/measure/src/box-model/visualizer.ts
+++ b/code/addons/measure/src/box-model/visualizer.ts
@@ -1,6 +1,4 @@
-/**
- * Based on https://gist.github.com/awestbro/e668c12662ad354f02a413205b65fce7
- */
+/** Based on https://gist.github.com/awestbro/e668c12662ad354f02a413205b65fce7 */
import { global } from '@storybook/global';
import { draw } from './canvas';
diff --git a/code/addons/onboarding/package.json b/code/addons/onboarding/package.json
index 1d21a5b069d0..53e7aa063976 100644
--- a/code/addons/onboarding/package.json
+++ b/code/addons/onboarding/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-onboarding",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Storybook Addon Onboarding - Introduces a new onboarding experience",
"keywords": [
"storybook-addons",
diff --git a/code/addons/onboarding/src/Onboarding.tsx b/code/addons/onboarding/src/Onboarding.tsx
index 2fe360db7e93..b861d918204a 100644
--- a/code/addons/onboarding/src/Onboarding.tsx
+++ b/code/addons/onboarding/src/Onboarding.tsx
@@ -85,7 +85,10 @@ export default function Onboarding({ api }: { api: API }) {
(storyId: string) => {
try {
const { id, refId } = api.getCurrentStoryData() || {};
- if (id !== storyId || refId !== undefined) api.selectStory(storyId);
+
+ if (id !== storyId || refId !== undefined) {
+ api.selectStory(storyId);
+ }
} catch (e) {}
},
[api]
@@ -132,17 +135,30 @@ export default function Onboarding({ api }: { api: API }) {
useEffect(() => {
setStep((current) => {
- if (['1:Intro', '5:StoryCreated', '6:FinishedOnboarding'].includes(current)) return current;
- if (createNewStoryForm) return '4:CreateStory';
- if (saveFromControls) return '3:SaveFromControls';
- if (primaryControl) return '2:Controls';
+ if (['1:Intro', '5:StoryCreated', '6:FinishedOnboarding'].includes(current)) {
+ return current;
+ }
+
+ if (createNewStoryForm) {
+ return '4:CreateStory';
+ }
+
+ if (saveFromControls) {
+ return '3:SaveFromControls';
+ }
+
+ if (primaryControl) {
+ return '2:Controls';
+ }
return '1:Intro';
});
}, [createNewStoryForm, primaryControl, saveFromControls]);
useEffect(() => {
return api.on(SAVE_STORY_RESPONSE, ({ payload, success }) => {
- if (!success || !payload?.newStoryName) return;
+ if (!success || !payload?.newStoryName) {
+ return;
+ }
setCreatedStory(payload);
setShowConfetti(true);
setStep('5:StoryCreated');
diff --git a/code/addons/onboarding/src/components/Button/Button.tsx b/code/addons/onboarding/src/components/Button/Button.tsx
index e8cc30d4cbd6..305abb58466c 100644
--- a/code/addons/onboarding/src/components/Button/Button.tsx
+++ b/code/addons/onboarding/src/components/Button/Button.tsx
@@ -20,22 +20,49 @@ const StyledButton = styled.button<{ variant: ButtonProps['variant'] }>`
justify-content: center;
padding: 0 0.75rem;
background: ${({ theme, variant }) => {
- if (variant === 'primary') return theme.color.secondary;
- if (variant === 'secondary') return theme.color.lighter;
- if (variant === 'outline') return 'transparent';
- if (variant === 'white') return theme.color.lightest;
+ if (variant === 'primary') {
+ return theme.color.secondary;
+ }
+
+ if (variant === 'secondary') {
+ return theme.color.lighter;
+ }
+
+ if (variant === 'outline') {
+ return 'transparent';
+ }
+
+ if (variant === 'white') {
+ return theme.color.lightest;
+ }
return theme.color.secondary;
}};
color: ${({ theme, variant }) => {
- if (variant === 'primary') return theme.color.lightest;
- if (variant === 'secondary') return theme.darkest;
- if (variant === 'outline') return theme.darkest;
- if (variant === 'white') return theme.color.secondary;
+ if (variant === 'primary') {
+ return theme.color.lightest;
+ }
+
+ if (variant === 'secondary') {
+ return theme.darkest;
+ }
+
+ if (variant === 'outline') {
+ return theme.darkest;
+ }
+
+ if (variant === 'white') {
+ return theme.color.secondary;
+ }
return theme.color.lightest;
}};
box-shadow: ${({ variant }) => {
- if (variant === 'secondary') return '#D9E8F2 0 0 0 1px inset';
- if (variant === 'outline') return '#D9E8F2 0 0 0 1px inset';
+ if (variant === 'secondary') {
+ return '#D9E8F2 0 0 0 1px inset';
+ }
+
+ if (variant === 'outline') {
+ return '#D9E8F2 0 0 0 1px inset';
+ }
return 'none';
}};
height: 32px;
@@ -49,27 +76,60 @@ const StyledButton = styled.button<{ variant: ButtonProps['variant'] }>`
&:hover {
background-color: ${({ theme, variant }) => {
- if (variant === 'primary') return '#0b94eb';
- if (variant === 'secondary') return '#eef4f9';
- if (variant === 'outline') return 'transparent';
- if (variant === 'white') return theme.color.lightest;
+ if (variant === 'primary') {
+ return '#0b94eb';
+ }
+
+ if (variant === 'secondary') {
+ return '#eef4f9';
+ }
+
+ if (variant === 'outline') {
+ return 'transparent';
+ }
+
+ if (variant === 'white') {
+ return theme.color.lightest;
+ }
return '#0b94eb';
}};
color: ${({ theme, variant }) => {
- if (variant === 'primary') return theme.color.lightest;
- if (variant === 'secondary') return theme.darkest;
- if (variant === 'outline') return theme.darkest;
- if (variant === 'white') return theme.color.darkest;
+ if (variant === 'primary') {
+ return theme.color.lightest;
+ }
+
+ if (variant === 'secondary') {
+ return theme.darkest;
+ }
+
+ if (variant === 'outline') {
+ return theme.darkest;
+ }
+
+ if (variant === 'white') {
+ return theme.color.darkest;
+ }
return theme.color.lightest;
}};
}
&:focus {
box-shadow: ${({ variant }) => {
- if (variant === 'primary') return 'inset 0 0 0 1px rgba(0, 0, 0, 0.2)';
- if (variant === 'secondary') return 'inset 0 0 0 1px #0b94eb';
- if (variant === 'outline') return 'inset 0 0 0 1px #0b94eb';
- if (variant === 'white') return 'none';
+ if (variant === 'primary') {
+ return 'inset 0 0 0 1px rgba(0, 0, 0, 0.2)';
+ }
+
+ if (variant === 'secondary') {
+ return 'inset 0 0 0 1px #0b94eb';
+ }
+
+ if (variant === 'outline') {
+ return 'inset 0 0 0 1px #0b94eb';
+ }
+
+ if (variant === 'white') {
+ return 'none';
+ }
return 'inset 0 0 0 2px rgba(0, 0, 0, 0.1)';
}};
}
diff --git a/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx b/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx
index 0a6cb70831b9..7cb0c52b0113 100644
--- a/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx
+++ b/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
-import { expect, within } from '@storybook/test';
+import { expect, waitFor, within } from '@storybook/test';
import { HighlightElement } from './HighlightElement';
@@ -38,7 +38,7 @@ export const Default: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement.parentElement!);
const button = canvas.getByRole('button');
- await expect(button).toHaveStyle('box-shadow: rgba(2,156,253,1) 0 0 2px 1px');
+ await waitFor(() => expect(button).toHaveStyle('box-shadow: rgba(2,156,253,1) 0 0 2px 1px'));
},
};
diff --git a/code/addons/onboarding/src/features/GuidedTour/GuidedTour.tsx b/code/addons/onboarding/src/features/GuidedTour/GuidedTour.tsx
index a61e44a420a9..56bbb75e7d50 100644
--- a/code/addons/onboarding/src/features/GuidedTour/GuidedTour.tsx
+++ b/code/addons/onboarding/src/features/GuidedTour/GuidedTour.tsx
@@ -26,15 +26,23 @@ export function GuidedTour({
let timeout: NodeJS.Timeout;
setStepIndex((current) => {
const index = steps.findIndex(({ key }) => key === step);
- if (index === -1) return null;
- if (index === current) return current;
+
+ if (index === -1) {
+ return null;
+ }
+
+ if (index === current) {
+ return current;
+ }
timeout = setTimeout(setStepIndex, 500, index);
return null;
});
return () => clearTimeout(timeout);
}, [step, steps]);
- if (stepIndex === null) return null;
+ if (stepIndex === null) {
+ return null;
+ }
return (
{
- if (data.action === ACTIONS.CLOSE) onClose();
- if (data.action === ACTIONS.NEXT && data.index === data.size - 1) onComplete();
+ if (data.action === ACTIONS.CLOSE) {
+ onClose();
+ }
+
+ if (data.action === ACTIONS.NEXT && data.index === data.size - 1) {
+ onComplete();
+ }
}}
floaterProps={{
disableAnimation: true,
diff --git a/code/addons/onboarding/src/features/GuidedTour/Tooltip.tsx b/code/addons/onboarding/src/features/GuidedTour/Tooltip.tsx
index 34ba2593b560..10d768094744 100644
--- a/code/addons/onboarding/src/features/GuidedTour/Tooltip.tsx
+++ b/code/addons/onboarding/src/features/GuidedTour/Tooltip.tsx
@@ -117,7 +117,10 @@ export const Tooltip: FC = ({
document.head.appendChild(style);
return () => {
const styleElement = document.querySelector('#sb-onboarding-arrow-style');
- if (styleElement) styleElement.remove();
+
+ if (styleElement) {
+ styleElement.remove();
+ }
};
}, []);
diff --git a/code/addons/onboarding/src/features/SplashScreen/SplashScreen.tsx b/code/addons/onboarding/src/features/SplashScreen/SplashScreen.tsx
index 0e373f63e16e..46e2eb90a352 100644
--- a/code/addons/onboarding/src/features/SplashScreen/SplashScreen.tsx
+++ b/code/addons/onboarding/src/features/SplashScreen/SplashScreen.tsx
@@ -194,7 +194,9 @@ export const SplashScreen = ({ onDismiss, duration = 6000 }: SplashScreenProps)
}, [onDismiss]);
useEffect(() => {
- if (!duration) return;
+ if (!duration) {
+ return;
+ }
const framelength = 1000 / 50; // 50 frames per second
const increment = 100 / (duration / framelength); // 0-100% at 20ms intervals
const interval = setInterval(() => setProgress((prev) => prev + increment), framelength);
@@ -202,7 +204,9 @@ export const SplashScreen = ({ onDismiss, duration = 6000 }: SplashScreenProps)
}, [duration]);
useEffect(() => {
- if (ready) dismiss();
+ if (ready) {
+ dismiss();
+ }
}, [ready, dismiss]);
return (
diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json
index 1fd0e5338cfa..1f2bd5595604 100644
--- a/code/addons/outline/package.json
+++ b/code/addons/outline/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-outline",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"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 438f09ec626d..61d26ce99107 100644
--- a/code/addons/storysource/package.json
+++ b/code/addons/storysource/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-storysource",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"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 c050f554b706..b901e18925e1 100644
--- a/code/addons/themes/package.json
+++ b/code/addons/themes/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-themes",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Switch between multiple themes for you components in Storybook",
"keywords": [
"css",
diff --git a/code/addons/themes/src/decorators/helpers.ts b/code/addons/themes/src/decorators/helpers.ts
index 396f0d257f24..237b0943568c 100644
--- a/code/addons/themes/src/decorators/helpers.ts
+++ b/code/addons/themes/src/decorators/helpers.ts
@@ -5,7 +5,6 @@ import type { ThemeParameters } from '../constants';
import { DEFAULT_THEME_PARAMETERS, GLOBAL_KEY, PARAM_KEY, THEMING_EVENTS } from '../constants';
/**
- *
* @param StoryContext
* @returns The global theme name set for your stories
*/
diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json
index 6a817ba70fd8..18a128a6903f 100644
--- a/code/addons/toolbars/package.json
+++ b/code/addons/toolbars/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-toolbars",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Create your own toolbar items that control story rendering",
"keywords": [
"addon",
diff --git a/code/addons/toolbars/src/components/ToolbarManager.tsx b/code/addons/toolbars/src/components/ToolbarManager.tsx
index 79ce101cb027..9d2dc0418109 100644
--- a/code/addons/toolbars/src/components/ToolbarManager.tsx
+++ b/code/addons/toolbars/src/components/ToolbarManager.tsx
@@ -8,9 +8,7 @@ import type { ToolbarArgType } from '../types';
import { normalizeArgType } from '../utils/normalize-toolbar-arg-type';
import { ToolbarMenuList } from './ToolbarMenuList';
-/**
- * A smart component for handling manager-preview interactions.
- */
+/** A smart component for handling manager-preview interactions. */
export const ToolbarManager: FC = () => {
const globalTypes = useGlobalTypes();
const globalIds = Object.keys(globalTypes).filter((id) => !!globalTypes[id].toolbar);
diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json
index 160ee246a1bb..1f57ca2cc9cd 100644
--- a/code/addons/viewport/package.json
+++ b/code/addons/viewport/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/addon-viewport",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Build responsive components by adjusting Storybook’s viewport size and orientation",
"keywords": [
"addon",
diff --git a/code/addons/vitest/package.json b/code/addons/vitest/package.json
index e318fc7f7f59..73831603d67d 100644
--- a/code/addons/vitest/package.json
+++ b/code/addons/vitest/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/experimental-addon-vitest",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Integrate Vitest with Storybook",
"keywords": [
"storybook-addons",
diff --git a/code/addons/vitest/src/plugin/index.ts b/code/addons/vitest/src/plugin/index.ts
index b607ce551df2..c1fbabb8b626 100644
--- a/code/addons/vitest/src/plugin/index.ts
+++ b/code/addons/vitest/src/plugin/index.ts
@@ -81,6 +81,10 @@ export const storybookTest = (options?: UserOptions): Plugin => {
__STORYBOOK_URL__: storybookUrl,
};
+ if (config.test.browser) {
+ config.test.browser.screenshotFailures ??= false;
+ }
+
config.resolve ??= {};
config.resolve.conditions ??= [];
config.resolve.conditions.push('storybook', 'stories', 'test');
diff --git a/code/addons/vitest/src/plugin/setup-file.test.ts b/code/addons/vitest/src/plugin/setup-file.test.ts
new file mode 100644
index 000000000000..35720515074e
--- /dev/null
+++ b/code/addons/vitest/src/plugin/setup-file.test.ts
@@ -0,0 +1,80 @@
+/* eslint-disable no-underscore-dangle */
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
+
+import { type Task, modifyErrorMessage } from './setup-file';
+
+describe('modifyErrorMessage', () => {
+ const originalUrl = import.meta.env.__STORYBOOK_URL__;
+ beforeEach(() => {
+ import.meta.env.__STORYBOOK_URL__ = 'http://localhost:6006';
+ });
+
+ afterEach(() => {
+ import.meta.env.__STORYBOOK_URL__ = originalUrl;
+ });
+
+ it('should modify the error message if the test is failing and there is a storyId in the task meta', () => {
+ const task: Task = {
+ type: 'test',
+ result: {
+ state: 'fail',
+ errors: [{ message: 'Original error message' }],
+ },
+ meta: { storyId: 'my-story' },
+ };
+
+ modifyErrorMessage({ task });
+
+ expect(task.result?.errors?.[0].message).toMatchInlineSnapshot(`
+ "
+ [34mClick to debug the error directly in Storybook: http://localhost:6006/?path=/story/my-story&addonPanel=storybook/interactions/panel[39m
+
+ Original error message"
+ `);
+ expect(task.result?.errors?.[0].message).toContain('Original error message');
+ });
+
+ it('should not modify the error message if task type is not "test"', () => {
+ const task: Task = {
+ type: 'custom',
+ result: {
+ state: 'fail',
+ errors: [{ message: 'Original error message' }],
+ },
+ meta: { storyId: 'my-story' },
+ };
+
+ modifyErrorMessage({ task });
+
+ expect(task.result?.errors?.[0].message).toBe('Original error message');
+ });
+
+ it('should not modify the error message if task result state is not "fail"', () => {
+ const task: Task = {
+ type: 'test',
+ result: {
+ state: 'pass',
+ },
+ meta: { storyId: 'my-story' },
+ };
+
+ modifyErrorMessage({ task });
+
+ expect(task.result?.errors).toBeUndefined();
+ });
+
+ it('should not modify the error message if meta.storyId is not present', () => {
+ const task: Task = {
+ type: 'test',
+ result: {
+ state: 'fail',
+ errors: [{ message: 'Non story test failure' }],
+ },
+ meta: {},
+ };
+
+ modifyErrorMessage({ task });
+
+ expect(task.result?.errors?.[0].message).toBe('Non story test failure');
+ });
+});
diff --git a/code/addons/vitest/src/plugin/setup-file.ts b/code/addons/vitest/src/plugin/setup-file.ts
index b5f411e97671..ad3db3807121 100644
--- a/code/addons/vitest/src/plugin/setup-file.ts
+++ b/code/addons/vitest/src/plugin/setup-file.ts
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable no-underscore-dangle */
-import { afterAll, vi } from 'vitest';
-import type { RunnerTask, TaskMeta } from 'vitest';
+import { afterEach, vi } from 'vitest';
+import type { RunnerTask } from 'vitest';
import { Channel } from 'storybook/internal/channels';
@@ -13,28 +13,26 @@ declare global {
var __STORYBOOK_ADDONS_CHANNEL__: Channel;
}
-type ExtendedMeta = TaskMeta & { storyId: string; hasPlayFunction: boolean };
+export type Task = Partial & {
+ meta: Record;
+};
const transport = { setHandler: vi.fn(), send: vi.fn() };
-globalThis.__STORYBOOK_ADDONS_CHANNEL__ = new Channel({ transport });
+globalThis.__STORYBOOK_ADDONS_CHANNEL__ ??= new Channel({ transport });
-// The purpose of this set up file is to modify the error message of failed tests
-// and inject a link to the story in Storybook
-const modifyErrorMessage = (currentTask: RunnerTask) => {
- const meta = currentTask.meta as ExtendedMeta;
+export const modifyErrorMessage = ({ task }: { task: Task }) => {
+ const meta = task.meta;
if (
- currentTask.type === 'test' &&
- currentTask.result?.state === 'fail' &&
+ task.type === 'test' &&
+ task.result?.state === 'fail' &&
meta.storyId &&
- currentTask.result.errors?.[0]
+ task.result.errors?.[0]
) {
- const currentError = currentTask.result.errors[0];
+ const currentError = task.result.errors[0];
const storybookUrl = import.meta.env.__STORYBOOK_URL__;
const storyUrl = `${storybookUrl}/?path=/story/${meta.storyId}&addonPanel=storybook/interactions/panel`;
currentError.message = `\n\x1B[34mClick to debug the error directly in Storybook: ${storyUrl}\x1B[39m\n\n${currentError.message}`;
}
};
-afterAll((suite) => {
- suite.tasks.forEach(modifyErrorMessage);
-});
+afterEach(modifyErrorMessage);
diff --git a/code/addons/vitest/src/plugin/types.ts b/code/addons/vitest/src/plugin/types.ts
index a339a7e694f5..b907cd081fcc 100644
--- a/code/addons/vitest/src/plugin/types.ts
+++ b/code/addons/vitest/src/plugin/types.ts
@@ -1,25 +1,27 @@
export type UserOptions = {
/**
- * The directory where the Storybook configuration is located, relative to the vitest configuration file.
- * If not provided, the plugin will use '.storybook' in the current working directory.
- * @default '.storybook'
+ * The directory where the Storybook configuration is located, relative to the vitest
+ * configuration file. If not provided, the plugin will use '.storybook' in the current working
+ * directory.
+ *
+ * @default '.storybook'
*/
configDir?: string;
/**
- * Optional script to run Storybook.
- * If provided, Vitest will start Storybook using this script when ran in watch mode.
- * @default undefined
+ * Optional script to run Storybook. If provided, Vitest will start Storybook using this script
+ * when ran in watch mode.
+ *
+ * @default undefined
*/
storybookScript?: string;
/**
- * The URL where Storybook is hosted.
- * This is used to provide a link to the story in the test output on failures.
- * @default 'http://localhost:6006'
+ * The URL where Storybook is hosted. This is used to provide a link to the story in the test
+ * output on failures.
+ *
+ * @default 'http://localhost:6006'
*/
storybookUrl?: string;
- /**
- * Tags to include, exclude, or skip. These tags are defined as annotations in your story or meta.
- */
+ /** Tags to include, exclude, or skip. These tags are defined as annotations in your story or meta. */
tags?: {
include?: string[];
exclude?: string[];
diff --git a/code/addons/vitest/src/plugin/viewports.test.ts b/code/addons/vitest/src/plugin/viewports.test.ts
new file mode 100644
index 000000000000..7b99e252ffe9
--- /dev/null
+++ b/code/addons/vitest/src/plugin/viewports.test.ts
@@ -0,0 +1,151 @@
+/* eslint-disable no-underscore-dangle */
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+
+import { page } from '@vitest/browser/context';
+
+import { DEFAULT_VIEWPORT_DIMENSIONS, type ViewportsParam, setViewport } from './viewports';
+
+vi.mock('@vitest/browser/context', () => ({
+ page: {
+ viewport: vi.fn(),
+ },
+}));
+
+describe('setViewport', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ globalThis.__vitest_browser__ = true;
+ });
+
+ afterEach(() => {
+ globalThis.__vitest_browser__ = false;
+ });
+
+ it('should no op outside when not in Vitest browser mode', async () => {
+ globalThis.__vitest_browser__ = false;
+
+ await setViewport();
+ expect(page.viewport).not.toHaveBeenCalled();
+ });
+
+ it('should fall back to DEFAULT_VIEWPORT_DIMENSIONS if defaultViewport does not exist', async () => {
+ const viewportsParam: any = {
+ defaultViewport: 'nonExistentViewport',
+ };
+
+ await setViewport(viewportsParam);
+ expect(page.viewport).toHaveBeenCalledWith(1200, 900);
+ });
+
+ it('should set the dimensions of viewport from INITIAL_VIEWPORTS', async () => {
+ const viewportsParam: any = {
+ // supported by default in addon viewports
+ defaultViewport: 'ipad',
+ };
+
+ await setViewport(viewportsParam);
+ expect(page.viewport).toHaveBeenCalledWith(768, 1024);
+ });
+
+ it('should set custom defined viewport dimensions', async () => {
+ const viewportsParam: ViewportsParam = {
+ defaultViewport: 'customViewport',
+ viewports: {
+ customViewport: {
+ name: 'Custom Viewport',
+ type: 'mobile',
+ styles: {
+ width: '800px',
+ height: '600px',
+ },
+ },
+ },
+ };
+
+ await setViewport(viewportsParam);
+ expect(page.viewport).toHaveBeenCalledWith(800, 600);
+ });
+
+ it('should correctly handle percentage-based dimensions', async () => {
+ const viewportsParam: ViewportsParam = {
+ defaultViewport: 'percentageViewport',
+ viewports: {
+ percentageViewport: {
+ name: 'Percentage Viewport',
+ type: 'desktop',
+ styles: {
+ width: '50%',
+ height: '50%',
+ },
+ },
+ },
+ };
+
+ await setViewport(viewportsParam);
+ expect(page.viewport).toHaveBeenCalledWith(600, 450); // 50% of 1920 and 1080
+ });
+
+ it('should correctly handle vw and vh based dimensions', async () => {
+ const viewportsParam: ViewportsParam = {
+ defaultViewport: 'viewportUnits',
+ viewports: {
+ viewportUnits: {
+ name: 'VW/VH Viewport',
+ type: 'desktop',
+ styles: {
+ width: '50vw',
+ height: '50vh',
+ },
+ },
+ },
+ };
+
+ await setViewport(viewportsParam);
+ expect(page.viewport).toHaveBeenCalledWith(600, 450); // 50% of 1920 and 1080
+ });
+
+ it('should correctly handle em based dimensions', async () => {
+ const viewportsParam: ViewportsParam = {
+ defaultViewport: 'viewportUnits',
+ viewports: {
+ viewportUnits: {
+ name: 'em/rem Viewport',
+ type: 'mobile',
+ styles: {
+ width: '20em',
+ height: '40rem',
+ },
+ },
+ },
+ };
+
+ await setViewport(viewportsParam);
+ expect(page.viewport).toHaveBeenCalledWith(320, 640); // dimensions * 16
+ });
+
+ it('should throw an error for unsupported dimension values', async () => {
+ const viewportsParam: ViewportsParam = {
+ defaultViewport: 'invalidViewport',
+ viewports: {
+ invalidViewport: {
+ name: 'Invalid Viewport',
+ type: 'desktop',
+ styles: {
+ width: 'calc(100vw - 20px)',
+ height: '10pc',
+ },
+ },
+ },
+ };
+
+ await expect(setViewport(viewportsParam)).rejects.toThrowErrorMatchingInlineSnapshot(`
+ [SB_ADDON_VITEST_0001 (UnsupportedViewportDimensionError): Encountered an unsupported value "calc(100vw - 20px)" when setting the viewport width dimension.
+
+ The Storybook plugin only supports values in the following units:
+ - px, vh, vw, em, rem and %.
+
+ You can either change the viewport for this story to use one of the supported units or skip the test by adding '!test' to the story's tags per https://storybook.js.org/docs/writing-stories/tags]
+ `);
+ expect(page.viewport).not.toHaveBeenCalled();
+ });
+});
diff --git a/code/addons/vitest/src/plugin/viewports.ts b/code/addons/vitest/src/plugin/viewports.ts
index 33312ecbbe4d..c68047877006 100644
--- a/code/addons/vitest/src/plugin/viewports.ts
+++ b/code/addons/vitest/src/plugin/viewports.ts
@@ -1,4 +1,6 @@
/* eslint-disable no-underscore-dangle */
+import { UnsupportedViewportDimensionError } from 'storybook/internal/preview-errors';
+
import { page } from '@vitest/browser/context';
import { INITIAL_VIEWPORTS } from '../../../viewport/src/defaults';
@@ -9,30 +11,65 @@ declare global {
var __vitest_browser__: boolean;
}
-interface ViewportsParam {
+export interface ViewportsParam {
defaultViewport: string;
viewports: ViewportMap;
}
+export const DEFAULT_VIEWPORT_DIMENSIONS = {
+ width: 1200,
+ height: 900,
+};
+
+const validPixelOrNumber = /^\d+(px)?$/;
+const percentagePattern = /^(\d+(\.\d+)?%)$/;
+const vwPattern = /^(\d+(\.\d+)?vw)$/;
+const vhPattern = /^(\d+(\.\d+)?vh)$/;
+const emRemPattern = /^(\d+)(em|rem)$/;
+
+const parseDimension = (value: string, dimension: 'width' | 'height') => {
+ if (validPixelOrNumber.test(value)) {
+ return Number.parseInt(value, 10);
+ } else if (percentagePattern.test(value)) {
+ const percentageValue = parseFloat(value) / 100;
+ return Math.round(DEFAULT_VIEWPORT_DIMENSIONS[dimension] * percentageValue);
+ } else if (vwPattern.test(value)) {
+ const vwValue = parseFloat(value) / 100;
+ return Math.round(DEFAULT_VIEWPORT_DIMENSIONS.width * vwValue);
+ } else if (vhPattern.test(value)) {
+ const vhValue = parseFloat(value) / 100;
+ return Math.round(DEFAULT_VIEWPORT_DIMENSIONS.height * vhValue);
+ } else if (emRemPattern.test(value)) {
+ const emRemValue = Number.parseInt(value, 10);
+ return emRemValue * 16;
+ } else {
+ throw new UnsupportedViewportDimensionError({ dimension, value });
+ }
+};
+
export const setViewport = async (viewportsParam: ViewportsParam = {} as ViewportsParam) => {
const defaultViewport = viewportsParam.defaultViewport;
- if (!page || !globalThis.__vitest_browser__ || !defaultViewport) return null;
+
+ if (!page || !globalThis.__vitest_browser__ || !defaultViewport) {
+ return;
+ }
const viewports = {
...INITIAL_VIEWPORTS,
...viewportsParam.viewports,
};
+ let viewportWidth = DEFAULT_VIEWPORT_DIMENSIONS.width;
+ let viewportHeight = DEFAULT_VIEWPORT_DIMENSIONS.height;
+
if (defaultViewport in viewports) {
const styles = viewports[defaultViewport].styles as ViewportStyles;
if (styles?.width && styles?.height) {
- const { width, height } = {
- width: Number.parseInt(styles.width, 10),
- height: Number.parseInt(styles.height, 10),
- };
- await page.viewport(width, height);
+ const { width, height } = styles;
+ viewportWidth = parseDimension(width, 'width');
+ viewportHeight = parseDimension(height, 'height');
}
}
- return null;
+ await page.viewport(viewportWidth, viewportHeight);
};
diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json
index 09d900c0d663..aefba4ffaca8 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.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"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-vite/src/codegen-importfn-script.ts b/code/builders/builder-vite/src/codegen-importfn-script.ts
index abf89ce09a73..0853b0549628 100644
--- a/code/builders/builder-vite/src/codegen-importfn-script.ts
+++ b/code/builders/builder-vite/src/codegen-importfn-script.ts
@@ -5,13 +5,14 @@ import type { Options } from 'storybook/internal/types';
import { listStories } from './list-stories';
/**
- * This file is largely based on https://github.com/storybookjs/storybook/blob/d1195cbd0c61687f1720fefdb772e2f490a46584/lib/core-common/src/utils/to-importFn.ts
+ * This file is largely based on
+ * https://github.com/storybookjs/storybook/blob/d1195cbd0c61687f1720fefdb772e2f490a46584/lib/core-common/src/utils/to-importFn.ts
*/
/**
- * Paths get passed either with no leading './' - e.g. `src/Foo.stories.js`,
- * or with a leading `../` (etc), e.g. `../src/Foo.stories.js`.
- * We want to deal in importPaths relative to the working dir, so we normalize
+ * Paths get passed either with no leading './' - e.g. `src/Foo.stories.js`, or with a leading `../`
+ * (etc), e.g. `../src/Foo.stories.js`. We want to deal in importPaths relative to the working dir,
+ * so we normalize
*/
function toImportPath(relativePath: string) {
return relativePath.startsWith('../') ? relativePath : `./${relativePath}`;
@@ -19,9 +20,10 @@ function toImportPath(relativePath: string) {
/**
* This function takes an array of stories and creates a mapping between the stories' relative paths
- * to the working directory and their dynamic imports. The import is done in an asynchronous function
- * to delay loading. It then creates a function, `importFn(path)`, which resolves a path to an import
- * function and this is called by Storybook to fetch a story dynamically when needed.
+ * to the working directory and their dynamic imports. The import is done in an asynchronous
+ * function to delay loading. It then creates a function, `importFn(path)`, which resolves a path to
+ * an import function and this is called by Storybook to fetch a story dynamically when needed.
+ *
* @param stories An array of absolute story paths.
*/
async function toImportFn(stories: string[]) {
diff --git a/code/builders/builder-vite/src/codegen-modern-iframe-script.ts b/code/builders/builder-vite/src/codegen-modern-iframe-script.ts
index 86a39776ddeb..2de92617befa 100644
--- a/code/builders/builder-vite/src/codegen-modern-iframe-script.ts
+++ b/code/builders/builder-vite/src/codegen-modern-iframe-script.ts
@@ -59,9 +59,11 @@ export async function generateModernIframeScriptCode(options: Options, projectRo
};
/**
- * This code is largely taken from https://github.com/storybookjs/storybook/blob/d1195cbd0c61687f1720fefdb772e2f490a46584/builders/builder-webpack4/src/preview/virtualModuleModernEntry.js.handlebars
- * Some small tweaks were made to `getProjectAnnotations` (since `import()` needs to be resolved asynchronously)
- * and the HMR implementation has been tweaked to work with Vite.
+ * This code is largely taken from
+ * https://github.com/storybookjs/storybook/blob/d1195cbd0c61687f1720fefdb772e2f490a46584/builders/builder-webpack4/src/preview/virtualModuleModernEntry.js.handlebars
+ * Some small tweaks were made to `getProjectAnnotations` (since `import()` needs to be resolved
+ * asynchronously) and the HMR implementation has been tweaked to work with Vite.
+ *
* @todo Inline variable and remove `noinspection`
*/
const code = `
diff --git a/code/builders/builder-vite/src/envs.ts b/code/builders/builder-vite/src/envs.ts
index 422ce3ae28bf..6d28c9b612b7 100644
--- a/code/builders/builder-vite/src/envs.ts
+++ b/code/builders/builder-vite/src/envs.ts
@@ -16,8 +16,8 @@ const allowedEnvVariables = [
];
/**
- * Customized version of stringifyProcessEnvs from @storybook/core-common which
- * uses import.meta.env instead of process.env and checks for allowed variables.
+ * Customized version of stringifyProcessEnvs from @storybook/core-common which uses import.meta.env
+ * instead of process.env and checks for allowed variables.
*/
export function stringifyProcessEnvs(raw: Builder_EnvsRaw, envPrefix: ViteConfig['envPrefix']) {
const updatedRaw: Builder_EnvsRaw = {};
diff --git a/code/builders/builder-vite/src/optimizeDeps.ts b/code/builders/builder-vite/src/optimizeDeps.ts
index 5937c4497720..0e81d7d5afc4 100644
--- a/code/builders/builder-vite/src/optimizeDeps.ts
+++ b/code/builders/builder-vite/src/optimizeDeps.ts
@@ -111,7 +111,8 @@ const INCLUDE_CANDIDATES = [
];
/**
- * Helper function which allows us to `filter` with an async predicate. Uses Promise.all for performance.
+ * Helper function which allows us to `filter` with an async predicate. Uses Promise.all for
+ * performance.
*/
const asyncFilter = async (arr: string[], predicate: (val: string) => Promise) =>
Promise.all(arr.map(predicate)).then((results) => arr.filter((_v, index) => results[index]));
diff --git a/code/builders/builder-vite/src/plugins/external-globals-plugin.ts b/code/builders/builder-vite/src/plugins/external-globals-plugin.ts
index 8fbe95669f1d..1c7ada46b7be 100644
--- a/code/builders/builder-vite/src/plugins/external-globals-plugin.ts
+++ b/code/builders/builder-vite/src/plugins/external-globals-plugin.ts
@@ -18,23 +18,24 @@ const replacementMap = new Map([
]);
/**
- * This plugin swaps out imports of pre-bundled storybook preview modules for destructured from global
- * variables that are added in runtime.js.
+ * This plugin swaps out imports of pre-bundled storybook preview modules for destructured from
+ * global variables that are added in runtime.js.
*
- * For instance:
+ * @example
*
* ```js
- * import { useMemo as useMemo2, useEffect as useEffect2 } from "@storybook/preview-api";
+ * import { useMemo as useMemo2, useEffect as useEffect2 } from '@storybook/preview-api';
* ```
*
- * becomes
+ * Becomes
*
* ```js
* const { useMemo: useMemo2, useEffect: useEffect2 } = __STORYBOOK_MODULE_PREVIEW_API__;
* ```
*
- * It is based on existing plugins like https://github.com/crcong/vite-plugin-externals
- * and https://github.com/eight04/rollup-plugin-external-globals, but simplified to meet our simple needs.
+ * It is based on existing plugins like https://github.com/crcong/vite-plugin-externals and
+ * https://github.com/eight04/rollup-plugin-external-globals, but simplified to meet our simple
+ * needs.
*/
export async function externalGlobalsPlugin(externals: Record) {
await init;
@@ -72,7 +73,10 @@ export async function externalGlobalsPlugin(externals: Record) {
// Replace imports with variables destructured from global scope
async transform(code: string, id: string) {
const globalsList = Object.keys(externals);
- if (globalsList.every((glob) => !code.includes(glob))) return undefined;
+
+ if (globalsList.every((glob) => !code.includes(glob))) {
+ return undefined;
+ }
const [imports] = parse(code);
const src = new MagicString(code);
diff --git a/code/builders/builder-vite/src/plugins/inject-export-order-plugin.ts b/code/builders/builder-vite/src/plugins/inject-export-order-plugin.ts
index 9587b23fdaf7..01b835ff6187 100644
--- a/code/builders/builder-vite/src/plugins/inject-export-order-plugin.ts
+++ b/code/builders/builder-vite/src/plugins/inject-export-order-plugin.ts
@@ -12,7 +12,9 @@ export async function injectExportOrderPlugin() {
// This should only run after the typescript has been transpiled
enforce: 'post',
async transform(code: string, id: string) {
- if (!filter(id)) return undefined;
+ if (!filter(id)) {
+ return undefined;
+ }
// TODO: Maybe convert `injectExportOrderPlugin` to function that returns object,
// and run `await init;` once and then call `parse()` without `await`,
diff --git a/code/builders/builder-vite/src/plugins/strip-story-hmr-boundaries.ts b/code/builders/builder-vite/src/plugins/strip-story-hmr-boundaries.ts
index d393d41476b1..2fe136b003db 100644
--- a/code/builders/builder-vite/src/plugins/strip-story-hmr-boundaries.ts
+++ b/code/builders/builder-vite/src/plugins/strip-story-hmr-boundaries.ts
@@ -2,8 +2,8 @@ import MagicString from 'magic-string';
import type { Plugin } from 'vite';
/**
- * This plugin removes HMR `accept` calls in story files. Stories should not be treated
- * as hmr boundaries, but vite has a bug which causes them to be treated as boundaries
+ * This plugin removes HMR `accept` calls in story files. Stories should not be treated as hmr
+ * boundaries, but vite has a bug which causes them to be treated as boundaries
* (https://github.com/vitejs/vite/issues/9869).
*/
export async function stripStoryHMRBoundary(): Promise {
@@ -14,7 +14,9 @@ export async function stripStoryHMRBoundary(): Promise {
name: 'storybook:strip-hmr-boundary-plugin',
enforce: 'post',
async transform(src: string, id: string) {
- if (!filter(id)) return undefined;
+ if (!filter(id)) {
+ return undefined;
+ }
const s = new MagicString(src);
s.replace(/import\.meta\.hot\.accept\(\);/, '');
diff --git a/code/builders/builder-vite/src/plugins/webpack-stats-plugin.ts b/code/builders/builder-vite/src/plugins/webpack-stats-plugin.ts
index 3669bfd4a745..3b8deebc8111 100644
--- a/code/builders/builder-vite/src/plugins/webpack-stats-plugin.ts
+++ b/code/builders/builder-vite/src/plugins/webpack-stats-plugin.ts
@@ -25,15 +25,14 @@ type WebpackStatsPluginOptions = {
};
/**
- * Strips off query params added by rollup/vite to ids, to make paths compatible for comparison with git.
+ * Strips off query params added by rollup/vite to ids, to make paths compatible for comparison with
+ * git.
*/
function stripQueryParams(filePath: string): string {
return filePath.split('?')[0];
}
-/**
- * We only care about user code, not node_modules, vite files, or (most) virtual files.
- */
+/** We only care about user code, not node_modules, vite files, or (most) virtual files. */
function isUserCode(moduleName: string) {
return Boolean(
moduleName &&
@@ -48,9 +47,7 @@ function isUserCode(moduleName: string) {
export type WebpackStatsPlugin = Plugin & { storybookGetStats: () => BuilderStats };
export function pluginWebpackStats({ workingDir }: WebpackStatsPluginOptions): WebpackStatsPlugin {
- /**
- * Convert an absolute path name to a path relative to the vite root, with a starting `./`
- */
+ /** Convert an absolute path name to a path relative to the vite root, with a starting `./` */
function normalize(filename: string) {
// Do not try to resolve virtual files
if (filename.startsWith('/virtual:')) {
@@ -64,16 +61,12 @@ export function pluginWebpackStats({ workingDir }: WebpackStatsPluginOptions): W
}
}
- /**
- * Helper to create Reason objects out of a list of string paths
- */
+ /** Helper to create Reason objects out of a list of string paths */
function createReasons(importers?: readonly string[]): Reason[] {
return (importers || []).map((i) => ({ moduleName: normalize(i) }));
}
- /**
- * Helper function to build a `Module` given a filename and list of files that import it
- */
+ /** Helper function to build a `Module` given a filename and list of files that import it */
function createStatsMapModule(filename: string, importers?: readonly string[]): Module {
return {
id: filename,
diff --git a/code/builders/builder-vite/src/types.ts b/code/builders/builder-vite/src/types.ts
index 404a259243a5..a3a2ab2ccc33 100644
--- a/code/builders/builder-vite/src/types.ts
+++ b/code/builders/builder-vite/src/types.ts
@@ -19,8 +19,6 @@ export type StorybookConfigVite = {
};
export type BuilderOptions = {
- /**
- * Path to vite.config file, relative to CWD.
- */
+ /** Path to `vite.config` file, relative to `process.cwd()`. */
viteConfigPath?: string;
};
diff --git a/code/builders/builder-vite/src/utils/has-vite-plugins.ts b/code/builders/builder-vite/src/utils/has-vite-plugins.ts
index 545176e4b85d..f56b24cd3983 100644
--- a/code/builders/builder-vite/src/utils/has-vite-plugins.ts
+++ b/code/builders/builder-vite/src/utils/has-vite-plugins.ts
@@ -7,8 +7,8 @@ function checkName(plugin: PluginOption, names: string[]) {
}
/**
- * Returns true if ANY of the plugins in the array have a name that matches one of the names in the names array.
- * Will resolve any promises in the array.
+ * Returns true if ANY of the plugins in the array have a name that matches one of the names in the
+ * names array. Will resolve any promises in the array.
*/
export async function hasVitePlugins(plugins: PluginOption[], names: string[]) {
const resolvedPlugins = await Promise.all(plugins);
diff --git a/code/builders/builder-vite/src/utils/process-preview-annotation.ts b/code/builders/builder-vite/src/utils/process-preview-annotation.ts
index d63dc9d375d1..7ff6f7a00081 100644
--- a/code/builders/builder-vite/src/utils/process-preview-annotation.ts
+++ b/code/builders/builder-vite/src/utils/process-preview-annotation.ts
@@ -6,11 +6,10 @@ import type { PreviewAnnotation } from 'storybook/internal/types';
import slash from 'slash';
/**
- * Preview annotations can take several forms, and vite needs them to be
- * a bit more restrained.
+ * Preview annotations can take several forms, and vite needs them to be a bit more restrained.
*
- * For node_modules, we want bare imports (so vite can process them),
- * and for files in the user's source, we want URLs absolute relative to project root.
+ * For node_modules, we want bare imports (so vite can process them), and for files in the user's
+ * source, we want URLs absolute relative to project root.
*/
export function processPreviewAnnotation(path: PreviewAnnotation | undefined, projectRoot: string) {
// If entry is an object, take the first, which is the
diff --git a/code/builders/builder-vite/src/utils/without-vite-plugins.ts b/code/builders/builder-vite/src/utils/without-vite-plugins.ts
index 708bd4348652..1a1c5685635c 100644
--- a/code/builders/builder-vite/src/utils/without-vite-plugins.ts
+++ b/code/builders/builder-vite/src/utils/without-vite-plugins.ts
@@ -1,9 +1,6 @@
import type { PluginOption } from 'vite';
-/**
- * Recursively removes all plugins with the names given
- * Resolves async plugins
- */
+/** Recursively removes all plugins with the names given Resolves async plugins */
export const withoutVitePlugins = async (
plugins: PluginOption[] = [],
namesToRemove: string[]
diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json
index e58e3b1afc63..cd17b935e139 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.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Storybook framework-agnostic API",
"keywords": [
"storybook"
diff --git a/code/builders/builder-webpack5/src/index.ts b/code/builders/builder-webpack5/src/index.ts
index 12b38b0709ee..f9a83f8efaf2 100644
--- a/code/builders/builder-webpack5/src/index.ts
+++ b/code/builders/builder-webpack5/src/index.ts
@@ -106,8 +106,8 @@ export const bail: WebpackBuilder['bail'] = async () => {
};
/**
- * This function is a generator so that we can abort it mid process
- * in case of failure coming from other processes e.g. preview builder
+ * This function is a generator so that we can abort it mid process in case of failure coming from
+ * other processes e.g. preview builder
*
* I am sorry for making you read about generators today :')
*/
@@ -231,8 +231,8 @@ function getWebpackStats({ config, stats }: { config: Configuration; stats: Stat
}
/**
- * This function is a generator so that we can abort it mid process
- * in case of failure coming from other processes e.g. manager builder
+ * This function is a generator so that we can abort it mid process in case of failure coming from
+ * other processes e.g. manager builder
*
* I am sorry for making you read about generators today :')
*/
diff --git a/code/builders/builder-webpack5/src/types.ts b/code/builders/builder-webpack5/src/types.ts
index 1064cdb485f6..5576baa5deea 100644
--- a/code/builders/builder-webpack5/src/types.ts
+++ b/code/builders/builder-webpack5/src/types.ts
@@ -10,26 +10,20 @@ import type { Configuration, Stats } from 'webpack';
type TypeScriptOptionsBase = Partial;
-/**
- * Options for TypeScript usage within Storybook.
- */
+/** Options for TypeScript usage within Storybook. */
export interface TypescriptOptions extends TypeScriptOptionsBase {
- /**
- * Configures `fork-ts-checker-webpack-plugin`
- */
+ /** Configures `fork-ts-checker-webpack-plugin` */
checkOptions?: ConstructorParameters[0];
}
export interface StorybookConfigWebpack extends Omit {
/**
- * Modify or return a custom Webpack config after the Storybook's default configuration
- * has run (mostly used by addons).
+ * Modify or return a custom Webpack config after the Storybook's default configuration has run
+ * (mostly used by addons).
*/
webpack?: (config: Configuration, options: Options) => Configuration | Promise;
- /**
- * Modify or return a custom Webpack config after every addon has run.
- */
+ /** Modify or return a custom Webpack config after every addon has run. */
webpackFinal?: (
config: Configuration,
options: Options
diff --git a/code/core/package.json b/code/core/package.json
index c8d0072041b7..e32184d7e822 100644
--- a/code/core/package.json
+++ b/code/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@storybook/core",
- "version": "8.3.0-alpha.6",
+ "version": "8.3.0-alpha.7",
"description": "Storybook framework-agnostic API",
"keywords": [
"storybook"
@@ -338,7 +338,7 @@
"chai": "^4.4.1",
"chalk": "^5.3.0",
"cli-table3": "^0.6.1",
- "commander": "^6.2.1",
+ "commander": "^12.1.0",
"comment-parser": "^1.4.1",
"compression": "^1.7.4",
"copy-to-clipboard": "^3.3.1",
diff --git a/code/core/scripts/helpers/generatePackageJsonFile.ts b/code/core/scripts/helpers/generatePackageJsonFile.ts
index 08a7975e3d9b..9ecf2f7679e5 100644
--- a/code/core/scripts/helpers/generatePackageJsonFile.ts
+++ b/code/core/scripts/helpers/generatePackageJsonFile.ts
@@ -13,8 +13,10 @@ export async function generatePackageJsonFile(entries: ReturnType>>((acc, entry) => {
let main = './' + slash(relative(cwd, entry.file).replace('src', 'dist'));
@@ -47,8 +49,11 @@ export async function generatePackageJsonFile(entries: ReturnType) {
- /** Generate the type mapper files, which are used to map the types to the SOURCE location.
- * This would be for development builds ONLY, **HOWEVER**:
- * During a production build we ALSO run this, because we want to generate a `d.ts` file for each entry in parallel.
- * By generating these files (in parallel) first, we can then ensure we can compile the actual type definitions in parallel.
- * This is because the type definitions have interdependencies between them.
- * These interdependencies are MEGA complex, and this simplified approach immensely is the only way to ensure we can compile them in parallel.
+ /**
+ * Generate the type mapper files, which are used to map the types to the SOURCE location. This
+ * would be for development builds ONLY, **HOWEVER**: During a production build we ALSO run this,
+ * because we want to generate a `d.ts` file for each entry in parallel. By generating these files
+ * (in parallel) first, we can then ensure we can compile the actual type definitions in parallel.
+ * This is because the type definitions have interdependencies between them. These
+ * interdependencies are MEGA complex, and this simplified approach immensely is the only way to
+ * ensure we can compile them in parallel.
*/
const all = entries.filter((e) => e.dts).map((e) => e.file);
diff --git a/code/core/scripts/helpers/modifyThemeTypes.ts b/code/core/scripts/helpers/modifyThemeTypes.ts
index 5e586f4763bc..5b35ca6be329 100644
--- a/code/core/scripts/helpers/modifyThemeTypes.ts
+++ b/code/core/scripts/helpers/modifyThemeTypes.ts
@@ -5,9 +5,10 @@ import { dedent } from '../../../../scripts/prepare/tools';
export async function modifyThemeTypes() {
/**
- * This is a unique hack (pre-existing the CPC project) because the only way to set a custom Theme interface with emotion, is by module enhancement.
- * This is not an option for us, because we pre-bundle emotion in.
- * The little hack work to ensure the `Theme` export is overloaded with our `StorybookTheme` interface. (in both development and production builds)
+ * This is a unique hack (pre-existing the CPC project) because the only way to set a custom Theme
+ * interface with emotion, is by module enhancement. This is not an option for us, because we
+ * pre-bundle emotion in. The little hack work to ensure the `Theme` export is overloaded with our
+ * `StorybookTheme` interface. (in both development and production builds)
*/
const target = join(__dirname, '..', '..', 'dist', 'theming', 'index.d.ts');
const contents = await readFile(target, 'utf-8');
diff --git a/code/core/scripts/helpers/sourcefiles.ts b/code/core/scripts/helpers/sourcefiles.ts
index 7b38a00e025e..2f437961a91e 100644
--- a/code/core/scripts/helpers/sourcefiles.ts
+++ b/code/core/scripts/helpers/sourcefiles.ts
@@ -55,7 +55,7 @@ async function generateVersionsFile(prettierConfig: prettier.Options | null): Pr
}
async function generateFrameworksFile(prettierConfig: prettier.Options | null): Promise {
- const thirdPartyFrameworks = ['qwik', 'solid'];
+ const thirdPartyFrameworks = ['qwik', 'solid', 'react-rsbuild', 'vue3-rsbuild'];
const location = join(__dirname, '..', '..', 'src', 'types', 'modules', 'frameworks.ts');
const frameworksDirectory = join(__dirname, '..', '..', '..', 'frameworks');
diff --git a/code/core/scripts/prep.ts b/code/core/scripts/prep.ts
index a24980b296f5..a9605232991c 100644
--- a/code/core/scripts/prep.ts
+++ b/code/core/scripts/prep.ts
@@ -312,9 +312,10 @@ async function run() {
await context.dispose();
/**
- * I'm leaving this in place, because I want to start utilizing it in the future.
- * I'm imagining a github action that shows the bundle analysis in the PR.
- * I didn't have the project-scope to make that happen now, but I want expose this very rich useful data accessible, for the next person investigating bundle size issues.
+ * I'm leaving this in place, because I want to start utilizing it in the future. I'm
+ * imagining a github action that shows the bundle analysis in the PR. I didn't have the
+ * project-scope to make that happen now, but I want expose this very rich useful data
+ * accessible, for the next person investigating bundle size issues.
*/
// if (out.metafile) {
diff --git a/code/core/src/builder-manager/index.ts b/code/core/src/builder-manager/index.ts
index e23d3bb89ac0..1e246b5d1cb1 100644
--- a/code/core/src/builder-manager/index.ts
+++ b/code/core/src/builder-manager/index.ts
@@ -116,8 +116,8 @@ export const executor = {
};
/**
- * This function is a generator so that we can abort it mid process
- * in case of failure coming from other processes e.g. preview builder
+ * This function is a generator so that we can abort it mid process in case of failure coming from
+ * other processes e.g. preview builder
*
* I am sorry for making you read about generators today :')
*/
@@ -214,8 +214,8 @@ const starter: StarterFunction = async function* starterGeneratorFn({
};
/**
- * This function is a generator so that we can abort it mid process
- * in case of failure coming from other processes e.g. preview builder
+ * This function is a generator so that we can abort it mid process in case of failure coming from
+ * other processes e.g. preview builder
*
* I am sorry for making you read about generators today :')
*/
diff --git a/code/core/src/builder-manager/utils/managerEntries.ts b/code/core/src/builder-manager/utils/managerEntries.ts
index a30fbab4a4bd..d808596f52e4 100644
--- a/code/core/src/builder-manager/utils/managerEntries.ts
+++ b/code/core/src/builder-manager/utils/managerEntries.ts
@@ -21,20 +21,23 @@ const sanitizeFinal = (path: string) => {
};
/**
- * Manager entries should be **self-invoking** bits of code.
- * They can of-course import from modules, and ESbuild will bundle all of that into a single file.
- * But they should not export anything. However this can't be enforced, so what we do is wrap the given file, in a bit of code like this:
+ * Manager entries should be **self-invoking** bits of code. They can of-course import from modules,
+ * and ESbuild will bundle all of that into a single file. But they should not export anything.
+ * However this can't be enforced, so what we do is wrap the given file, in a bit of code like
+ * this:
*
* ```js
* import '<>';
* ```
*
- * That way we are indicating to ESbuild that we do not care about this files exports, and they will be dropped in the bundle.
+ * That way we are indicating to ESbuild that we do not care about this files exports, and they will
+ * be dropped in the bundle.
*
- * We do all of that so we can wrap a try-catch around the code.
- * That would have been invalid syntax had the export statements been left in place.
+ * We do all of that so we can wrap a try-catch around the code. That would have been invalid syntax
+ * had the export statements been left in place.
*
- * We need to wrap each managerEntry with a try-catch because if we do not, a failing managerEntry can stop execution of other managerEntries.
+ * We need to wrap each managerEntry with a try-catch because if we do not, a failing managerEntry
+ * can stop execution of other managerEntries.
*/
export async function wrapManagerEntries(entrypoints: string[], uniqueId?: string) {
return Promise.all(
diff --git a/code/core/src/channels/index.ts b/code/core/src/channels/index.ts
index ab2d311b097f..58e992b98580 100644
--- a/code/core/src/channels/index.ts
+++ b/code/core/src/channels/index.ts
@@ -21,9 +21,11 @@ type Options = Config & {
/**
* Creates a new browser channel instance.
+ *
* @param {Options} options - The options object.
- * @param {Page} options.page - page identifier.
- * @param {ChannelTransport[]} [options.extraTransports=[]] - An optional array of extra channel transports.
+ * @param {Page} options.page - Page identifier.
+ * @param {ChannelTransport[]} [options.extraTransports=[]] - An optional array of extra channel
+ * transports. Default is `[]`
* @returns {Channel} - The new channel instance.
*/
export function createBrowserChannel({ page, extraTransports = [] }: Options): Channel {
diff --git a/code/core/src/channels/postmessage/index.ts b/code/core/src/channels/postmessage/index.ts
index a60ba16a47b4..f7ae1d72b1a5 100644
--- a/code/core/src/channels/postmessage/index.ts
+++ b/code/core/src/channels/postmessage/index.ts
@@ -58,8 +58,9 @@ export class PostMessageTransport implements ChannelTransport {
}
/**
- * Sends `event` to the associated window. If the window does not yet exist
- * the event will be stored in a buffer and sent when the window exists.
+ * Sends `event` to the associated window. If the window does not yet exist the event will be
+ * stored in a buffer and sent when the window exists.
+ *
* @param event
*/
send(event: ChannelEvent, options?: any): Promise {
diff --git a/code/core/src/cli/bin/index.ts b/code/core/src/cli/bin/index.ts
index 38cbce23efb1..20cc55c1d809 100644
--- a/code/core/src/cli/bin/index.ts
+++ b/code/core/src/cli/bin/index.ts
@@ -4,7 +4,7 @@ import { addToGlobalContext } from '@storybook/core/telemetry';
import { logger } from '@storybook/core/node-logger';
import chalk from 'chalk';
-import program from 'commander';
+import { program } from 'commander';
import { findPackageSync } from 'fd-package-json';
import leven from 'leven';
import invariant from 'tiny-invariant';
@@ -69,7 +69,7 @@ command('dev')
'URL path to be appended when visiting Storybook for the first time'
)
.action(async (options) => {
- logger.setLevel(program.loglevel);
+ logger.setLevel(options.loglevel);
consoleLogger.log(chalk.bold(`${pkg.name} v${pkg.version}`) + chalk.reset('\n'));
// The key is the field created in `options` variable for
@@ -109,7 +109,7 @@ command('build')
.option('--test', 'Build stories optimized for testing purposes.')
.action(async (options) => {
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
- logger.setLevel(program.loglevel);
+ logger.setLevel(options.loglevel);
consoleLogger.log(chalk.bold(`${pkg.name} v${pkg.version}\n`));
// The key is the field created in `options` variable for
@@ -132,8 +132,7 @@ program.on('command:*', ([invalidCmd]) => {
' Invalid command: %s.\n See --help for a list of available commands.',
invalidCmd
);
- // eslint-disable-next-line no-underscore-dangle
- const availableCommands = program.commands.map((cmd) => cmd._name);
+ const availableCommands = program.commands.map((cmd) => cmd.name());
const suggestion = availableCommands.find((cmd) => leven(cmd, invalidCmd) < 3);
if (suggestion) {
consoleLogger.info(`\n Did you mean ${suggestion}?`);
diff --git a/code/core/src/cli/detect.ts b/code/core/src/cli/detect.ts
index 96ab4c785cee..09ef8cae02cf 100644
--- a/code/core/src/cli/detect.ts
+++ b/code/core/src/cli/detect.ts
@@ -107,8 +107,8 @@ export function detectFrameworkPreset(
}
/**
- * Attempts to detect which builder to use, by searching for a vite config file or webpack installation.
- * If neither are found it will choose the default builder based on the project type.
+ * Attempts to detect which builder to use, by searching for a vite config file or webpack
+ * installation. If neither are found it will choose the default builder based on the project type.
*
* @returns CoreBuilder
*/
diff --git a/code/core/src/cli/eslintPlugin.ts b/code/core/src/cli/eslintPlugin.ts
index 53371725f84a..4b8d47b293a2 100644
--- a/code/core/src/cli/eslintPlugin.ts
+++ b/code/core/src/cli/eslintPlugin.ts
@@ -51,9 +51,17 @@ export async function extractEslintInfo(packageManager: JsPackageManager): Promi
}
export const normalizeExtends = (existingExtends: any): string[] => {
- if (!existingExtends) return [];
- if (typeof existingExtends === 'string') return [existingExtends];
- if (Array.isArray(existingExtends)) return existingExtends;
+ if (!existingExtends) {
+ return [];
+ }
+
+ if (typeof existingExtends === 'string') {
+ return [existingExtends];
+ }
+
+ if (Array.isArray(existingExtends)) {
+ return existingExtends;
+ }
throw new Error(`Invalid eslint extends ${existingExtends}`);
};
diff --git a/code/core/src/cli/helpers.ts b/code/core/src/cli/helpers.ts
index 5970a1276237..355e142cece1 100644
--- a/code/core/src/cli/helpers.ts
+++ b/code/core/src/cli/helpers.ts
@@ -18,7 +18,7 @@ import stripJsonComments from 'strip-json-comments';
import invariant from 'tiny-invariant';
import { getRendererDir } from './dirs';
-import { CoreBuilder, SupportedLanguage } from './project_types';
+import { CommunityBuilder, CoreBuilder, SupportedLanguage } from './project_types';
const logger = console;
@@ -50,17 +50,25 @@ export const writeFileAsJson = (jsonPath: string, content: unknown) => {
};
/**
- * Detect if any babel dependencies need to be added to the project
- * This is currently used by react-native generator
- * @param {Object} packageJson The current package.json so we can inspect its contents
- * @returns {Array} Contains the packages and versions that need to be installed
+ * Detect if any babel dependencies need to be added to the project This is currently used by
+ * react-native generator
+ *
* @example
- * const babelDependencies = await getBabelDependencies(packageManager, npmOptions, packageJson);
- * // you can then spread the result when using installDependencies
+ *
+ * ```ts
+ * const babelDependencies = await getBabelDependencies(
+ * packageManager,
+ * npmOptions,
+ * packageJson
+ * ); // you can then spread the result when using installDependencies
* installDependencies(npmOptions, [
* `@storybook/react@${storybookVersion}`,
* ...babelDependencies,
* ]);
+ * ```
+ *
+ * @param {Object} packageJson The current package.json so we can inspect its contents
+ * @returns {Array} Contains the packages and versions that need to be installed
*/
export async function getBabelDependencies(
packageManager: JsPackageManager,
@@ -133,12 +141,13 @@ type CopyTemplateFilesOptions = {
destination?: string;
};
-/**
- * @deprecated Please use `frameworkToRenderer` from `@storybook/core-common` instead
- */
+/** @deprecated Please use `frameworkToRenderer` from `@storybook/core-common` instead */
export const frameworkToRenderer = CoreFrameworkToRenderer;
-export const frameworkToDefaultBuilder: Record = {
+export const frameworkToDefaultBuilder: Record<
+ SupportedFrameworks,
+ CoreBuilder | CommunityBuilder
+> = {
angular: CoreBuilder.Webpack5,
ember: CoreBuilder.Webpack5,
'html-vite': CoreBuilder.Vite,
@@ -159,6 +168,9 @@ export const frameworkToDefaultBuilder: Record
'vue3-webpack5': CoreBuilder.Webpack5,
'web-components-vite': CoreBuilder.Vite,
'web-components-webpack5': CoreBuilder.Webpack5,
+ // Only to pass type checking, will never be used
+ 'react-rsbuild': CommunityBuilder.Rsbuild,
+ 'vue3-rsbuild': CommunityBuilder.Rsbuild,
};
export async function copyTemplateFiles({
@@ -224,8 +236,11 @@ export async function copyTemplateFiles({
if (commonAssetsDir) {
let rendererType = frameworkToRenderer[renderer] || 'react';
+
// This is only used for docs links and the docs site uses `vue` for both `vue` & `vue3` renderers
- if (rendererType === 'vue3') rendererType = 'vue';
+ if (rendererType === 'vue3') {
+ rendererType = 'vue';
+ }
await adjustTemplate(join(destinationPath, 'Configure.mdx'), { renderer: rendererType });
}
}
diff --git a/code/core/src/cli/project_types.ts b/code/core/src/cli/project_types.ts
index 1efeba6cc52f..5d7d4a4d3ead 100644
--- a/code/core/src/cli/project_types.ts
+++ b/code/core/src/cli/project_types.ts
@@ -26,9 +26,7 @@ export const externalFrameworks: ExternalFramework[] = [
{ name: 'solid', frameworks: ['storybook-solidjs-vite'], renderer: 'storybook-solidjs' },
];
-/**
- * @deprecated Please use `SupportedFrameworks` from `@storybook/types` instead
- */
+/** @deprecated Please use `SupportedFrameworks` from `@storybook/types` instead */
export type SupportedRenderers = CoreSupportedFrameworks;
export const SUPPORTED_RENDERERS: SupportedRenderers[] = [
@@ -76,6 +74,10 @@ export enum CoreWebpackCompilers {
SWC = 'swc',
}
+export enum CommunityBuilder {
+ Rsbuild = 'rsbuild',
+}
+
export const compilerNameToCoreCompiler: Record = {
'@storybook/addon-webpack5-compiler-babel': CoreWebpackCompilers.Babel,
'@storybook/addon-webpack5-compiler-swc': CoreWebpackCompilers.SWC,
@@ -103,7 +105,7 @@ export type TemplateMatcher = {
export type TemplateConfiguration = {
preset: ProjectType;
- /** will be checked both against dependencies and devDependencies */
+ /** Will be checked both against dependencies and devDependencies */
dependencies?: string[] | { [dependency: string]: (version: string) => boolean };
peerDependencies?: string[] | { [dependency: string]: (version: string) => boolean };
files?: string[];
@@ -113,9 +115,9 @@ export type TemplateConfiguration = {
/**
* Configuration to match a storybook preset template.
*
- * This has to be an array sorted in order of specificity/priority.
- * Reason: both REACT and WEBPACK_REACT have react as dependency,
- * therefore WEBPACK_REACT has to come first, as it's more specific.
+ * This has to be an array sorted in order of specificity/priority. Reason: both REACT and
+ * WEBPACK_REACT have react as dependency, therefore WEBPACK_REACT has to come first, as it's more
+ * specific.
*/
export const supportedTemplates: TemplateConfiguration[] = [
{
diff --git a/code/core/src/client-logger/index.ts b/code/core/src/client-logger/index.ts
index 7eee3a6eb33f..92b60a42e674 100644
--- a/code/core/src/client-logger/index.ts
+++ b/code/core/src/client-logger/index.ts
@@ -57,7 +57,9 @@ const logged = new Set();
export const once =
(type: keyof typeof logger) =>
(message: any, ...rest: any[]) => {
- if (logged.has(message)) return undefined;
+ if (logged.has(message)) {
+ return undefined;
+ }
logged.add(message);
return logger[type](message, ...rest);
};
diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts
index d126db20aa8a..4b3e00c2f5e7 100644
--- a/code/core/src/common/js-package-manager/JsPackageManager.ts
+++ b/code/core/src/common/js-package-manager/JsPackageManager.ts
@@ -24,7 +24,7 @@ type StorybookPackage = keyof typeof storybookPackagesVersions;
* Extract package name and version from input
*
* @param pkg A string like `@storybook/cli`, `react` or `react@^16`
- * @return A tuple of 2 elements: [packageName, packageVersion]
+ * @returns A tuple of 2 elements: [packageName, packageVersion]
*/
export function getPackageDetails(pkg: string): [string, string?] {
const idx = pkg.lastIndexOf('@');
@@ -57,9 +57,7 @@ export abstract class JsPackageManager {
basePath?: string
): Promise;
- /**
- * Get the INSTALLED version of a package from the package.json file
- */
+ /** Get the INSTALLED version of a package from the package.json file */
async getPackageVersion(packageName: string, basePath = this.cwd): Promise {
const packageJSON = await this.getPackageJSON(packageName, basePath);
return packageJSON ? packageJSON.version ?? null : null;
@@ -69,9 +67,11 @@ export abstract class JsPackageManager {
this.cwd = options?.cwd || process.cwd();
}
- /** Detect whether Storybook gets initialized in a monorepository/workspace environment
- * The cwd doesn't have to be the root of the monorepo, it can be a subdirectory
- * @returns true, if Storybook is initialized inside a monorepository/workspace
+ /**
+ * Detect whether Storybook gets initialized in a mono-repository/workspace environment The cwd
+ * doesn't have to be the root of the monorepo, it can be a subdirectory
+ *
+ * @returns `true`, if Storybook is initialized inside a mono-repository/workspace
*/
public isStorybookInMonorepo() {
let cwd = process.cwd();
@@ -113,9 +113,7 @@ export abstract class JsPackageManager {
return false;
}
- /**
- * Install dependencies listed in `package.json`
- */
+ /** Install dependencies listed in `package.json` */
public async installDependencies() {
logger.log('Installing dependencies...');
logger.log();
@@ -172,8 +170,8 @@ export abstract class JsPackageManager {
}
/**
- * Read the `package.json` file available in the directory the command was call from
- * If there is no `package.json` it will create one.
+ * Read the `package.json` file available in the directory the command was call from If there is
+ * no `package.json` it will create one.
*/
public async retrievePackageJson(): Promise {
let packageJson;
@@ -215,15 +213,20 @@ export abstract class JsPackageManager {
/**
* Add dependencies to a project using `yarn add` or `npm install`.
*
- * @param {Object} options contains `skipInstall`, `packageJson` and `installAsDevDependencies` which we use to determine how we install packages.
- * @param {Array} dependencies contains a list of packages to add.
* @example
+ *
+ * ```ts
* addDependencies(options, [
* `@storybook/react@${storybookVersion}`,
* `@storybook/addon-actions@${actionsVersion}`,
* `@storybook/addon-links@${linksVersion}`,
* `@storybook/preview-api@${addonsVersion}`,
* ]);
+ * ```
+ *
+ * @param {Object} options Contains `skipInstall`, `packageJson` and `installAsDevDependencies`
+ * which we use to determine how we install packages.
+ * @param {Array} dependencies Contains a list of packages to add.
*/
public async addDependencies(
options: {
@@ -270,13 +273,15 @@ export abstract class JsPackageManager {
/**
* Remove dependencies from a project using `yarn remove` or `npm uninstall`.
*
- * @param {Object} options contains `skipInstall`, `packageJson` and `installAsDevDependencies` which we use to determine how we install packages.
- * @param {Array} dependencies contains a list of packages to remove.
* @example
- * removeDependencies(options, [
- * `@storybook/react`,
- * `@storybook/addon-actions`,
- * ]);
+ *
+ * ```ts
+ * removeDependencies(options, [`@storybook/react`, `@storybook/addon-actions`]);
+ * ```
+ *
+ * @param {Object} options Contains `skipInstall`, `packageJson` and `installAsDevDependencies`
+ * which we use to determine how we install packages.
+ * @param {Array} dependencies Contains a list of packages to remove.
*/
public async removeDependencies(
options: {
@@ -315,10 +320,11 @@ export abstract class JsPackageManager {
/**
* Return an array of strings matching following format: `@`
*
- * For packages in the storybook monorepo, when the latest version is equal to the version of the current CLI
- * the version is not added to the string.
+ * For packages in the storybook monorepo, when the latest version is equal to the version of the
+ * current CLI the version is not added to the string.
*
- * When a package is in the monorepo, and the version is not equal to the CLI version, the version is taken from the versions.ts file and added to the string.
+ * When a package is in the monorepo, and the version is not equal to the CLI version, the version
+ * is taken from the versions.ts file and added to the string.
*
* @param packages
*/
@@ -343,8 +349,8 @@ export abstract class JsPackageManager {
}
/**
- * Return an array of string standing for the latest version of the input packages.
- * To be able to identify which version goes with which package the order of the input array is keep.
+ * Return an array of string standing for the latest version of the input packages. To be able to
+ * identify which version goes with which package the order of the input array is keep.
*
* @param packageNames
*/
@@ -357,10 +363,11 @@ export abstract class JsPackageManager {
}
/**
- * Return the latest version of the input package available on npmjs registry.
- * If constraint are provided it return the latest version matching the constraints.
+ * Return the latest version of the input package available on npmjs registry. If constraint are
+ * provided it return the latest version matching the constraints.
*
- * For `@storybook/*` packages the latest version is retrieved from `cli/src/versions.json` file directly
+ * For `@storybook/*` packages the latest version is retrieved from `cli/src/versions.json` file
+ * directly
*
* @param packageName The name of the package
* @param constraint A valid semver constraint, example: '1.x || >=2.5.0 || 5.0.0 - 7.2.3'
@@ -393,8 +400,8 @@ export abstract class JsPackageManager {
}
/**
- * Get the latest version of the package available on npmjs.com.
- * If constraint is set then it returns a version satisfying it, otherwise the latest version available is returned.
+ * Get the latest version of the package available on npmjs.com. If constraint is set then it
+ * returns a version satisfying it, otherwise the latest version available is returned.
*
* @param packageName Name of the package
* @param constraint Version range to use to constraint the returned version
@@ -526,9 +533,7 @@ export abstract class JsPackageManager {
}
}
- /**
- * Returns the installed (within node_modules or pnp zip) version of a specified package
- */
+ /** Returns the installed (within node_modules or pnp zip) version of a specified package */
public async getInstalledVersion(packageName: string): Promise {
const installations = await this.findInstallations([packageName]);
if (!installations) {
diff --git a/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts b/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts
index 0b09f57bac52..7477a1e5f2c0 100644
--- a/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts
+++ b/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts
@@ -88,9 +88,7 @@ export class JsPackageManagerFactory {
throw new Error('Unable to find a usable package manager within NPM, PNPM, Yarn and Yarn 2');
}
- /**
- * Look up map of package manager proxies by name
- */
+ /** Look up map of package manager proxies by name */
private static PROXY_MAP: Record = {
npm: NPMProxy,
pnpm: PNPMProxy,
@@ -99,8 +97,8 @@ export class JsPackageManagerFactory {
};
/**
- * Infer the package manager based on the command the user is running.
- * Each package manager sets the `npm_config_user_agent` environment variable with its name and version e.g. "npm/7.24.0"
+ * Infer the package manager based on the command the user is running. Each package manager sets
+ * the `npm_config_user_agent` environment variable with its name and version e.g. "npm/7.24.0"
* Which is really useful when invoking commands via npx/pnpx/yarn create/etc.
*/
private static inferPackageManagerFromUserAgent(): PackageManagerName | undefined {
diff --git a/code/core/src/common/js-package-manager/NPMProxy.ts b/code/core/src/common/js-package-manager/NPMProxy.ts
index 1347a4a124d3..44bccfdb4cb9 100644
--- a/code/core/src/common/js-package-manager/NPMProxy.ts
+++ b/code/core/src/common/js-package-manager/NPMProxy.ts
@@ -264,7 +264,6 @@ export class NPMProxy extends JsPackageManager {
}
/**
- *
* @param input The output of `npm ls --json`
* @param pattern A list of package names to filter the result. * can be used as a placeholder
*/
diff --git a/code/core/src/common/presets.ts b/code/core/src/common/presets.ts
index 5651aa3e6a1f..c578b0502889 100644
--- a/code/core/src/common/presets.ts
+++ b/code/core/src/common/presets.ts
@@ -68,17 +68,12 @@ function resolvePresetFunction(
* Parse an addon into either a managerEntries or a preset. Throw on invalid input.
*
* Valid inputs:
- * - '@storybook/addon-actions/manager'
- * => { type: 'virtual', item }
*
- * - '@storybook/addon-docs/preset'
- * => { type: 'presets', item }
- *
- * - '@storybook/addon-docs'
- * => { type: 'presets', item: '@storybook/addon-docs/preset' }
- *
- * - { name: '@storybook/addon-docs(/preset)?', options: { ... } }
- * => { type: 'presets', item: { name: '@storybook/addon-docs/preset', options } }
+ * - `'@storybook/addon-actions/manager' => { type: 'virtual', item }`
+ * - `'@storybook/addon-docs/preset' => { type: 'presets', item }`
+ * - `'@storybook/addon-docs' => { type: 'presets', item: '@storybook/addon-docs/preset' }`
+ * - `{ name: '@storybook/addon-docs(/preset)?', options: { } } => { type: 'presets', item: { name:
+ * '@storybook/addon-docs/preset', options } }`
*/
export const resolveAddonName = (
@@ -111,16 +106,19 @@ export const resolveAddonName = (
}
const checkExists = (exportName: string) => {
- if (resolve(`${name}${exportName}`)) return `${name}${exportName}`;
+ if (resolve(`${name}${exportName}`)) {
+ return `${name}${exportName}`;
+ }
return undefined;
};
- // This is used to maintain back-compat with community addons that do not
- // re-export their sub-addons but reference the sub-addon name directly.
- // We need to turn it into an absolute path so that webpack can
- // serve it up correctly when yarn pnp or pnpm is being used.
- // Vite will be broken in such cases, because it does not process absolute paths,
- // and it will try to import from the bare import, breaking in pnp/pnpm.
+ /**
+ * This is used to maintain back-compat with community addons that do not re-export their
+ * sub-addons but reference the sub-addon name directly. We need to turn it into an absolute path
+ * so that webpack can serve it up correctly when yarn pnp or pnpm is being used. Vite will be
+ * broken in such cases, because it does not process absolute paths, and it will try to import
+ * from the bare import, breaking in pnp/pnpm.
+ */
const absolutizeExport = (exportName: string, preferMJS: boolean) => {
const found = resolve(`${name}${exportName}`);
diff --git a/code/core/src/common/utils/HandledError.ts b/code/core/src/common/utils/HandledError.ts
index 429d9620df3a..223861ee7b77 100644
--- a/code/core/src/common/utils/HandledError.ts
+++ b/code/core/src/common/utils/HandledError.ts
@@ -4,6 +4,8 @@ export class HandledError extends Error {
constructor(error: unknown) {
super(String(error));
- if (typeof error !== 'string') this.cause = error;
+ if (typeof error !== 'string') {
+ this.cause = error;
+ }
}
}
diff --git a/code/core/src/common/utils/__tests__/check-addon-order.test.ts b/code/core/src/common/utils/__tests__/check-addon-order.test.ts
index c9f67ffd3631..5e7c0a43a106 100644
--- a/code/core/src/common/utils/__tests__/check-addon-order.test.ts
+++ b/code/core/src/common/utils/__tests__/check-addon-order.test.ts
@@ -25,7 +25,9 @@ const essentialAddons = [
const pkgName = (entry: CoreCommon_AddonEntry): string => {
if (typeof entry === 'string') {
- if (entry.includes('node_modules')) return entry;
+ if (entry.includes('node_modules')) {
+ return entry;
+ }
return `@storybook/addon-${entry}`;
}
return (entry as CoreCommon_OptionsEntry).name;
diff --git a/code/core/src/common/utils/check-addon-order.ts b/code/core/src/common/utils/check-addon-order.ts
index 0922a8cce447..9d8f72669e0f 100644
--- a/code/core/src/common/utils/check-addon-order.ts
+++ b/code/core/src/common/utils/check-addon-order.ts
@@ -26,8 +26,14 @@ const isCorrectOrder = (
const essentialsIndex = addons.findIndex(predicateFor('@storybook/addon-essentials'));
let beforeIndex = addons.findIndex(predicateFor(before.name));
let afterIndex = addons.findIndex(predicateFor(after.name));
- if (beforeIndex === -1 && before.inEssentials) beforeIndex = essentialsIndex;
- if (afterIndex === -1 && after.inEssentials) afterIndex = essentialsIndex;
+
+ if (beforeIndex === -1 && before.inEssentials) {
+ beforeIndex = essentialsIndex;
+ }
+
+ if (afterIndex === -1 && after.inEssentials) {
+ afterIndex = essentialsIndex;
+ }
return beforeIndex !== -1 && afterIndex !== -1 && beforeIndex <= afterIndex;
};
diff --git a/code/core/src/common/utils/cli.ts b/code/core/src/common/utils/cli.ts
index 5061d81905c3..00b831133d2a 100644
--- a/code/core/src/common/utils/cli.ts
+++ b/code/core/src/common/utils/cli.ts
@@ -24,22 +24,22 @@ export async function temporaryDirectory({ prefix = '' } = {}) {
export type FileOptions = MergeExclusive<
{
/**
- File extension.
-
- Mutually exclusive with the `name` option.
-
- _You usually won't need this option. Specify it only when actually needed._
- */
+ * File extension.
+ *
+ * Mutually exclusive with the `name` option.
+ *
+ * _You usually won't need this option. Specify it only when actually needed._
+ */
readonly extension?: string;
},
{
/**
- Filename.
-
- Mutually exclusive with the `extension` option.
-
- _You usually won't need this option. Specify it only when actually needed._
- */
+ * Filename.
+ *
+ * Mutually exclusive with the `extension` option.
+ *
+ * _You usually won't need this option. Specify it only when actually needed._
+ */
readonly name?: string;
}
>;
@@ -67,10 +67,10 @@ export function parseList(str: string): string[] {
}
/**
- * Given a package manager, returns the coerced version of Storybook.
- * It tries to find renderer packages in the project and returns the coerced version of the first one found.
- * Example:
- * If @storybook/react version 8.0.0-alpha.14 is installed, it returns the coerced version 8.0.0
+ * Given a package manager, returns the coerced version of Storybook. It tries to find renderer
+ * packages in the project and returns the coerced version of the first one found. Example: If
+ *
+ * @storybook/react version 8.0.0-alpha.14 is installed, it returns the coerced version 8.0.0
*/
export async function getCoercedStorybookVersion(packageManager: JsPackageManager) {
const packages = (
@@ -96,37 +96,38 @@ export function getEnvConfig(program: Record, configEnv: Record {
try {
diff --git a/code/core/src/common/utils/framework-to-renderer.ts b/code/core/src/common/utils/framework-to-renderer.ts
index 63107ad8313b..1dd1fa0b811e 100644
--- a/code/core/src/common/utils/framework-to-renderer.ts
+++ b/code/core/src/common/utils/framework-to-renderer.ts
@@ -26,6 +26,8 @@ export const frameworkToRenderer: Record<
'vue3-webpack5': 'vue3',
'web-components-vite': 'web-components',
'web-components-webpack5': 'web-components',
+ 'react-rsbuild': 'react',
+ 'vue3-rsbuild': 'vue3',
// renderers
html: 'html',
preact: 'preact',
diff --git a/code/core/src/common/utils/get-framework-name.ts b/code/core/src/common/utils/get-framework-name.ts
index b4fcc57ee344..25b45b772bd9 100644
--- a/code/core/src/common/utils/get-framework-name.ts
+++ b/code/core/src/common/utils/get-framework-name.ts
@@ -5,9 +5,7 @@ import { dedent } from 'ts-dedent';
import { frameworkPackages } from './get-storybook-info';
import { normalizePath } from './normalize-path';
-/**
- * Framework can be a string or an object. This utility always returns the string name.
- */
+/** Framework can be a string or an object. This utility always returns the string name. */
export async function getFrameworkName(options: Options) {
const framework = await options.presets.apply('framework', '', options);
@@ -23,11 +21,15 @@ export async function getFrameworkName(options: Options) {
}
/**
- * Extracts the proper framework name from the given framework field.
- * The framework field can be the framework package name or a path to the framework package.
+ * Extracts the proper framework name from the given framework field. The framework field can be the
+ * framework package name or a path to the framework package.
+ *
* @example
- * extractProperFrameworkName('/path/to/@storybook/angular') // => '@storybook/angular'
- * extractProperFrameworkName('@third-party/framework') // => '@third-party/framework'
+ *
+ * ```ts
+ * ExtractProperFrameworkName('/path/to/@storybook/angular'); // => '@storybook/angular'
+ * extractProperFrameworkName('@third-party/framework'); // => '@third-party/framework'
+ * ```
*/
export const extractProperFrameworkName = (framework: string) => {
const normalizedPath = normalizePath(framework);
diff --git a/code/core/src/common/utils/get-renderer-name.ts b/code/core/src/common/utils/get-renderer-name.ts
index 867fa94f3775..75e95f76411f 100644
--- a/code/core/src/common/utils/get-renderer-name.ts
+++ b/code/core/src/common/utils/get-renderer-name.ts
@@ -5,8 +5,8 @@ import { extractProperFrameworkName, getFrameworkName } from './get-framework-na
import { frameworkPackages } from './get-storybook-info';
/**
- * Render is set as a string on core. It must be set by the framework
- * It falls back to the framework name if not set
+ * Render is set as a string on core. It must be set by the framework It falls back to the framework
+ * name if not set
*/
export async function getRendererName(options: Options) {
const core = await options.presets.apply('core', {}, options);
@@ -22,12 +22,17 @@ export async function getRendererName(options: Options) {
/**
* Extracts the proper renderer name from the given framework name.
+ *
+ * @example
+ *
+ * ```ts
+ * extractProperRendererNameFromFramework('@storybook/react'); // => 'react'
+ * extractProperRendererNameFromFramework('@storybook/angular'); // => 'angular'
+ * extractProperRendererNameFromFramework('@third-party/framework'); // => null
+ * ```
+ *
* @param frameworkName The name of the framework.
* @returns The name of the renderer.
- * @example
- * extractProperRendererNameFromFramework('@storybook/react') // => 'react'
- * extractProperRendererNameFromFramework('@storybook/angular') // => 'angular'
- * extractProperRendererNameFromFramework('@third-party/framework') // => null
*/
export async function extractProperRendererNameFromFramework(frameworkName: string) {
const extractedFrameworkName = extractProperFrameworkName(frameworkName);
diff --git a/code/core/src/common/utils/get-storybook-info.ts b/code/core/src/common/utils/get-storybook-info.ts
index e86281caad8e..af65546949eb 100644
--- a/code/core/src/common/utils/get-storybook-info.ts
+++ b/code/core/src/common/utils/get-storybook-info.ts
@@ -23,9 +23,7 @@ export const rendererPackages: Record = {
'storybook-framework-qwik': 'qwik',
'storybook-solidjs': 'solid',
- /**
- * @deprecated This is deprecated.
- */
+ /** @deprecated This is deprecated. */
'@storybook/vue': 'vue',
};
@@ -50,6 +48,8 @@ export const frameworkPackages: Record = {
// community (outside of monorepo)
'storybook-framework-qwik': 'qwik',
'storybook-solidjs-vite': 'solid',
+ 'storybook-react-rsbuild': 'react-rsbuild',
+ 'storybook-vue3-rsbuild': 'vue3-rsbuild',
};
export const builderPackages = ['@storybook/builder-webpack5', '@storybook/builder-vite'];
@@ -103,7 +103,10 @@ export const getConfigInfo = (packageJson: PackageJson, configDir?: string) => {
const storybookScript = packageJson.scripts?.storybook;
if (storybookScript && !configDir) {
const configParam = getStorybookConfiguration(storybookScript, '-c', '--config-dir');
- if (configParam) storybookConfigDir = configParam;
+
+ if (configParam) {
+ storybookConfigDir = configParam;
+ }
}
return {
diff --git a/code/core/src/common/utils/interpolate.ts b/code/core/src/common/utils/interpolate.ts
index 43e826efc35f..2ebdcf92a916 100644
--- a/code/core/src/common/utils/interpolate.ts
+++ b/code/core/src/common/utils/interpolate.ts
@@ -1,9 +1,10 @@
/**
- * Return a string corresponding to template filled with bindings using following pattern:
- * For each (key, value) of `bindings` replace, in template, `{{key}}` by escaped version of `value`
+ * Return a string corresponding to template filled with bindings using following pattern: For each
+ * (key, value) of `bindings` replace, in template, `{{key}}` by escaped version of `value`
*
* @param template {String} Template with `{{binding}}`
- * @param bindings {Object} key-value object use to fill the template, `{{key}}` will be replaced by `escaped(value)`
+ * @param bindings {Object} key-value object use to fill the template, `{{key}}` will be replaced by
+ * `escaped(value)`
* @returns {String} Filled template
*/
export const interpolate = (template: string, bindings: Record) => {
diff --git a/code/core/src/common/utils/normalize-path.ts b/code/core/src/common/utils/normalize-path.ts
index 18c6c00dd157..af96961f3bf5 100644
--- a/code/core/src/common/utils/normalize-path.ts
+++ b/code/core/src/common/utils/normalize-path.ts
@@ -2,12 +2,17 @@ import { posix } from 'node:path';
/**
* Normalize a path to use forward slashes and remove .. and .
+ *
+ * @example
+ *
+ * ```ts
+ * normalizePath('path/to/../file'); // => 'path/file'
+ * normalizePath('path/to/./file'); // => 'path/to/file'
+ * normalizePath('path\\to\\file'); // => 'path/to/file'
+ * ```
+ *
* @param p The path to normalize
* @returns The normalized path
- * @example
- * normalizePath('path/to/../file') // => 'path/file'
- * normalizePath('path/to/./file') // => 'path/to/file'
- * normalizePath('path\\to\\file') // => 'path/to/file'
*/
export function normalizePath(p: string) {
return posix.normalize(p.replace(/\\/g, '/'));
diff --git a/code/core/src/common/utils/paths.ts b/code/core/src/common/utils/paths.ts
index 9600f3028e1a..1117c5cffb71 100644
--- a/code/core/src/common/utils/paths.ts
+++ b/code/core/src/common/utils/paths.ts
@@ -60,11 +60,11 @@ export const nodePathsToArray = (nodePath: string) =>
.map((p) => resolve('./', p));
const relativePattern = /^\.{1,2}([/\\]|$)/;
-/**
- * Ensures that a path starts with `./` or `../`, or is entirely `.` or `..`
- */
+/** Ensures that a path starts with `./` or `../`, or is entirely `.` or `..` */
export function normalizeStoryPath(filename: string) {
- if (relativePattern.test(filename)) return filename;
+ if (relativePattern.test(filename)) {
+ return filename;
+ }
return `.${sep}${filename}`;
}
diff --git a/code/core/src/common/utils/posix.ts b/code/core/src/common/utils/posix.ts
index d4fbcc98b3cf..775787c965a8 100644
--- a/code/core/src/common/utils/posix.ts
+++ b/code/core/src/common/utils/posix.ts
@@ -1,7 +1,5 @@
import { posix as posixPath, sep } from 'node:path';
-/**
- * Replaces the path separator with forward slashes
- */
+/** Replaces the path separator with forward slashes */
export const posix = (localPath: string, seperator: string = sep) =>
localPath.split(seperator).filter(Boolean).join(posixPath.sep);
diff --git a/code/core/src/common/utils/remove.ts b/code/core/src/common/utils/remove.ts
index a1be0176cca2..033e193d5336 100644
--- a/code/core/src/common/utils/remove.ts
+++ b/code/core/src/common/utils/remove.ts
@@ -11,8 +11,11 @@ const logger = console;
/**
* Remove the given addon package and remove it from main.js
*
- * Usage:
- * - sb remove @storybook/addon-links
+ * @example
+ *
+ * ```sh
+ * sb remove @storybook/addon-links
+ * ```
*/
export async function removeAddon(
addon: string,
diff --git a/code/core/src/common/utils/resolve-path-in-sb-cache.ts b/code/core/src/common/utils/resolve-path-in-sb-cache.ts
index 3bd12c365c2f..0df3ed118e58 100644
--- a/code/core/src/common/utils/resolve-path-in-sb-cache.ts
+++ b/code/core/src/common/utils/resolve-path-in-sb-cache.ts
@@ -4,11 +4,12 @@ import findCacheDirectory from 'find-cache-dir';
/**
* Get the path of the file or directory with input name inside the Storybook cache directory:
- * - `node_modules/.cache/storybook/{directoryName}` in a Node.js project or npm package
- * - `.cache/storybook/{directoryName}` otherwise
+ *
+ * - `node_modules/.cache/storybook/{directoryName}` in a Node.js project or npm package
+ * - `.cache/storybook/{directoryName}` otherwise
*
* @param fileOrDirectoryName {string} Name of the file or directory
- * @return {string} Absolute path to the file or directory
+ * @returns {string} Absolute path to the file or directory
*/
export function resolvePathInStorybookCache(fileOrDirectoryName: string, sub = 'default'): string {
let cacheDirectory = findCacheDirectory({ name: 'storybook' });
diff --git a/code/core/src/common/utils/satisfies.ts b/code/core/src/common/utils/satisfies.ts
index 05207661f535..e97eaca00ebe 100644
--- a/code/core/src/common/utils/satisfies.ts
+++ b/code/core/src/common/utils/satisfies.ts
@@ -1,6 +1,4 @@
-/**
- * Mimicking the satisfies operator until we can upgrade to TS4.9
- */
+/** Mimicking the satisfies operator until we can upgrade to TS4.9 */
export function satisfies() {
return (x: T) => x;
}
diff --git a/code/core/src/common/versions.ts b/code/core/src/common/versions.ts
index 29d65729f4dc..f40354a0f1ee 100644
--- a/code/core/src/common/versions.ts
+++ b/code/core/src/common/versions.ts
@@ -1,87 +1,87 @@
// auto generated file, do not edit
export default {
- '@storybook/addon-a11y': '8.3.0-alpha.6',
- '@storybook/addon-actions': '8.3.0-alpha.6',
- '@storybook/addon-backgrounds': '8.3.0-alpha.6',
- '@storybook/addon-controls': '8.3.0-alpha.6',
- '@storybook/addon-docs': '8.3.0-alpha.6',
- '@storybook/addon-essentials': '8.3.0-alpha.6',
- '@storybook/addon-mdx-gfm': '8.3.0-alpha.6',
- '@storybook/addon-highlight': '8.3.0-alpha.6',
- '@storybook/addon-interactions': '8.3.0-alpha.6',
- '@storybook/addon-jest': '8.3.0-alpha.6',
- '@storybook/addon-links': '8.3.0-alpha.6',
- '@storybook/addon-measure': '8.3.0-alpha.6',
- '@storybook/addon-onboarding': '8.3.0-alpha.6',
- '@storybook/addon-outline': '8.3.0-alpha.6',
- '@storybook/addon-storysource': '8.3.0-alpha.6',
- '@storybook/addon-themes': '8.3.0-alpha.6',
- '@storybook/addon-toolbars': '8.3.0-alpha.6',
- '@storybook/addon-viewport': '8.3.0-alpha.6',
- '@storybook/experimental-addon-vitest': '8.3.0-alpha.6',
- '@storybook/builder-vite': '8.3.0-alpha.6',
- '@storybook/builder-webpack5': '8.3.0-alpha.6',
- '@storybook/core': '8.3.0-alpha.6',
- '@storybook/builder-manager': '8.3.0-alpha.6',
- '@storybook/channels': '8.3.0-alpha.6',
- '@storybook/client-logger': '8.3.0-alpha.6',
- '@storybook/components': '8.3.0-alpha.6',
- '@storybook/core-common': '8.3.0-alpha.6',
- '@storybook/core-events': '8.3.0-alpha.6',
- '@storybook/core-server': '8.3.0-alpha.6',
- '@storybook/csf-tools': '8.3.0-alpha.6',
- '@storybook/docs-tools': '8.3.0-alpha.6',
- '@storybook/manager': '8.3.0-alpha.6',
- '@storybook/manager-api': '8.3.0-alpha.6',
- '@storybook/node-logger': '8.3.0-alpha.6',
- '@storybook/preview': '8.3.0-alpha.6',
- '@storybook/preview-api': '8.3.0-alpha.6',
- '@storybook/router': '8.3.0-alpha.6',
- '@storybook/telemetry': '8.3.0-alpha.6',
- '@storybook/theming': '8.3.0-alpha.6',
- '@storybook/types': '8.3.0-alpha.6',
- '@storybook/angular': '8.3.0-alpha.6',
- '@storybook/ember': '8.3.0-alpha.6',
- '@storybook/experimental-nextjs-vite': '8.3.0-alpha.6',
- '@storybook/html-vite': '8.3.0-alpha.6',
- '@storybook/html-webpack5': '8.3.0-alpha.6',
- '@storybook/nextjs': '8.3.0-alpha.6',
- '@storybook/preact-vite': '8.3.0-alpha.6',
- '@storybook/preact-webpack5': '8.3.0-alpha.6',
- '@storybook/react-vite': '8.3.0-alpha.6',
- '@storybook/react-webpack5': '8.3.0-alpha.6',
- '@storybook/server-webpack5': '8.3.0-alpha.6',
- '@storybook/svelte-vite': '8.3.0-alpha.6',
- '@storybook/svelte-webpack5': '8.3.0-alpha.6',
- '@storybook/sveltekit': '8.3.0-alpha.6',
- '@storybook/vue3-vite': '8.3.0-alpha.6',
- '@storybook/vue3-webpack5': '8.3.0-alpha.6',
- '@storybook/web-components-vite': '8.3.0-alpha.6',
- '@storybook/web-components-webpack5': '8.3.0-alpha.6',
- '@storybook/blocks': '8.3.0-alpha.6',
- storybook: '8.3.0-alpha.6',
- sb: '8.3.0-alpha.6',
- '@storybook/cli': '8.3.0-alpha.6',
- '@storybook/codemod': '8.3.0-alpha.6',
- '@storybook/core-webpack': '8.3.0-alpha.6',
- 'create-storybook': '8.3.0-alpha.6',
- '@storybook/csf-plugin': '8.3.0-alpha.6',
- '@storybook/instrumenter': '8.3.0-alpha.6',
- '@storybook/react-dom-shim': '8.3.0-alpha.6',
- '@storybook/source-loader': '8.3.0-alpha.6',
- '@storybook/test': '8.3.0-alpha.6',
- '@storybook/preset-create-react-app': '8.3.0-alpha.6',
- '@storybook/preset-html-webpack': '8.3.0-alpha.6',
- '@storybook/preset-preact-webpack': '8.3.0-alpha.6',
- '@storybook/preset-react-webpack': '8.3.0-alpha.6',
- '@storybook/preset-server-webpack': '8.3.0-alpha.6',
- '@storybook/preset-svelte-webpack': '8.3.0-alpha.6',
- '@storybook/preset-vue3-webpack': '8.3.0-alpha.6',
- '@storybook/html': '8.3.0-alpha.6',
- '@storybook/preact': '8.3.0-alpha.6',
- '@storybook/react': '8.3.0-alpha.6',
- '@storybook/server': '8.3.0-alpha.6',
- '@storybook/svelte': '8.3.0-alpha.6',
- '@storybook/vue3': '8.3.0-alpha.6',
- '@storybook/web-components': '8.3.0-alpha.6',
+ '@storybook/addon-a11y': '8.3.0-alpha.7',
+ '@storybook/addon-actions': '8.3.0-alpha.7',
+ '@storybook/addon-backgrounds': '8.3.0-alpha.7',
+ '@storybook/addon-controls': '8.3.0-alpha.7',
+ '@storybook/addon-docs': '8.3.0-alpha.7',
+ '@storybook/addon-essentials': '8.3.0-alpha.7',
+ '@storybook/addon-mdx-gfm': '8.3.0-alpha.7',
+ '@storybook/addon-highlight': '8.3.0-alpha.7',
+ '@storybook/addon-interactions': '8.3.0-alpha.7',
+ '@storybook/addon-jest': '8.3.0-alpha.7',
+ '@storybook/addon-links': '8.3.0-alpha.7',
+ '@storybook/addon-measure': '8.3.0-alpha.7',
+ '@storybook/addon-onboarding': '8.3.0-alpha.7',
+ '@storybook/addon-outline': '8.3.0-alpha.7',
+ '@storybook/addon-storysource': '8.3.0-alpha.7',
+ '@storybook/addon-themes': '8.3.0-alpha.7',
+ '@storybook/addon-toolbars': '8.3.0-alpha.7',
+ '@storybook/addon-viewport': '8.3.0-alpha.7',
+ '@storybook/experimental-addon-vitest': '8.3.0-alpha.7',
+ '@storybook/builder-vite': '8.3.0-alpha.7',
+ '@storybook/builder-webpack5': '8.3.0-alpha.7',
+ '@storybook/core': '8.3.0-alpha.7',
+ '@storybook/builder-manager': '8.3.0-alpha.7',
+ '@storybook/channels': '8.3.0-alpha.7',
+ '@storybook/client-logger': '8.3.0-alpha.7',
+ '@storybook/components': '8.3.0-alpha.7',
+ '@storybook/core-common': '8.3.0-alpha.7',
+ '@storybook/core-events': '8.3.0-alpha.7',
+ '@storybook/core-server': '8.3.0-alpha.7',
+ '@storybook/csf-tools': '8.3.0-alpha.7',
+ '@storybook/docs-tools': '8.3.0-alpha.7',
+ '@storybook/manager': '8.3.0-alpha.7',
+ '@storybook/manager-api': '8.3.0-alpha.7',
+ '@storybook/node-logger': '8.3.0-alpha.7',
+ '@storybook/preview': '8.3.0-alpha.7',
+ '@storybook/preview-api': '8.3.0-alpha.7',
+ '@storybook/router': '8.3.0-alpha.7',
+ '@storybook/telemetry': '8.3.0-alpha.7',
+ '@storybook/theming': '8.3.0-alpha.7',
+ '@storybook/types': '8.3.0-alpha.7',
+ '@storybook/angular': '8.3.0-alpha.7',
+ '@storybook/ember': '8.3.0-alpha.7',
+ '@storybook/experimental-nextjs-vite': '8.3.0-alpha.7',
+ '@storybook/html-vite': '8.3.0-alpha.7',
+ '@storybook/html-webpack5': '8.3.0-alpha.7',
+ '@storybook/nextjs': '8.3.0-alpha.7',
+ '@storybook/preact-vite': '8.3.0-alpha.7',
+ '@storybook/preact-webpack5': '8.3.0-alpha.7',
+ '@storybook/react-vite': '8.3.0-alpha.7',
+ '@storybook/react-webpack5': '8.3.0-alpha.7',
+ '@storybook/server-webpack5': '8.3.0-alpha.7',
+ '@storybook/svelte-vite': '8.3.0-alpha.7',
+ '@storybook/svelte-webpack5': '8.3.0-alpha.7',
+ '@storybook/sveltekit': '8.3.0-alpha.7',
+ '@storybook/vue3-vite': '8.3.0-alpha.7',
+ '@storybook/vue3-webpack5': '8.3.0-alpha.7',
+ '@storybook/web-components-vite': '8.3.0-alpha.7',
+ '@storybook/web-components-webpack5': '8.3.0-alpha.7',
+ '@storybook/blocks': '8.3.0-alpha.7',
+ storybook: '8.3.0-alpha.7',
+ sb: '8.3.0-alpha.7',
+ '@storybook/cli': '8.3.0-alpha.7',
+ '@storybook/codemod': '8.3.0-alpha.7',
+ '@storybook/core-webpack': '8.3.0-alpha.7',
+ 'create-storybook': '8.3.0-alpha.7',
+ '@storybook/csf-plugin': '8.3.0-alpha.7',
+ '@storybook/instrumenter': '8.3.0-alpha.7',
+ '@storybook/react-dom-shim': '8.3.0-alpha.7',
+ '@storybook/source-loader': '8.3.0-alpha.7',
+ '@storybook/test': '8.3.0-alpha.7',
+ '@storybook/preset-create-react-app': '8.3.0-alpha.7',
+ '@storybook/preset-html-webpack': '8.3.0-alpha.7',
+ '@storybook/preset-preact-webpack': '8.3.0-alpha.7',
+ '@storybook/preset-react-webpack': '8.3.0-alpha.7',
+ '@storybook/preset-server-webpack': '8.3.0-alpha.7',
+ '@storybook/preset-svelte-webpack': '8.3.0-alpha.7',
+ '@storybook/preset-vue3-webpack': '8.3.0-alpha.7',
+ '@storybook/html': '8.3.0-alpha.7',
+ '@storybook/preact': '8.3.0-alpha.7',
+ '@storybook/react': '8.3.0-alpha.7',
+ '@storybook/server': '8.3.0-alpha.7',
+ '@storybook/svelte': '8.3.0-alpha.7',
+ '@storybook/vue3': '8.3.0-alpha.7',
+ '@storybook/web-components': '8.3.0-alpha.7',
};
diff --git a/code/core/src/components/components/Button/Button.tsx b/code/core/src/components/components/Button/Button.tsx
index 4e91549a9874..7c0c8db3da44 100644
--- a/code/core/src/components/components/Button/Button.tsx
+++ b/code/core/src/components/components/Button/Button.tsx
@@ -54,22 +54,35 @@ export const Button = forwardRef(
ref
) => {
let Comp: 'button' | 'a' | typeof Slot = 'button';
- if (props.isLink) Comp = 'a';
- if (asChild) Comp = Slot;
+
+ if (props.isLink) {
+ Comp = 'a';
+ }
+
+ if (asChild) {
+ Comp = Slot;
+ }
let localVariant = variant;
let localSize = size;
const [isAnimating, setIsAnimating] = useState(false);
const handleClick = (event: SyntheticEvent) => {
- if (onClick) onClick(event);
- if (animation === 'none') return;
+ if (onClick) {
+ onClick(event);
+ }
+
+ if (animation === 'none') {
+ return;
+ }
setIsAnimating(true);
};
useEffect(() => {
const timer = setTimeout(() => {
- if (isAnimating) setIsAnimating(false);
+ if (isAnimating) {
+ setIsAnimating(false);
+ }
}, 1000);
return () => clearTimeout(timer);
}, [isAnimating]);
@@ -146,10 +159,21 @@ const StyledButton = styled('button', {
justifyContent: 'center',
overflow: 'hidden',
padding: (() => {
- if (padding === 'small' && size === 'small') return '0 7px';
- if (padding === 'small' && size === 'medium') return '0 9px';
- if (size === 'small') return '0 10px';
- if (size === 'medium') return '0 12px';
+ if (padding === 'small' && size === 'small') {
+ return '0 7px';
+ }
+
+ if (padding === 'small' && size === 'medium') {
+ return '0 9px';
+ }
+
+ if (size === 'small') {
+ return '0 10px';
+ }
+
+ if (size === 'medium') {
+ return '0 12px';
+ }
return 0;
})(),
height: size === 'small' ? '28px' : '32px',
@@ -168,9 +192,17 @@ const StyledButton = styled('button', {
fontWeight: theme.typography.weight.bold,
lineHeight: '1',
background: (() => {
- if (variant === 'solid') return theme.color.secondary;
- if (variant === 'outline') return theme.button.background;
- if (variant === 'ghost' && active) return theme.background.hoverable;
+ if (variant === 'solid') {
+ return theme.color.secondary;
+ }
+
+ if (variant === 'outline') {
+ return theme.button.background;
+ }
+
+ if (variant === 'ghost' && active) {
+ return theme.background.hoverable;
+ }
return 'transparent';
})(),
...(variant === 'ghost'
@@ -179,11 +211,15 @@ const StyledButton = styled('button', {
// It is a temporary solution until we have implemented Theming 2.0.
'.sb-bar &': {
background: (() => {
- if (active) return transparentize(0.9, theme.barTextColor);
+ if (active) {
+ return transparentize(0.9, theme.barTextColor);
+ }
return 'transparent';
})(),
color: (() => {
- if (active) return theme.barSelectedColor;
+ if (active) {
+ return theme.barSelectedColor;
+ }
return theme.barTextColor;
})(),
'&:hover': {
@@ -204,10 +240,21 @@ const StyledButton = styled('button', {
}
: {}),
color: (() => {
- if (variant === 'solid') return theme.color.lightest;
- if (variant === 'outline') return theme.input.color;
- if (variant === 'ghost' && active) return theme.color.secondary;
- if (variant === 'ghost') return theme.color.mediumdark;
+ if (variant === 'solid') {
+ return theme.color.lightest;
+ }
+
+ if (variant === 'outline') {
+ return theme.input.color;
+ }
+
+ if (variant === 'ghost' && active) {
+ return theme.color.secondary;
+ }
+
+ if (variant === 'ghost') {
+ return theme.color.mediumdark;
+ }
return theme.input.color;
})(),
boxShadow: variant === 'outline' ? `${theme.button.border} 0 0 0 1px inset` : 'none',
@@ -219,10 +266,18 @@ const StyledButton = styled('button', {
color: variant === 'ghost' ? theme.color.secondary : undefined,
background: (() => {
let bgColor = theme.color.secondary;
- if (variant === 'solid') bgColor = theme.color.secondary;
- if (variant === 'outline') bgColor = theme.button.background;
- if (variant === 'ghost') return transparentize(0.86, theme.color.secondary);
+ if (variant === 'solid') {
+ bgColor = theme.color.secondary;
+ }
+
+ if (variant === 'outline') {
+ bgColor = theme.button.background;
+ }
+
+ if (variant === 'ghost') {
+ return transparentize(0.86, theme.color.secondary);
+ }
return theme.base === 'light' ? darken(0.02, bgColor) : lighten(0.03, bgColor);
})(),
},
@@ -231,10 +286,18 @@ const StyledButton = styled('button', {
color: variant === 'ghost' ? theme.color.secondary : undefined,
background: (() => {
let bgColor = theme.color.secondary;
- if (variant === 'solid') bgColor = theme.color.secondary;
- if (variant === 'outline') bgColor = theme.button.background;
- if (variant === 'ghost') return theme.background.hoverable;
+ if (variant === 'solid') {
+ bgColor = theme.color.secondary;
+ }
+
+ if (variant === 'outline') {
+ bgColor = theme.button.background;
+ }
+
+ if (variant === 'ghost') {
+ return theme.background.hoverable;
+ }
return theme.base === 'light' ? darken(0.02, bgColor) : lighten(0.03, bgColor);
})(),
},
diff --git a/code/core/src/components/components/Loader/Loader.tsx b/code/core/src/components/components/Loader/Loader.tsx
index e30812e27286..26d01ad3f05d 100644
--- a/code/core/src/components/components/Loader/Loader.tsx
+++ b/code/core/src/components/components/Loader/Loader.tsx
@@ -119,7 +119,10 @@ export const Loader = ({ progress, error, size, ...props }: LoaderProps) => {
if (progress) {
const { value, modules } = progress;
let { message } = progress;
- if (modules) message += ` ${modules.complete} / ${modules.total} modules`;
+
+ if (modules) {
+ message += ` ${modules.complete} / ${modules.total} modules`;
+ }
return (
({
height: 28,
}));
-/**
- * @deprecated
- * This component will be removed in Storybook 9.0
- * */
+/** @deprecated This component will be removed in Storybook 9.0 */
export const IconButtonSkeleton = () => (
diff --git a/code/core/src/components/components/form/input/input.tsx b/code/core/src/components/components/form/input/input.tsx
index 5e037b38fb4f..b32381ff107d 100644
--- a/code/core/src/components/components/form/input/input.tsx
+++ b/code/core/src/components/components/form/input/input.tsx
@@ -7,9 +7,9 @@ import { styled } from '@storybook/core/theming';
import TextareaAutoResize from 'react-textarea-autosize';
/**
- * these types are copied from `react-textarea-autosize`.
- * I copied them because of https://github.com/storybookjs/storybook/issues/18734
- * Maybe there's some bug in `tsup` or `react-textarea-autosize`?
+ * These types are copied from `react-textarea-autosize`. I copied them because of
+ * https://github.com/storybookjs/storybook/issues/18734 Maybe there's some bug in `tsup` or
+ * `react-textarea-autosize`?
*/
type TextareaPropsRaw = React.TextareaHTMLAttributes;
type Style = Omit, 'maxHeight' | 'minHeight'> & {
diff --git a/code/core/src/components/components/icon/icon.tsx b/code/core/src/components/components/icon/icon.tsx
index 9e2a52405cd5..bc9d447bec97 100644
--- a/code/core/src/components/components/icon/icon.tsx
+++ b/code/core/src/components/components/icon/icon.tsx
@@ -29,9 +29,9 @@ export interface IconsProps extends ComponentProps {
}
/**
- * @deprecated No longer used, will be removed in Storybook 9.0
- * Please use the `@storybook/icons` package instead.
- * */
+ * @deprecated No longer used, will be removed in Storybook 9.0 Please use the `@storybook/icons`
+ * package instead.
+ */
export const Icons = ({
icon,
useSymbol,
@@ -66,9 +66,9 @@ export interface SymbolsProps {
}
/**
- * @deprecated No longer used, will be removed in Storybook 9.0
- * Please use the `@storybook/icons` package instead.
- * */
+ * @deprecated No longer used, will be removed in Storybook 9.0 Please use the `@storybook/icons`
+ * package instead.
+ */
export const Symbols = memo(function Symbols({ icons: keys = Object.keys(icons) }) {
return (