Skip to content

Svelte: Support meta.type<>() in Svelte CSF files - #36693

Merged
valentinpalkovic merged 2 commits into
jeppe/sb-2212-svelte-csf-accept-previewmeta-and-compile-to-csf4-factoriesfrom
jeppe/sb-2214-svelte-csf-support-metatype
Oct 15, 2026
Merged

valentinpalkovic merged 2 commits into
jeppe/sb-2212-svelte-csf-accept-previewmeta-and-compile-to-csf4-factoriesfrom
jeppe/sb-2214-svelte-csf-support-metatype

Conversation

@JReinhold

@JReinhold JReinhold commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Closes #

What I did

A Svelte CSF file can now destructure more Story components from meta.type<…>(), to add args that the component doesn't declare. A file can mix them with the plain Story. Linear: SB-2214. This PR is stacked on #36691.

Before and after

The same stories file, compiled before this PR (the tip of #36691) and with this PR. This is the real output of the Svelte compiler (production mode) followed by the Svelte CSF transform, from the meta down. I replaced the compiled Svelte component with a comment.

Source (Button.stories.svelte):

<script module lang="ts">
  import preview from '#.storybook/preview';
  import Button from './Button.svelte';

  const meta = preview.meta({ component: Button, args: { disabled: false } });
  const { Story } = meta;
  const { Story: IconStory } = meta.type<{ args: { icon: string } }>();
</script>

<Story name="Primary" args={{ label: 'Primary' }} />

<IconStory name="Icon" args={{ label: 'Icon', icon: '★' }}>
  {#snippet template({ icon, ...args })}
    <Button {...args} label={icon} />
  {/snippet}
</IconStory>

Before: <IconStory> renders at runtime, but the compiler and the indexer don't know it, so the Icon story is dropped without an error:

const meta = preview.meta({
	component: Button,
	args: { disabled: false }
});
const { Story } = meta;
const { Story: IconStory } = meta.type();
// … the compiled Svelte component …
import { createRuntimeStories } from "@storybook/svelte/internal/svelte-csf/create-runtime-stories";

const $__stories = createRuntimeStories(Button_stories, meta.input);

export const __namedExportsOrder = ["Primary"];

const $__Primary = meta.story({
	...$__stories["Primary"],
	tags: ["svelte-csf-v5"]
});

export { $__Primary as Primary };

After:

const meta = preview.meta({
	component: Button,
	args: { disabled: false }
});
const { Story } = meta;
const { Story: IconStory } = meta.type();
// … the compiled Svelte component …
import { createRuntimeStories } from "@storybook/svelte/internal/svelte-csf/create-runtime-stories";

const $__stories = createRuntimeStories(Button_stories, meta.input);

export const __namedExportsOrder = ["Primary", "Icon"];

const $__Primary = meta.story({
	...$__stories["Primary"],
	tags: ["svelte-csf-v5"]
});

const $__Icon = meta.story({
	...$__stories["Icon"],
	tags: ["svelte-csf-v5"]
});

export { $__Primary as Primary, $__Icon as Icon };

meta.type() returns the same meta at runtime, so the stories still call meta.story(), and core's CsfFile needs no change.

How to review

  1. feat(svelte): find the Story components of meta.type<>() in Svelte CSF files. You can skim this one. The parser, the compiler and the indexer now track a list of Story names in place of one Story identifier. skipTypeCalls in utils/import-source.ts follows chains of .type() calls, for both meta.type<…>() and preview.type<…>().meta().
  2. test: the test cases for meta.type<>() in Svelte CSF files. Review this one. It has the compiler, Vitest-transform and indexer snapshots of a file that mixes Story and IconStory, a runtime stories file, and the type fixtures.

Choices to review:

  • No type changes. SvelteMeta.type<S>() from Svelte: Add CSF factories with definePreview #36669 already returns a meta whose Story has the args of S, with the core TypedMetaArgKeys rule. type-checks-meta-type.svelte ports the meta.type<>() cases of the CSF4 type tests to Story components, and svelte-check passes.
  • Supported forms: const { Story: IconStory } = meta.type<…>(), chains such as meta.type<A>().type<B>(), and more than one declarator in a const. Not supported: a typed meta in its own variable (const typed = meta.type<…>(); const { Story: X } = typed;), and preview.meta(…).type<…>() directly in the meta declaration. The issue doesn't list them.
  • preview.type<…>().meta() was already found in Svelte: Accept preview.meta() in Svelte CSF files #36691. This PR adds its full compiler snapshot.
  • Known limit, from Svelte: Accept preview.meta() in Svelte CSF files #36691: a story with a template snippet must set every required arg of the component, also a required children. This holds for Story and IconStory alike.

Evidence

  • Compiler, Vitest transform and indexer: full snapshots of a file with Story and IconStory. The Vitest transform makes a test for each story.
  • Runtime: meta-type.stories.svelte runs both stories with Story.run(), and a test checks that both are exported.
  • Types: type-checks-meta-type.svelte covers a required extra arg, a meta arg that type<>() declares again, optional args, the inferred template and play args, Args<typeof IconStory>, and the composition with preview.type<>(), decorators and a chained type<>().
  • Invariants hunt: all 50 .stories.svelte files in the repo compile byte-identically and give the same index entries before and after this PR. All 6 orders of three Story components give matching index entries, export order, exports and Vitest tests. The hunt found that a Story component in the second declarator of a const was dropped, and this PR fixes that.
  • Sandbox (svelte-kit/skeleton-ts, with definePreview): an IconStory in a factory .stories.svelte file is in the index, renders, and passes its play function in the UI and in addon-vitest (Chromium).

Interactions panel: the play function of a meta.type<>() story passes

Merge Danger

Door: two-way. The change adds support for more Story components. Files without meta.type<>() compile as before.

Blast Radius: small. Only the Svelte CSF parser, compiler and indexer change, and the hunt shows byte-identical output for every existing .stories.svelte file in the repo.

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

Caution

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

  1. Set up the sandbox from the manual testing steps of Svelte: Accept preview.meta() in Svelte CSF files #36691.

  2. In src/factories/Button.stories.svelte, change const { Story } = preview.meta(…) to const meta = preview.meta(…) and const { Story } = meta;. Then add:

    <script module lang="ts">
      // after `const { Story } = meta;`
      const { Story: IconStory } = meta.type<{ args: { icon: string } }>();
    </script>
    
    <IconStory name="Icon" args={{ icon: '★' }}>Icon</IconStory>
  3. Run yarn storybook. Check that the sidebar has the "Icon" story, and that its Controls panel shows the icon arg with the value ★.

  4. Run yarn vitest --run --project storybook. The Icon story passes.

  5. Remove icon from the args and run yarn check. svelte-check reports that icon is missing.

Documentation

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

The docs for Svelte factories come with SB-2215.

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.

🦋 Canary Release - 🚫 Not run

This PR does not have a canary release associated.

In-repo PRs: add the ci:canary label. Later pushes republish while the label remains.

Fork PRs: the label does nothing (a later push must not auto-publish). A maintainer publishes from this repository with Run workflow and the pr input. branch and sha are optional; if more than one is set, they must be the same commit. The fork author does not need to do anything.

🤖 Generated with Claude Code

JReinhold and others added 2 commits October 9, 2026 10:16
…F files

A Svelte CSF file can destructure more `Story` components from
`meta.type<…>()`, to add args that the component doesn't declare:

  const { Story: IconStory } = meta.type<{ args: { icon: string } }>();

The parser, the compiler and the indexer now track the names of all `Story`
components, also through chains of `.type()` calls, so a file can mix `Story`
and `IconStory`. `meta.type()` returns the same meta at runtime, so the
compiled stories still call `meta.story()`. The types already supported it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cases that show what the previous commit does:

- Compiler: the full compiled module for `preview.type<>().meta()`, and for a
  file that mixes `Story` and `IconStory` (`compiler/post-transform/index.test.ts`).
- Vitest transform: a test for each story of `Story` and `IconStory`
  (`compiler/vitest-transform.test.ts`).
- Indexer and parsers: the index entries and the `Story` names of a mixed file.
- Runtime: `meta-type.stories.svelte` renders and runs both kinds of stories.
- Types: `type-checks-meta-type.svelte` has the `meta.type<>()` cases of the
  CSF4 tests as `Story` components, checked by `svelte-check`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JReinhold JReinhold added feature request ci:normal Run our default set of CI jobs (choose this for most PRs). qa:needed Pull Requests that will need manual QA prior to release. labels Oct 9, 2026
@JReinhold

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@JReinhold

Copy link
Copy Markdown
Contributor Author

@codex review

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor
Warnings
⚠️

This PR targets jeppe/sb-2212-svelte-csf-accept-previewmeta-and-compile-to-csf4-factories. The default branch for contributions is next. Please make sure you are targeting the correct branch.

Generated by 🚫 dangerJS against b707ad8

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T11:56:34.558697Z b707ad8 Draft marked ready
🔒 Security Review ✅ Completed 2026-10-09T11:56:14.712411Z b707ad8 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: b707ad855b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b18dff60-fda2-439e-9d5e-4c135d376afb

📥 Commits

Reviewing files that changed from the base of the PR and between d049175 and b707ad8.


📒 Files selected for processing (14)
  • code/renderers/svelte/src/__test__/svelte-csf-factories/meta-type.stories.svelte
  • code/renderers/svelte/src/__test__/svelte-csf-factories/svelte-csf-factories.test.ts
  • code/renderers/svelte/src/__test__/svelte-csf-factories/type-checks-meta-type.svelte
  • code/renderers/svelte/src/svelte-csf/compiler/post-transform/index.test.ts
  • code/renderers/svelte/src/svelte-csf/compiler/vitest-transform.test.ts
  • code/renderers/svelte/src/svelte-csf/indexer/parser.test.ts
  • code/renderers/svelte/src/svelte-csf/indexer/parser.ts
  • code/renderers/svelte/src/svelte-csf/parser/extract/compiled/nodes.test.ts
  • code/renderers/svelte/src/svelte-csf/parser/extract/compiled/nodes.ts
  • code/renderers/svelte/src/svelte-csf/parser/extract/compiled/stories.ts
  • code/renderers/svelte/src/svelte-csf/parser/extract/svelte/fragment-nodes.ts
  • code/renderers/svelte/src/svelte-csf/parser/extract/svelte/module-nodes.test.ts
  • code/renderers/svelte/src/svelte-csf/parser/extract/svelte/module-nodes.ts
  • code/renderers/svelte/src/svelte-csf/utils/import-source.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.



Walkthrough

The Svelte CSF parser and indexer now support multiple story component names, including names declared through meta.type<>(). Added tests cover type inference, story exports, indexing, and transformed output.

Changes

Svelte CSF meta.type support

Layer / File(s) Summary
Extract story names from metadata
code/renderers/svelte/src/svelte-csf/utils/import-source.ts, code/renderers/svelte/src/svelte-csf/parser/extract/compiled/*, code/renderers/svelte/src/svelte-csf/parser/extract/svelte/*
Metadata extraction now unwraps chained .type() calls and returns an array of story component names. Compiled and Svelte module extraction pass the names to their consumers.
Use story names in extraction and indexing
code/renderers/svelte/src/svelte-csf/parser/extract/compiled/stories.ts, code/renderers/svelte/src/svelte-csf/parser/extract/svelte/fragment-nodes.ts, code/renderers/svelte/src/svelte-csf/indexer/parser.ts, code/renderers/svelte/src/svelte-csf/indexer/parser.test.ts
Story extraction and indexing now match component names against the collected list. Tests cover multiple story declarations, including typed stories.
Check typed stories and transformed output
code/renderers/svelte/src/__test__/svelte-csf-factories/*, code/renderers/svelte/src/svelte-csf/compiler/post-transform/index.test.ts, code/renderers/svelte/src/svelte-csf/compiler/vitest-transform.test.ts
Fixtures and tests cover typed story arguments, exports, transformed output, and generated test calls for multiple stories.

Possibly related PRs

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to b707a

The supported mixed-declaration form retains both stories. No actionable merge-blocking issue remains in the reviewed changes.

✨ Finishing Touches 💡 1
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR


🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@JReinhold JReinhold self-assigned this Oct 9, 2026
@JReinhold JReinhold added svelte csf factories qa:skip Pull Requests that do not need any QA. (e.g. documentation) and removed qa:needed Pull Requests that will need manual QA prior to release. labels Oct 9, 2026
@JReinhold
JReinhold marked this pull request as ready for review October 9, 2026 11:52
@JReinhold
JReinhold requested a review from huang-julien October 9, 2026 11:52

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b707ad855b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread code/renderers/svelte/src/svelte-csf/utils/import-source.ts
@valentinpalkovic
valentinpalkovic merged commit 3ff3eeb into jeppe/sb-2212-svelte-csf-accept-previewmeta-and-compile-to-csf4-factories Oct 15, 2026
151 of 161 checks passed
@valentinpalkovic
valentinpalkovic deleted the jeppe/sb-2214-svelte-csf-support-metatype branch October 15, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:normal Run our default set of CI jobs (choose this for most PRs). csf factories feature request qa:skip Pull Requests that do not need any QA. (e.g. documentation) svelte

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants