Skip to content

Conversation

@kasperpeulen
Copy link
Contributor

@kasperpeulen kasperpeulen commented Oct 31, 2025

Closes #

What I did

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 pull request has been released as version 0.0.0-pr-32905-sha-03386401. Try it out in a new sandbox by running npx [email protected] sandbox or in an existing project with npx [email protected] upgrade.

More information
Published version 0.0.0-pr-32905-sha-03386401
Triggered by @kasperpeulen
Repository storybookjs/storybook
Branch 10.1-with-canary-release
Commit 03386401
Datetime Fri Oct 31 09:44:14 UTC 2025 (1761903854)
Workflow run 18968757436

To request a new release of this pull request, mention the @storybookjs/core team.

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

@nx-cloud
Copy link

nx-cloud bot commented Oct 31, 2025

View your CI Pipeline Execution ↗ for commit 0338640

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

☁️ Nx Cloud last updated this comment at 2025-10-31 10:01:29 UTC

@JReinhold
Copy link
Contributor

Papertrail: This is a duplicate of #32882 . That PR originally targeted the temporary 10.1 branch #32810 . However the 10.1 branch was merged to next and released as 10.1.0-alpha.2 before the original of this PR was merged, so merging it made no difference.

This PR just continues to merge it to next.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 31, 2025

📝 Walkthrough

Walkthrough

This PR introduces shared utility functions for module resolution and object grouping, creates a new HTML rendering feature for component manifests with error tracking, refactors module resolution across the codebase to use the new utilities, updates the ComponentManifest type to include error names, and enhances error reporting throughout the component manifest generation pipeline.

Changes

Cohort / File(s) Summary
Shared Utilities & Dependencies
code/core/package.json, code/core/src/common/index.ts, code/core/src/common/utils/utils.ts, code/core/src/common/utils/interpret-files.ts
Added resolve dependency. Exported new utility functions: groupBy for object grouping and invariant for runtime assertions. Introduced resolveImport function with TypeScript fallback path logic for module resolution, and expanded supportedExtensions to include .mts, .mtsx, .ctsx, .cjs.
HTML Manifest Rendering
code/core/src/core-server/manifest.ts, code/core/src/core-server/build-static.ts, code/core/src/core-server/dev-server.ts
New module implementing renderManifestComponentsPage with self-contained HTML rendering for component manifests, including error/warning filtering, component cards, and metrics aggregation. Updated build-static to generate HTML manifests alongside JSON. Added /manifests/components.html endpoint to dev-server.
Module Resolution Refactoring
code/core/src/core-server/utils/StoryIndexGenerator.ts, code/renderers/react/src/componentManifest/reactDocgen.ts, code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts
Replaced manual path resolution with resolveImport and supportedExtensions. Removed hard-coded RESOLVE_EXTENSIONS constant; updated defaultLookupModule to use shared extensions. Updated StoryIndexGenerator to leverage tsconfig paths matching and the new resolution utilities.
Type Updates
code/core/src/types/modules/core-common.ts
Updated ComponentManifest interface: error fields (top-level error and examples[].error) now include name: string alongside message: string.
Component Manifest Generation
code/renderers/react/src/componentManifest/generator.ts, code/renderers/react/src/componentManifest/generator.test.ts, code/renderers/react/src/componentManifest/generateCodeSnippet.ts, code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
Enhanced error handling to capture and propagate error names across multiple failure paths (component file read, docgen evaluation, missing meta.component). Added storyArgsAssignmentPath helper for merging story-assigned args into code snippets. Updated test snapshots to include error names.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant DevServer
    participant Generator as ComponentManifestGenerator
    participant Renderer as renderManifestComponentsPage
    participant HTML as HTML Output

    Client->>DevServer: GET /manifests/components.html
    alt Generator and Index Present
        DevServer->>Generator: generate()
        Generator-->>DevServer: ComponentsManifest (with errors/warnings)
        DevServer->>Renderer: renderManifestComponentsPage(manifest)
        Renderer->>Renderer: Sort components by name
        Renderer->>Renderer: Analyze each component<br/>(errors, warnings, examples)
        Renderer->>Renderer: Aggregate metrics<br/>(counts, error types)
        Renderer->>Renderer: Build component cards<br/>with badges and toggles
        Renderer-->>HTML: Complete HTML document<br/>(filtered by error type)
        DevServer->>Client: 200 HTML page
    else Missing Generator or Index
        DevServer->>Client: 400 Bad Request
    else Generation Error
        DevServer->>Client: 500 Error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Key areas requiring careful attention:
    • code/core/src/core-server/manifest.ts — New 200+ line HTML rendering module with complex nested UI logic, filtering state, and CSS-based conditional rendering; requires thorough review of correctness, accessibility, and data aggregation logic
    • code/renderers/react/src/componentManifest/generator.ts — Multi-layered error handling refactoring with conditional logic for different failure scenarios; requires verification that error names are consistently captured and propagated
    • code/core/src/common/utils/interpret-files.ts — New resolveImport function with fallback path logic for JS-to-TS extension mapping; edge cases and tsconfig integration should be verified
    • code/renderers/react/src/componentManifest/reactDocgen.ts — Switching from defaultLookupModule/RESOLVE_EXTENSIONS to resolveImport/supportedExtensions; ensure resolution behavior remains equivalent across all usage sites

Possibly related PRs

✨ Finishing touches
  • 📝 Generate docstrings

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

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/renderers/react/src/componentManifest/generator.ts (1)

103-107: Preserve the original readFile error details

We currently swallow the underlying readFile error, which makes debugging harder (e.g., ENOENT vs. permissions). Please carry the original message through so callers get actionable context.

Apply something like:

         try {
           componentFile = await readFile(path.join(process.cwd(), entry.componentPath!), 'utf-8');
         } catch (e) {
           invariant(e instanceof Error);
-          return {
+          const details = e.message ? `\nOriginal error: ${e.message}` : '';
+          return {
             ...base,
             name,
             examples,
             error: {
               name: 'Component file could not be read',
-              message: `Could not read the component file located at "${entry.componentPath}".\nPrefer relative imports.`,
+              message: `Could not read the component file located at "${entry.componentPath}".${details}\nPrefer relative imports.`,
             },
           };
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a2e1b2 and 0338640.

⛔ Files ignored due to path filters (1)
  • code/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (15)
  • code/core/package.json (1 hunks)
  • code/core/src/common/index.ts (1 hunks)
  • code/core/src/common/utils/interpret-files.ts (1 hunks)
  • code/core/src/common/utils/utils.ts (1 hunks)
  • code/core/src/core-server/build-static.ts (2 hunks)
  • code/core/src/core-server/dev-server.ts (2 hunks)
  • code/core/src/core-server/manifest.ts (1 hunks)
  • code/core/src/core-server/utils/StoryIndexGenerator.ts (2 hunks)
  • code/core/src/types/modules/core-common.ts (1 hunks)
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx (1 hunks)
  • code/renderers/react/src/componentManifest/generateCodeSnippet.ts (2 hunks)
  • code/renderers/react/src/componentManifest/generator.test.ts (2 hunks)
  • code/renderers/react/src/componentManifest/generator.ts (4 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen.ts (3 hunks)
  • code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,jsx,json,html,ts,tsx,mjs}: Run Prettier formatting on changed files before committing
Run ESLint on changed files and fix all errors/warnings before committing (use yarn lint:js:cmd <file>)

Files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/core/src/common/index.ts
  • code/core/package.json
  • code/core/src/core-server/build-static.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/common/utils/utils.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.ts
  • code/core/src/core-server/dev-server.ts
  • code/core/src/common/utils/interpret-files.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
  • code/core/src/core-server/utils/StoryIndexGenerator.ts
  • code/core/src/core-server/manifest.ts
**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Export functions from modules when they need to be unit-tested

Files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/core/src/common/index.ts
  • code/core/src/core-server/build-static.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/common/utils/utils.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.ts
  • code/core/src/core-server/dev-server.ts
  • code/core/src/common/utils/interpret-files.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
  • code/core/src/core-server/utils/StoryIndexGenerator.ts
  • code/core/src/core-server/manifest.ts
code/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In application code, use Storybook loggers instead of console.* (client code: storybook/internal/client-logger; server code: storybook/internal/node-logger)

Files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/core/src/common/index.ts
  • code/core/src/core-server/build-static.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/common/utils/utils.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.ts
  • code/core/src/core-server/dev-server.ts
  • code/core/src/common/utils/interpret-files.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
  • code/core/src/core-server/utils/StoryIndexGenerator.ts
  • code/core/src/core-server/manifest.ts
{code/**,scripts/**}/**/*.{ts,tsx,js,jsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/core/src/common/index.ts
  • code/core/src/core-server/build-static.ts
  • code/renderers/react/src/componentManifest/generator.ts
  • code/core/src/common/utils/utils.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.ts
  • code/core/src/core-server/dev-server.ts
  • code/core/src/common/utils/interpret-files.ts
  • code/core/src/types/modules/core-common.ts
  • code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
  • code/core/src/core-server/utils/StoryIndexGenerator.ts
  • code/core/src/core-server/manifest.ts
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/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
**/*.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/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
**/*.@(test|spec).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.@(test|spec).{ts,tsx,js,jsx}: Unit tests should import and execute the functions under test rather than only asserting on syntax patterns
Mock external dependencies in tests using vi.mock() (e.g., filesystem, loggers)

Files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
🧠 Learnings (14)
📚 Learning: 2025-10-01T15:24:01.060Z
Learnt from: Sidnioulz
Repo: storybookjs/storybook PR: 32594
File: code/core/src/components/components/Popover/WithPopover.tsx:7-9
Timestamp: 2025-10-01T15:24:01.060Z
Learning: In the Storybook repository, "react-aria-components/patched-dist/*" (e.g., "react-aria-components/patched-dist/Dialog", "react-aria-components/patched-dist/Popover", "react-aria-components/patched-dist/Tooltip") are valid import paths created by a patch applied to the react-aria-components package. These imports should not be flagged as broken or invalid until a maintainer explicitly states they are no longer acceptable.

Applied to files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/core/src/core-server/utils/StoryIndexGenerator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to test-storybooks/** : Maintain test Storybook configurations under `test-storybooks/` for E2E and visual testing scenarios

Applied to files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/utils/StoryIndexGenerator.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/.storybook/** : Place internal UI Storybook configuration in `code/.storybook/` and maintain it there

Applied to files:

  • code/renderers/react/src/componentManifest/reactDocgen.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.@(test|spec).{ts,tsx,js,jsx} : Unit tests should import and execute the functions under test rather than only asserting on syntax patterns

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to **/*.{ts,tsx,js,jsx,mjs} : Export functions from modules when they need to be unit-tested

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/core/src/common/index.ts
  • code/core/src/common/utils/interpret-files.ts
  • code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should match the expected return type of the original function

Applied to files:

  • code/renderers/react/src/componentManifest/generator.test.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to scripts/**/*.{ts,js,mjs} : In Node.js scripts, use `storybook/internal/node-logger` instead of `console.*`

Applied to files:

  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/dev-server.ts
📚 Learning: 2025-10-13T13:33:14.659Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-13T13:33:14.659Z
Learning: Applies to code/**/*.{ts,tsx,js,jsx,mjs} : In application code, use Storybook loggers instead of `console.*` (client code: `storybook/internal/client-logger`; server code: `storybook/internal/node-logger`)

Applied to files:

  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/dev-server.ts
📚 Learning: 2025-09-24T09:39:39.233Z
Learnt from: ndelangen
Repo: storybookjs/storybook PR: 32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.233Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.

Applied to files:

  • code/core/src/core-server/build-static.ts
  • code/core/src/core-server/dev-server.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Implement mock behaviors in beforeEach blocks

Applied to files:

  • code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx
🧬 Code graph analysis (8)
code/renderers/react/src/componentManifest/reactDocgen.ts (1)
code/core/src/common/utils/interpret-files.ts (2)
  • supportedExtensions (6-17)
  • resolveImport (25-58)
code/core/src/core-server/build-static.ts (1)
code/core/src/core-server/manifest.ts (1)
  • renderManifestComponentsPage (7-557)
code/core/src/core-server/dev-server.ts (4)
code/renderers/react/src/componentManifest/generator.ts (1)
  • componentManifestGenerator (20-157)
code/renderers/react/src/preset.ts (1)
  • componentManifestGenerator (11-11)
code/core/src/types/modules/core-common.ts (2)
  • ComponentManifestGenerator (365-367)
  • ComponentsManifest (360-363)
code/core/src/core-server/manifest.ts (1)
  • renderManifestComponentsPage (7-557)
code/core/src/common/utils/interpret-files.ts (1)
code/frameworks/angular/src/server/angular-cli-webpack.js (1)
  • resolve (192-201)
code/renderers/react/src/componentManifest/reactDocgen/docgenResolver.ts (1)
code/core/src/common/utils/interpret-files.ts (1)
  • supportedExtensions (6-17)
code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx (1)
scripts/utils/tools.ts (1)
  • dedent (118-118)
code/core/src/core-server/utils/StoryIndexGenerator.ts (2)
code/core/src/common/utils/interpret-files.ts (2)
  • supportedExtensions (6-17)
  • resolveImport (25-58)
code/core/src/common/utils/paths.ts (1)
  • normalizeStoryPath (82-88)
code/core/src/core-server/manifest.ts (2)
code/core/src/types/modules/core-common.ts (2)
  • ComponentsManifest (360-363)
  • ComponentManifest (348-358)
code/core/src/common/utils/utils.ts (1)
  • groupBy (2-15)
⏰ 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). (3)
  • GitHub Check: normal
  • GitHub Check: Core Unit Tests, windows-latest
  • GitHub Check: Publish canary version
🔇 Additional comments (1)
code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx (1)

198-207: Nice coverage for CSF2 args assignments

Thanks for capturing the Template.bind plus Story.args merge case—this will prevent regressions in the new storyAssignedArgs flow.

Comment on lines +47 to +57
const newId = ['.js', '.mjs', '.cjs'].includes(ext)
? `${id.slice(0, -2)}ts`
: ext === '.jsx'
? `${id.slice(0, -3)}tsx`
: null;

if (!newId) {
throw error;
}
return resolve.sync(newId, { ...mergedOptions, extensions: [] });
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix TypeScript ESM fallback for .tsx components

When stories follow the NodeNext/ESM guidance and import their component as ./Component.js, the source file is often Component.tsx. The new fallback only tries *.ts, so resolution now fails and the component manifest ends up with “Component file could not be read”, which is a functional regression. Please expand the fallback to retry .tsx (or simply drop the extension and let supportedExtensions take over) so .tsx sources keep working.

Apply this diff to cover both .ts and .tsx before giving up:

-    const newId = ['.js', '.mjs', '.cjs'].includes(ext)
-      ? `${id.slice(0, -2)}ts`
-      : ext === '.jsx'
-        ? `${id.slice(0, -3)}tsx`
-        : null;
-
-    if (!newId) {
-      throw error;
-    }
-    return resolve.sync(newId, { ...mergedOptions, extensions: [] });
+    if (['.js', '.mjs', '.cjs', '.jsx'].includes(ext)) {
+      const base = id.slice(0, -ext.length);
+      const candidates =
+        ext === '.jsx'
+          ? [`${base}.tsx`, base]
+          : [`${base}.ts`, `${base}.tsx`, base];
+
+      for (const candidate of candidates) {
+        try {
+          return resolve.sync(candidate, mergedOptions);
+        } catch (_) {
+          // keep trying
+        }
+      }
+    }
+    throw error;
🤖 Prompt for AI Agents
In code/core/src/common/utils/interpret-files.ts around lines 47 to 57, the TS
ESM fallback only rewrites imports like ./Component.js to ./Component.ts and
fails to handle Component.tsx; update the fallback so when ext is one of ['.js',
'.mjs', '.cjs'] you attempt resolution candidates for both the .tsx and .ts
variants (try .tsx first then .ts), and ensure the resolver tries each candidate
before throwing the original error (or alternatively remove the manual extension
rewrite and call resolve.sync with no forced extension so supportedExtensions
handles .ts/.tsx automatically).

Comment on lines +263 to +276
AssignmentExpression(p) {
const left = p.get('left');
const right = p.get('right');
if (left.isMemberExpression()) {
const obj = left.get('object');
const prop = left.get('property');
const isStoryIdent = obj.isIdentifier() && obj.node.name === storyName;
const isArgsProp =
(prop.isIdentifier() && prop.node.name === 'args' && !left.node.computed) ||
(t.isStringLiteral(prop.node) && left.node.computed && prop.node.value === 'args');
if (isStoryIdent && isArgsProp && right.isObjectExpression()) {
found = right as NodePath<t.ObjectExpression>;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle TS wrapper expressions when collecting Story.args

TypeScript users routinely write Primary.args = { … } as const; or wrap the object with satisfies StoryObj. In those cases the right-hand side is a TSAsExpression, TSSatisfiesExpression, or a parenthesized expression, so this guard never fires and the new snippet logic still drops the assigned props. That defeats the main goal of pulling in Story.args for strongly typed CSF stories.

Please unwrap those wrappers before checking for an ObjectExpression, e.g.:

-        if (isStoryIdent && isArgsProp && right.isObjectExpression()) {
-          found = right as NodePath<t.ObjectExpression>;
+        if (isStoryIdent && isArgsProp) {
+          let value: NodePath<t.Expression> = right as NodePath<t.Expression>;
+          while (
+            value.isTSAsExpression?.() ||
+            value.isTSSatisfiesExpression?.() ||
+            value.isParenthesizedExpression()
+          ) {
+            value = value.get('expression') as NodePath<t.Expression>;
+          }
+          if (value.isObjectExpression()) {
+            found = value as NodePath<t.ObjectExpression>;
+          }
         }

That will make the feature work for the common as const / satisfies patterns.

📝 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
AssignmentExpression(p) {
const left = p.get('left');
const right = p.get('right');
if (left.isMemberExpression()) {
const obj = left.get('object');
const prop = left.get('property');
const isStoryIdent = obj.isIdentifier() && obj.node.name === storyName;
const isArgsProp =
(prop.isIdentifier() && prop.node.name === 'args' && !left.node.computed) ||
(t.isStringLiteral(prop.node) && left.node.computed && prop.node.value === 'args');
if (isStoryIdent && isArgsProp && right.isObjectExpression()) {
found = right as NodePath<t.ObjectExpression>;
}
}
AssignmentExpression(p) {
const left = p.get('left');
const right = p.get('right');
if (left.isMemberExpression()) {
const obj = left.get('object');
const prop = left.get('property');
const isStoryIdent = obj.isIdentifier() && obj.node.name === storyName;
const isArgsProp =
(prop.isIdentifier() && prop.node.name === 'args' && !left.node.computed) ||
(t.isStringLiteral(prop.node) && left.node.computed && prop.node.value === 'args');
if (isStoryIdent && isArgsProp) {
let value: NodePath<t.Expression> = right as NodePath<t.Expression>;
while (
value.isTSAsExpression?.() ||
value.isTSSatisfiesExpression?.() ||
value.isParenthesizedExpression()
) {
value = value.get('expression') as NodePath<t.Expression>;
}
if (value.isObjectExpression()) {
found = value as NodePath<t.ObjectExpression>;
}
}
}

@storybook-app-bot
Copy link

Package Benchmarks

Commit: 0338640, ran on 31 October 2025 at 09:58:59 UTC

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

storybook

Before After Difference
Dependency count 43 43 0
Self size 22.93 MB 23.01 MB 🚨 +78 KB 🚨
Dependency size 17.36 MB 17.36 MB 0 B
Bundle Size Analyzer Link Link

@storybook/cli

Before After Difference
Dependency count 187 187 0
Self size 928 KB 928 KB 🚨 +168 B 🚨
Dependency size 72.89 MB 72.96 MB 🚨 +78 KB 🚨
Bundle Size Analyzer Link Link

@storybook/codemod

Before After Difference
Dependency count 169 169 0
Self size 35 KB 35 KB 🎉 -42 B 🎉
Dependency size 69.31 MB 69.39 MB 🚨 +78 KB 🚨
Bundle Size Analyzer Link Link

create-storybook

Before After Difference
Dependency count 44 44 0
Self size 1.55 MB 1.55 MB 🎉 -30 B 🎉
Dependency size 40.29 MB 40.37 MB 🚨 +78 KB 🚨
Bundle Size Analyzer node node

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:normal feature request manifest Component manifest generation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants