Skip to content

Angular: Report what a snippet could not resolve - #35798

Merged
valentinpalkovic merged 10 commits into
nextfrom
valentin/angular-story-docs-3-warning
Aug 13, 2026
Merged

valentinpalkovic merged 10 commits into
nextfrom
valentin/angular-story-docs-3-warning

Conversation

@valentinpalkovic

@valentinpalkovic valentinpalkovic commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Note

Third of four Angular story-docs slices, stacked on #35797 (which now sits on #35807 -> #35808 -> #35805). First producer of the warning field added in #35794.

What I did

Angular story snippets are built on the server by reading the story file, not by running it. Some things cannot be read that way: args merged in through a spread, a template held in an imported const, a render that points at a function declared elsewhere. The snippet that comes out is still useful, but nothing marked it as partial, so a consumer had no way to tell an incomplete example from a complete one.

Every story left incomplete now carries a warning naming the source text this pass could not read, next to the snippet it produced anyway.

                       +--- template / render ---+
 story file --parse--> +--- meta config ---------+--> readable in full?
                       +--- story config --------+           |
                                                     yes ----+---- no
                                                      |             |
                                                      v             v
                                       snippet: markup     snippet: generated bindings
                                       as written          warning: the source text it
                                       (no warning)                 could not read

What changes in the output

The same story file, built before and after this change:

const sharedArgs = { label: 'shared' };
export default { title: 'Example/Button', component: ButtonComponent, args: { label: 'meta' } };
export const SpreadArgs = { args: { ...sharedArgs, count: 1 } };
export const Plain = { args: { count: 2 } };

Before, the two stories are indistinguishable:

{
  "example-button--spread-args": {
    "id": "example-button--spread-args",
    "name": "Spread Args",
    "snippet": "<sb-button [label]=\"'meta'\" [count]=\"1\" (clicked)=\"clicked($event)\"></sb-button>"
  },
  "example-button--plain": {
    "id": "example-button--plain",
    "name": "Plain",
    "snippet": "<sb-button [label]=\"'meta'\" [count]=\"2\" (clicked)=\"clicked($event)\"></sb-button>"
  }
}

After, the partial one says so and the complete one is left alone:

{
  "example-button--spread-args": {
    "id": "example-button--spread-args",
    "name": "Spread Args",
    "snippet": "<sb-button [label]=\"'meta'\" [count]=\"1\" (clicked)=\"clicked($event)\"></sb-button>",
    "warning": "Incomplete snippet: `...sharedArgs` could not be resolved statically."
  },
  "example-button--plain": {
    "id": "example-button--plain",
    "name": "Plain",
    "snippet": "<sb-button [label]=\"'meta'\" [count]=\"2\" (clicked)=\"clicked($event)\"></sb-button>"
  }
}

label in the first snippet is the meta's value, not sharedArgs's. The snippet itself is byte-identical in both runs; only the note next to it is new.

Why a field and not a comment in the snippet

The obvious alternative is to write it into the markup:

<!-- unresolved: ...sharedArgs -->
<sb-button [label]="'meta'" [count]="1"></sb-button>

That pushes the problem onto every consumer. The Docs Source block renders it as a stray comment, an agent reading the manifest has to parse it back out, and a story whose snippet is not HTML has no comment syntax to hide it in.

warning always comes with a snippet. error continues to mean there is no snippet at all.

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

  1. yarn task sandbox --template angular-vite/docgen-server-ts --start-from auto. That template is the Angular sandbox with experimentalDocgenServer and componentsManifest already on.
  2. In the sandbox, add a story whose args come from a spread:
    const shared = { label: 'Hi' };
    export const Spread = { args: { ...shared, primary: true } };
  3. Build the sandbox (yarn build-storybook).
  4. Open storybook-static/manifests/components.json, find the component, and follow its stories $ref into storybook-static/services/core/story-docs/<component-id>.json.
  5. The Spread story carries a warning naming ...shared, and its snippet contains no HTML comment. The other stories in the same file carry no warning.

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

  • Declare whether manual QA will be needed for this PR during the next release, through qa:needed or qa:skip

  • 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.

@github-actions

github-actions Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor
Fails
🚫

PR is not labeled with one of: ["qa:needed","qa:skip","qa:success"]

Generated by 🚫 dangerJS against 3f70988

Server-side snippets are built by reading the story file, not by running it, so
some things cannot be resolved: args merged in through a spread, a template held
in an imported const, a `render` that points at a function declared elsewhere.

The snippet that comes out is still useful, but until now nothing said it was
partial. A story that fell back now carries a `warning` naming the source text
this pass could not read, alongside the snippet it produced anyway.

The note is data on the story rather than a comment inside the markup, so a
consumer that renders the snippet is not left with a stray comment and one that
reads it can act on it. `warning` always comes with a `snippet`; `error`
continues to mean there is no snippet at all.
@valentinpalkovic
valentinpalkovic force-pushed the valentin/angular-story-docs-3-warning branch from f3061fa to 3d41670 Compare August 8, 2026 05:42
…in/angular-story-docs-3-warning

The warning feature is re-expressed on the rebuilt base: the spread
resolver, the standalone handling and the multi-line templates all
landed below since this branch forked, so the conflict resolution takes
the base's structure and ports the feature onto it. A story whose
markup or args cannot be read statically now falls back to the
component-derived bindings and carries a warning naming the source text
this pass could not read, instead of yielding no snippet at all; the
story-shapes recordings capture the warning next to the snippet.

Claude-Session: https://claude.ai/code/session_017CAwzzrqr28YcFB5c3NtpQ
…in/angular-story-docs-3-warning

The base split the story-docs builder into its markup, args and
ngModules modules and reshapes story-authored markup, so the warning
feature moves with the code: the unresolved-source tracking lands in
the args records and the markup reader, and the orchestrator keeps the
fallback-with-warning rendering on top of the split.

Claude-Session: https://claude.ai/code/session_017CAwzzrqr28YcFB5c3NtpQ
Base automatically changed from valentin/angular-story-docs-2-story-shapes to next August 13, 2026 13:13
@valentinpalkovic valentinpalkovic self-assigned this Aug 13, 2026
@valentinpalkovic valentinpalkovic added feature request angular ci:normal Run our default set of CI jobs (choose this for most PRs). labels Aug 13, 2026
@storybook-app-bot

Copy link
Copy Markdown
Contributor

Package Benchmarks

Commit: 3f70988, ran on 13 August 2026 at 13:27:29 UTC

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

@storybook/addon-mcp

Before After Difference
Dependency count 11 13 🚨 +2 🚨
Self size 106 KB 191 KB 🚨 +85 KB 🚨
Dependency size 2.64 MB 2.79 MB 🚨 +145 KB 🚨
Bundle Size Analyzer Link Link

@storybook/addon-vitest

Before After Difference
Dependency count 2 2 0
Self size 467 KB 429 KB 🎉 -37 KB 🎉
Dependency size 350 KB 350 KB 0 B
Bundle Size Analyzer Link Link

@storybook/builder-webpack5

Before After Difference
Dependency count 186 186 0
Self size 92 KB 79 KB 🎉 -13 KB 🎉
Dependency size 35.81 MB 35.81 MB 🎉 -6 B 🎉
Bundle Size Analyzer Link Link

storybook

Before After Difference
Dependency count 73 73 0
Self size 21.89 MB 21.49 MB 🎉 -392 KB 🎉
Dependency size 30.98 MB 30.98 MB 0 B
Bundle Size Analyzer Link Link

@storybook/angular

Before After Difference
Dependency count 185 185 0
Self size 267 KB 255 KB 🎉 -11 KB 🎉
Dependency size 30.19 MB 30.18 MB 🎉 -13 KB 🎉
Bundle Size Analyzer Link Link

@storybook/ember

Before After Difference
Dependency count 185 185 0
Self size 13 KB 13 KB 🚨 +18 B 🚨
Dependency size 31.17 MB 31.16 MB 🎉 -13 KB 🎉
Bundle Size Analyzer Link Link

@storybook/nextjs

Before After Difference
Dependency count 540 531 🎉 -9 🎉
Self size 641 KB 641 KB 🎉 -149 B 🎉
Dependency size 63.07 MB 62.49 MB 🎉 -578 KB 🎉
Bundle Size Analyzer Link Link

@storybook/nextjs-vite

Before After Difference
Dependency count 101 90 🎉 -11 🎉
Self size 1.42 MB 1.42 MB 🎉 -971 B 🎉
Dependency size 23.31 MB 23.10 MB 🎉 -202 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-native-web-vite

Before After Difference
Dependency count 122 122 0
Self size 29 KB 29 KB 0 B
Dependency size 25.66 MB 25.65 MB 🎉 -13 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-vite

Before After Difference
Dependency count 79 79 0
Self size 32 KB 32 KB 0 B
Dependency size 20.42 MB 20.41 MB 🎉 -13 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-webpack5

Before After Difference
Dependency count 272 272 0
Self size 23 KB 23 KB 0 B
Dependency size 48.26 MB 48.23 MB 🎉 -24 KB 🎉
Bundle Size Analyzer Link Link

@storybook/server-webpack5

Before After Difference
Dependency count 198 198 0
Self size 15 KB 15 KB 0 B
Dependency size 37.08 MB 37.07 MB 🎉 -13 KB 🎉
Bundle Size Analyzer Link Link

@storybook/tanstack-react

Before After Difference
Dependency count 80 80 0
Self size 132 KB 118 KB 🎉 -14 KB 🎉
Dependency size 20.46 MB 20.44 MB 🎉 -13 KB 🎉
Bundle Size Analyzer Link Link

@storybook/vue3-vite

Before After Difference
Dependency count 94 94 0
Self size 31 KB 31 KB 0 B
Dependency size 18.45 MB 18.44 MB 🎉 -17 KB 🎉
Bundle Size Analyzer Link Link

@storybook/cli

Before After Difference
Dependency count 205 205 0
Self size 843 KB 833 KB 🎉 -10 KB 🎉
Dependency size 86.38 MB 85.98 MB 🎉 -403 KB 🎉
Bundle Size Analyzer Link Link

@storybook/codemod

Before After Difference
Dependency count 198 198 0
Self size 44 KB 32 KB 🎉 -12 KB 🎉
Dependency size 84.85 MB 84.46 MB 🎉 -392 KB 🎉
Bundle Size Analyzer Link Link

create-storybook

Before After Difference
Dependency count 74 74 0
Self size 1.09 MB 1.09 MB 🚨 +799 B 🚨
Dependency size 52.87 MB 52.48 MB 🎉 -392 KB 🎉
Bundle Size Analyzer node node

@storybook/mcp

Before After Difference
Dependency count 11 11 0
Self size 145 KB 107 KB 🎉 -37 KB 🎉
Dependency size 2.64 MB 2.64 MB 0 B
Bundle Size Analyzer Link Link

@storybook/react

Before After Difference
Dependency count 59 59 0
Self size 1.46 MB 1.45 MB 🎉 -12 KB 🎉
Dependency size 12.27 MB 12.27 MB 🚨 +4 B 🚨
Bundle Size Analyzer Link Link

@storybook/vue3

Before After Difference
Dependency count 90 90 0
Self size 118 KB 102 KB 🎉 -16 KB 🎉
Dependency size 18.10 MB 18.10 MB 0 B
Bundle Size Analyzer Link Link

@valentinpalkovic
valentinpalkovic marked this pull request as ready for review August 13, 2026 13:34
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 43 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 344d6827-8da3-4120-b696-9fffe06262cc

📥 Commits

Reviewing files that changed from the base of the PR and between 811ed7c and 3f70988.

📒 Files selected for processing (11)
  • code/frameworks/angular-vite/src/docgen/story-docs-args.ts
  • code/frameworks/angular-vite/src/docgen/story-docs-build.test.ts
  • code/frameworks/angular-vite/src/docgen/story-docs-build.ts
  • code/frameworks/angular-vite/src/docgen/story-docs-markup.ts
  • code/lib/docgen-harness/src/angular/__storyshapes__/button-shapes/server-snippet-AccessorRender.snapshot
  • code/lib/docgen-harness/src/angular/__storyshapes__/button-shapes/server-snippet-DynamicOptions.snapshot
  • code/lib/docgen-harness/src/angular/__storyshapes__/button-shapes/server-snippet-ImportedTemplate.snapshot
  • code/lib/docgen-harness/src/angular/__storyshapes__/button-shapes/server-snippet-MultiExitRender.snapshot
  • code/lib/docgen-harness/src/angular/__storyshapes__/button-shapes/server-snippet-ReassignedTemplate.snapshot
  • code/lib/docgen-harness/src/angular/__storyshapes__/button-shapes/server-snippet-SpreadShadowedRender.snapshot
  • code/lib/docgen-harness/src/angular/angular-story-docs-shapes.test.ts

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

@huang-julien
huang-julien self-requested a review August 13, 2026 14:25
@valentinpalkovic
valentinpalkovic merged commit 4d267f2 into next Aug 13, 2026
152 of 158 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

angular ci:normal Run our default set of CI jobs (choose this for most PRs). feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants