Skip to content

Conversation

mrginglymus
Copy link
Contributor

@mrginglymus mrginglymus commented Sep 25, 2025

Re-opening #32396 as the target branch was deleted

What I did

Reasonably stable draft of an idea for a .each and .matrix function on csf4 factories to allow for efficient parametrization of tests.

Motivation is largely around chromatic usage - getting combinatorial coverage is currently a lot of C&P, even with things like extend and reusable play functions.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • New Features

    • Introduced parameterized story tests with each and matrix, generating multiple cases with dynamic, formatted names.
    • Supports per-case annotations and tags through static or function-based overrides.
    • Added example stories demonstrating multi-case testing.
  • Tests

    • Expanded coverage for tagging, discovery, naming, and execution of parameterized tests (each/matrix).
    • Updated indexer tests to include generated test entries.
  • Chores

    • Added a lightweight formatting dependency to support dynamic test name generation.

Copy link
Contributor

coderabbitai bot commented Sep 25, 2025

Walkthrough

Adds parameterized test support to CSF stories via new Story APIs: each and matrix. Updates csf-factories to generate multiple tests per parameter set, using fast-printf for label formatting. Extends CsfFile parsing to discover and expand A.each and A.matrix calls, including tag resolution from static values or inline functions, and validates/expands parameters (including cartesian product for matrix). Updates story indexer and multiple tests to cover discovery, naming, tagging, and execution. Adds new public types (EachTestParam, EachTestFunction, EachAnnotationsFunction) and re-exports them. Adds fast-printf as a dependency.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Author
  participant Story as Story (CSF)
  participant Factories as csf-factories
  participant Runtime as Runtime/Test Runner

  Author->>Story: define story
  Author->>Story: Story.each(name, rows[, annotations], testFn)
  Story->>Factories: create tests from rows
  Factories->>Factories: format names (fast-printf)
  Factories->>Runtime: register N tests with resolved annotations
  Runtime-->>Author: execute each test with mapped params
Loading
sequenceDiagram
  autonumber
  actor Author
  participant Story as Story (CSF)
  participant Factories as csf-factories
  participant CsfTools as CsfFile parser
  participant Indexer as Story Indexer

  Author->>Story: Story.matrix(name, matrix[, annotations], testFn)
  Story->>Factories: expand cartesian product
  Factories->>Factories: format names (fast-printf)
  Note over Factories: Generate one test per combination
  Factories->>Indexer: expose tests in story metadata
  Indexer->>CsfTools: parse CallExpressions (matrix/each)
  CsfTools->>CsfTools: validate params, resolve tags (incl. inline fns)
  CsfTools-->>Indexer: discovered tests with names/tags
Loading

Possibly related PRs

Suggested labels

feature request, csf, core

Suggested reviewers

  • yannbf
  • kylegach
  • jonniebigodes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly conveys the introduction of .each and .matrix testing capabilities for CSF, directly reflecting the PR’s main addition of parameterized test support without extraneous details.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

nx-cloud bot commented Sep 25, 2025

View your CI Pipeline Execution ↗ for commit a94138e

Command Status Duration Result
nx run-many -t build --parallel=3 ✅ Succeeded 54s View ↗

☁️ Nx Cloud last updated this comment at 2025-09-25 07:56:10 UTC

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
code/core/src/csf/csf-factories.ts (1)

29-31: Allow readonly tuples for matrix inputs.

Right now MatrixParams insists on mutable inner arrays, so a very common pattern such as
const matrix = [['A', 'B'], [1, 2]] as const; story.matrix(..., matrix, ...)
fails the constraint (readonly [...] ≠ mutable [...]). Switching the inner type to ReadonlyArray keeps the runtime behavior identical while letting consumers use as const/satisfies without casts.

-type MatrixParams<T extends EachTestParam[]> = {
-  [K in keyof T]: T[K][];
-};
+type MatrixParams<T extends EachTestParam[]> = {
+  [K in keyof T]: ReadonlyArray<T[K]>;
+};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e13905 and a94138e.

⛔ Files ignored due to path filters (1)
  • code/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (9)
  • code/core/package.json (1 hunks)
  • code/core/src/component-testing/components/test-fn.stories.tsx (1 hunks)
  • code/core/src/csf-tools/CsfFile.test.ts (1 hunks)
  • code/core/src/csf-tools/CsfFile.ts (4 hunks)
  • code/core/src/csf-tools/storyIndexer.test.ts (2 hunks)
  • code/core/src/csf/csf-factories.test.ts (1 hunks)
  • code/core/src/csf/csf-factories.ts (4 hunks)
  • code/core/src/csf/story.ts (1 hunks)
  • code/core/src/types/modules/csf.ts (1 hunks)
👮 Files not reviewed due to content moderation or server errors (1)
  • code/core/src/csf/story.ts
🧰 Additional context used
📓 Path-based instructions (2)
code/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

code/**/*.{test,spec}.{ts,tsx}: Place all test files under the code/ directory
Name test files as *.test.ts, *.test.tsx, *.spec.ts, or *.spec.tsx

Files:

  • code/core/src/csf/csf-factories.test.ts
  • code/core/src/csf-tools/CsfFile.test.ts
  • code/core/src/csf-tools/storyIndexer.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/spy-mocking.mdc)

**/*.test.{ts,tsx,js,jsx}: Use vi.mock() with the spy: true option for all package and file mocks in Vitest tests
Place all mocks at the top of the test file before any test cases
Use vi.mocked() to type and access mocked functions
Implement mock behaviors in beforeEach blocks
Mock all required dependencies that the test subject uses
Mock implementations should be placed in beforeEach blocks
Each mock implementation should return a Promise for async functions
Mock implementations should match the expected return type of the original function
Use vi.mocked() to access and implement mock behaviors
Mock all required properties and methods that the test subject uses
Avoid direct function mocking without vi.mocked()
Avoid mock implementations outside of beforeEach blocks
Avoid mocking without the spy: true option
Avoid inline mock implementations within test cases
Avoid mocking only a subset of required dependencies
Mock at the highest level of abstraction needed
Keep mock implementations simple and focused
Use type-safe mocking with vi.mocked()
Document complex mock behaviors
Group related mocks together

Files:

  • code/core/src/csf/csf-factories.test.ts
  • code/core/src/csf-tools/CsfFile.test.ts
  • code/core/src/csf-tools/storyIndexer.test.ts
🧬 Code graph analysis (3)
code/core/src/csf/csf-factories.test.ts (1)
code/core/src/csf/csf-factories.ts (3)
  • test (232-260)
  • meta (64-67)
  • getStoryChildren (347-354)
code/core/src/csf-tools/CsfFile.test.ts (2)
code/core/src/csf-tools/CsfFile.ts (2)
  • loadCsf (1109-1113)
  • parse (451-1014)
code/core/src/csf/csf-factories.ts (2)
  • story (123-127)
  • test (232-260)
code/core/src/csf/csf-factories.ts (1)
code/core/src/csf/story.ts (5)
  • EachTestParam (291-291)
  • EachTestFunction (293-297)
  • StoryAnnotations (534-554)
  • EachAnnotationsFunction (299-303)
  • TestFunction (287-289)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (5)
code/core/src/component-testing/components/test-fn.stories.tsx (1)

181-210: Great smoke coverage for the new parameterized APIs.

These stories hit both .each and .matrix end-to-end (formatter + per-row args + assertions), so we get immediate signal that the plumbing works as intended.

code/core/src/types/modules/csf.ts (1)

25-27: Exports cover the new parameterized test types

Good call surfacing these through the public CSF types module so downstream factory consumers can stay strongly typed with the new each/matrix APIs.

code/core/src/csf-tools/storyIndexer.test.ts (1)

49-66: Story index coverage for each/matrix looks solid

The snapshot assertions exercise both the per-row and cartesian matrix expansions, so regressions in discovery or naming should be caught early.

code/core/src/csf-tools/CsfFile.test.ts (1)

2654-2963: Great coverage on test tag propagation and expansion

These scenarios thoroughly validate that tag resolution, overrides, and generated names stay correct across test, each, and matrix, which should keep the parser honest as the API evolves.

code/core/src/csf/csf-factories.test.ts (1)

79-201: Factory helpers verified end-to-end

Appreciate the direct execution of the generated children—confirms both argument propagation and override behavior for each and matrix.

Comment on lines 309 to 313
"execa": "^8.0.1",
"exsolve": "^1.0.7",
"fast-printf": "^1.6.10",
"fetch-retry": "^6.0.0",
"flush-promises": "^1.0.2",
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Move fast-printf to dependencies.

fast-printf is consumed at runtime by csf-factories.ts, so bundling it as a dev dependency will leave downstream installs without the module and trigger Cannot find module 'fast-printf' at execution time. Please publish it as a production dependency.

@@
-    "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0",
-    "recast": "^0.23.5",
+    "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0",
+    "fast-printf": "^1.6.10",
+    "recast": "^0.23.5",
@@
-    "exsolve": "^1.0.7",
-    "fast-printf": "^1.6.10",
+    "exsolve": "^1.0.7",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"execa": "^8.0.1",
"exsolve": "^1.0.7",
"fast-printf": "^1.6.10",
"fetch-retry": "^6.0.0",
"flush-promises": "^1.0.2",
"dependencies": {
"esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0",
"fast-printf": "^1.6.10",
"recast": "^0.23.5"
// … other dependencies …
},
"devDependencies": {
"execa": "^8.0.1",
"exsolve": "^1.0.7",
"fetch-retry": "^6.0.0",
"flush-promises": "^1.0.2"
// … other devDependencies …
}
🤖 Prompt for AI Agents
In code/core/package.json around lines 309 to 313, fast-printf is listed as a
devDependency but is required at runtime by csf-factories.ts; move
"fast-printf": "^1.6.10" from devDependencies into the top-level dependencies
section (same version), remove it from devDependencies, then update the lockfile
by running npm install or yarn install so the production install includes the
package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency will be bundled by the build script.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrginglymus Thank you for the clarification! You're absolutely right. I see from the retrieved learning that in Storybook's core package, dependencies are bundled into the final distribution during the build process, so they should remain in devDependencies rather than being moved to dependencies. End users don't need these packages as separate runtime dependencies since they're included in the bundled code.

I apologize for the confusion in my initial suggestion. The placement of fast-printf in devDependencies is correct for Storybook's bundling approach.


✏️ Learnings added
Learnt from: mrginglymus
PR: storybookjs/storybook#32556
File: code/core/package.json:309-313
Timestamp: 2025-09-29T13:20:23.320Z
Learning: The `fast-printf` dependency in Storybook's core package is bundled into the final distribution during the build process, so it should remain in devDependencies rather than being moved to dependencies, following the same pattern as other bundled dependencies like `open`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: ndelangen
PR: storybookjs/storybook#32484
File: code/core/package.json:326-326
Timestamp: 2025-09-17T07:31:04.432Z
Learning: In Storybook's core package, dependencies like `open` are bundled into the final distribution during the build process, so they should remain in devDependencies rather than being moved to dependencies. End users don't need these packages as separate runtime dependencies since they're included in the bundled code.

Comment on lines +818 to +861
t.isCallExpression(expression) &&
t.isMemberExpression(expression.callee) &&
expression.arguments.length >= 3 &&
t.isStringLiteral(expression.arguments[0]) &&
t.isArrayExpression(expression.arguments[1]) &&
t.isMemberExpression(expression.callee) &&
t.isIdentifier(expression.callee.object) &&
t.isIdentifier(expression.callee.property) &&
['each', 'matrix'].includes(expression.callee.property.name)
) {
const exportName = expression.callee.object.name;
const testName = expression.arguments[0].value;
const testFunction =
expression.arguments.length === 3 ? expression.arguments[2] : expression.arguments[3];
const testArguments =
expression.arguments.length === 3 ? null : expression.arguments[2];
const tags = parseTestTags(testArguments as t.Node | null, self._ast.program);

const parameters = parseParameters(expression.arguments[1]);

const combinate = (args: typeof parameters) =>
args.reduce<typeof args>(
(acc, param) => acc.flatMap((acc2) => param.map((p) => [...acc2, p])),
[[]]
);

(expression.callee.property.name === 'matrix'
? combinate(parameters)
: parameters
).forEach((args) => {
self._tests.push({
function: testFunction,
name: format(testName, ...args),
node: expression,
// can't set id because meta title isn't available yet
// so it's set later on
id: 'FIXME',
tags,
parent: { node: self._storyStatements[exportName] },
});
// TODO: fix this when stories fail
self._stories[exportName].__stats.tests = true;
});
}
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle .each/.matrix parameter arrays resolved from identifiers.

Right now we only enter this branch when the second argument is an inline array literal. In practice it’s common to write const cases = [...] and then call A.each('case %s', cases, …). That’s perfectly valid at runtime, but with the current guard those tests disappear from the index because the parser never sees them. We should mirror the tag logic: resolve identifiers (and other simple indirections) to their initializer via findVarInitialization before asserting t.isArrayExpression, so hoisted/shared parameter lists are still discovered.

-            t.isArrayExpression(expression.arguments[1]) &&
+            (t.isArrayExpression(expression.arguments[1]) ||
+              t.isIdentifier(expression.arguments[1])) &&-            const parameters = parseParameters(expression.arguments[1]);
+            const parametersNode = t.isIdentifier(expression.arguments[1])
+              ? findVarInitialization(expression.arguments[1].name, self._ast.program)
+              : expression.arguments[1];
+            if (!parametersNode || !t.isArrayExpression(parametersNode)) {
+              return;
+            }
+            const parameters = parseParameters(parametersNode);

Without this, parameterized tests defined through reusable constants (or simple re-exports) silently drop out of the story index. Let's make sure we cover that path before shipping.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
t.isCallExpression(expression) &&
t.isMemberExpression(expression.callee) &&
expression.arguments.length >= 3 &&
t.isStringLiteral(expression.arguments[0]) &&
t.isArrayExpression(expression.arguments[1]) &&
t.isMemberExpression(expression.callee) &&
t.isIdentifier(expression.callee.object) &&
t.isIdentifier(expression.callee.property) &&
['each', 'matrix'].includes(expression.callee.property.name)
) {
const exportName = expression.callee.object.name;
const testName = expression.arguments[0].value;
const testFunction =
expression.arguments.length === 3 ? expression.arguments[2] : expression.arguments[3];
const testArguments =
expression.arguments.length === 3 ? null : expression.arguments[2];
const tags = parseTestTags(testArguments as t.Node | null, self._ast.program);
const parameters = parseParameters(expression.arguments[1]);
const combinate = (args: typeof parameters) =>
args.reduce<typeof args>(
(acc, param) => acc.flatMap((acc2) => param.map((p) => [...acc2, p])),
[[]]
);
(expression.callee.property.name === 'matrix'
? combinate(parameters)
: parameters
).forEach((args) => {
self._tests.push({
function: testFunction,
name: format(testName, ...args),
node: expression,
// can't set id because meta title isn't available yet
// so it's set later on
id: 'FIXME',
tags,
parent: { node: self._storyStatements[exportName] },
});
// TODO: fix this when stories fail
self._stories[exportName].__stats.tests = true;
});
}
t.isCallExpression(expression) &&
t.isMemberExpression(expression.callee) &&
expression.arguments.length >= 3 &&
t.isStringLiteral(expression.arguments[0]) &&
(t.isArrayExpression(expression.arguments[1]) ||
t.isIdentifier(expression.arguments[1])) &&
t.isMemberExpression(expression.callee) &&
t.isIdentifier(expression.callee.object) &&
t.isIdentifier(expression.callee.property) &&
['each', 'matrix'].includes(expression.callee.property.name)
) {
const exportName = expression.callee.object.name;
const testName = expression.arguments[0].value;
const testFunction =
expression.arguments.length === 3 ? expression.arguments[2] : expression.arguments[3];
const testArguments =
expression.arguments.length === 3 ? null : expression.arguments[2];
const tags = parseTestTags(testArguments as t.Node | null, self._ast.program);
const parametersNode = t.isIdentifier(expression.arguments[1])
? findVarInitialization(expression.arguments[1].name, self._ast.program)
: expression.arguments[1];
if (!parametersNode || !t.isArrayExpression(parametersNode)) {
return;
}
const parameters = parseParameters(parametersNode);
const combinate = (args: typeof parameters) =>
args.reduce<typeof args>(
(acc, param) => acc.flatMap((acc2) => param.map((p) => [...acc2, p])),
[[]]
);
(expression.callee.property.name === 'matrix'
? combinate(parameters)
: parameters
).forEach((args) => {
self._tests.push({
function: testFunction,
name: format(testName, ...args),
node: expression,
// can't set id because meta title isn't available yet
// so it's set later on
id: 'FIXME',
tags,
parent: { node: self._storyStatements[exportName] },
});
// TODO: fix this when stories fail
self._stories[exportName].__stats.tests = true;
});
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't noticed that utility - if the RFC gets over the line I will implement this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrginglymus That sounds like a great plan! The findVarInitialization utility is indeed quite handy for resolving identifier references in AST parsing scenarios like this. It's already being used effectively in the codebase for parsing tags and other identifier-based configurations.

Once the RFC gets approved, implementing this enhancement will make the .each and .matrix functionality much more flexible for users who prefer to define their test parameters as reusable constants - which is a pretty common pattern. Good catch on deferring this until the RFC decision is made!

@storybook-pr-benchmarking
Copy link

Package Benchmarks

Commit: a94138e, ran on 29 September 2025 at 13:21:44 UTC

The following packages have significant changes to their size or dependencies:

@storybook/addon-docs

Before After Difference
Dependency count 18 18 0
Self size 2.07 MB 2.06 MB 🎉 -11 KB 🎉
Dependency size 9.44 MB 9.43 MB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@storybook/addon-vitest

Before After Difference
Dependency count 6 6 0
Self size 501 KB 491 KB 🎉 -11 KB 🎉
Dependency size 1.53 MB 1.53 MB 0 B
Bundle Size Analyzer Link Link

@storybook/builder-vite

Before After Difference
Dependency count 11 11 0
Self size 330 KB 319 KB 🎉 -10 KB 🎉
Dependency size 1.30 MB 1.30 MB 0 B
Bundle Size Analyzer Link Link

storybook

Before After Difference
Dependency count 43 43 0
Self size 30.16 MB 30.19 MB 🚨 +30 KB 🚨
Dependency size 17.30 MB 17.30 MB 0 B
Bundle Size Analyzer Link Link

@storybook/html-vite

Before After Difference
Dependency count 14 14 0
Self size 23 KB 23 KB 🚨 +18 B 🚨
Dependency size 1.67 MB 1.66 MB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@storybook/nextjs

Before After Difference
Dependency count 531 531 0
Self size 950 KB 939 KB 🎉 -11 KB 🎉
Dependency size 58.43 MB 58.41 MB 🎉 -21 KB 🎉
Bundle Size Analyzer Link Link

@storybook/nextjs-vite

Before After Difference
Dependency count 124 124 0
Self size 4.10 MB 4.01 MB 🎉 -81 KB 🎉
Dependency size 21.62 MB 21.59 MB 🎉 -31 KB 🎉
Bundle Size Analyzer Link Link

@storybook/preact-vite

Before After Difference
Dependency count 14 14 0
Self size 14 KB 14 KB 0 B
Dependency size 1.65 MB 1.64 MB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-native-web-vite

Before After Difference
Dependency count 157 157 0
Self size 31 KB 31 KB 0 B
Dependency size 23.01 MB 22.97 MB 🎉 -31 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-vite

Before After Difference
Dependency count 114 114 0
Self size 37 KB 37 KB 0 B
Dependency size 19.56 MB 19.53 MB 🎉 -31 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-webpack5

Before After Difference
Dependency count 272 272 0
Self size 25 KB 25 KB 🚨 +18 B 🚨
Dependency size 43.35 MB 43.33 MB 🎉 -21 KB 🎉
Bundle Size Analyzer Link Link

@storybook/svelte-vite

Before After Difference
Dependency count 19 19 0
Self size 59 KB 59 KB 🎉 -52 B 🎉
Dependency size 26.79 MB 26.78 MB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@storybook/sveltekit

Before After Difference
Dependency count 20 20 0
Self size 58 KB 58 KB 🚨 +30 B 🚨
Dependency size 26.85 MB 26.84 MB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@storybook/vue3-vite

Before After Difference
Dependency count 109 109 0
Self size 38 KB 38 KB 0 B
Dependency size 43.78 MB 43.77 MB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@storybook/web-components-vite

Before After Difference
Dependency count 15 15 0
Self size 20 KB 20 KB 0 B
Dependency size 1.70 MB 1.68 MB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@storybook/cli

Before After Difference
Dependency count 187 187 0
Self size 905 KB 890 KB 🎉 -14 KB 🎉
Dependency size 79.76 MB 79.79 MB 🚨 +30 KB 🚨
Bundle Size Analyzer Link Link

@storybook/codemod

Before After Difference
Dependency count 169 169 0
Self size 35 KB 35 KB 0 B
Dependency size 76.19 MB 76.22 MB 🚨 +30 KB 🚨
Bundle Size Analyzer Link Link

create-storybook

Before After Difference
Dependency count 44 44 0
Self size 1.55 MB 1.55 MB 🚨 +8 B 🚨
Dependency size 47.46 MB 47.49 MB 🚨 +30 KB 🚨
Bundle Size Analyzer node node

@storybook/react-dom-shim

Before After Difference
Dependency count 0 0 0
Self size 22 KB 12 KB 🎉 -10 KB 🎉
Dependency size 785 B 785 B 0 B
Bundle Size Analyzer Link Link

@storybook/preset-create-react-app

Before After Difference
Dependency count 68 68 0
Self size 36 KB 26 KB 🎉 -10 KB 🎉
Dependency size 5.97 MB 5.97 MB 0 B
Bundle Size Analyzer Link Link

@storybook/react

Before After Difference
Dependency count 2 2 0
Self size 894 KB 884 KB 🎉 -10 KB 🎉
Dependency size 28 KB 18 KB 🎉 -10 KB 🎉
Bundle Size Analyzer Link Link

@github-actions github-actions bot added the Stale label Oct 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants