From 610a62946d8e093fcae67dc8bb1af4d93e0fb1ad Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 13 Jan 2026 10:11:25 +0100 Subject: [PATCH 1/4] Fix TS4023: Export WebComponentsTypes and VueTypes When using CSF factories with `meta.story()`, the return type references `WebComponentsTypes` and `VueTypes` constraints, but these types were not exported from the package's public API, causing TS4023 errors: "Exported variable 'Default' has or is using name 'WebComponentsTypes'" This follows the existing pattern from @storybook/react which already exports `ReactTypes`. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- code/renderers/vue3/src/index.ts | 2 ++ code/renderers/web-components/src/index.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/code/renderers/vue3/src/index.ts b/code/renderers/vue3/src/index.ts index d6381e93d05c..389b4517fe82 100644 --- a/code/renderers/vue3/src/index.ts +++ b/code/renderers/vue3/src/index.ts @@ -5,3 +5,5 @@ export * from './public-types'; export * from './portable-stories'; export * from './preview'; + +export type { VueTypes } from './types'; diff --git a/code/renderers/web-components/src/index.ts b/code/renderers/web-components/src/index.ts index 5c4a52d61327..7addbdb00f94 100644 --- a/code/renderers/web-components/src/index.ts +++ b/code/renderers/web-components/src/index.ts @@ -9,6 +9,8 @@ export * from './framework-api'; export * from './portable-stories'; export * from './preview'; +export type { WebComponentsTypes } from './types'; + // TODO: disable HMR and do full page loads because of customElements.define // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore From a2e09fa284a8baefc38b37ea84e05032d04fc571 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 13 Jan 2026 12:53:43 +0100 Subject: [PATCH 2/4] CSF Factories: Allow kebab-case HTML attribute names in web components args When using @wc-toolkit/storybook-helpers or similar libraries that generate args with kebab-case attribute names (e.g., 'static-color'), TypeScript would error because our types only allowed camelCase property names. This adds `InferArgsFromComponent` which allows both: - camelCase properties from HTMLElementTagNameMap (type-checked) - kebab-case strings containing `-` (for HTML attributes) Since JavaScript property names cannot contain `-`, any string with a dash is definitively an HTML attribute name, making this a safe heuristic. Closes #33524 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- .../web-components/src/csf-factories.test.ts | 20 +++++++++++++++++++ code/renderers/web-components/src/preview.ts | 19 ++++++++++++------ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/code/renderers/web-components/src/csf-factories.test.ts b/code/renderers/web-components/src/csf-factories.test.ts index 902426720063..854496233169 100644 --- a/code/renderers/web-components/src/csf-factories.test.ts +++ b/code/renderers/web-components/src/csf-factories.test.ts @@ -205,3 +205,23 @@ it('Components without Props can be used', () => { const Basic = meta.story(); }); + +// https://github.com/storybookjs/storybook/issues/33524 +it('✅ Kebab-case HTML attribute names are allowed in args', () => { + const meta = preview.meta({ + component: 'my-button', + args: { + label: 'hello', + 'aria-label': 'my button', // kebab-case attribute + }, + }); + + const Basic = meta.story({ + args: { + 'data-testid': 'button-1', // kebab-case attribute + }, + }); + + expect(meta.input.args?.['aria-label']).toBe('my button'); + expect(Basic.input.args?.['data-testid']).toBe('button-1'); +}); diff --git a/code/renderers/web-components/src/preview.ts b/code/renderers/web-components/src/preview.ts index 857cafe5320b..0b5a8e8c2e19 100644 --- a/code/renderers/web-components/src/preview.ts +++ b/code/renderers/web-components/src/preview.ts @@ -59,6 +59,15 @@ type InferArgs = Simplify< type InferWebComponentsTypes = WebComponentsTypes & T & { args: Simplify> }; +/** + * Infers args from a web component's HTMLElement type, allowing both camelCase properties and + * kebab-case HTML attribute names (e.g., 'aria-label', 'data-testid', 'static-color'). + */ +type InferArgsFromComponent = Partial< + HTMLElementTagNameMap[C] +> & + Record<`${string}-${string}`, unknown>; + /** * Web Components-specific Preview interface that provides type-safe CSF factory methods. * @@ -94,22 +103,20 @@ export interface WebComponentsPreview extends Preview< C extends keyof HTMLElementTagNameMap, Decorators extends DecoratorFunction, // Try to make Exact, TMetaArgs> work - TMetaArgs extends Partial, + TMetaArgs extends InferArgsFromComponent & Partial, >( meta: { component?: C; args?: TMetaArgs; decorators?: Decorators | Decorators[]; } & Omit< - ComponentAnnotations & T['args']>, + ComponentAnnotations & T['args']>, 'decorators' | 'component' | 'args' > ): WebComponentsMeta< - InferWebComponentsTypes, Decorators>, + InferWebComponentsTypes, Decorators>, Omit< - ComponentAnnotations< - InferWebComponentsTypes, Decorators> - >, + ComponentAnnotations, Decorators>>, 'args' > & { args: {} extends TMetaArgs ? {} : TMetaArgs; From 1753a9a26e6e49166dd0153560ea8e312c1652a0 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 13 Jan 2026 15:13:26 +0100 Subject: [PATCH 3/4] Chore: Add .claude to .gitignore Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6a7de9e3cf28..09afe69b6e96 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,4 @@ code/core/report .junie CLAUDE.local.md +.claude From 4fa0ad94ce7ad7633af3574027dce26d63211c35 Mon Sep 17 00:00:00 2001 From: storybook-bot <32066757+storybook-bot@users.noreply.github.com> Date: Thu, 15 Jan 2026 13:41:30 +0000 Subject: [PATCH 4/4] Write changelog for 10.2.0-alpha.19 [skip ci] --- CHANGELOG.prerelease.md | 9 +++++++++ code/package.json | 3 ++- docs/versions/next.json | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 2eda235c9da1..de6c762ad7fc 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,12 @@ +## 10.2.0-alpha.19 + +- CLIInitiate: Simplify the CLI init port flag detection - [#33546](https://github.com/storybookjs/storybook/pull/33546), thanks @ndelangen! +- CSF-Factories: Allow kebab-case HTML attribute names in web components args - [#33526](https://github.com/storybookjs/storybook/pull/33526), thanks @kasperpeulen! +- CSF-Factories: Export WebComponentsTypes and VueTypes - [#33521](https://github.com/storybookjs/storybook/pull/33521), thanks @kasperpeulen! +- Initiate: Fix used port flag handling - [#33544](https://github.com/storybookjs/storybook/pull/33544), thanks @ndelangen! +- Manager: Fix system query parameters being overridable - [#33535](https://github.com/storybookjs/storybook/pull/33535), thanks @JReinhold! +- NextJSVite: Upgrade plugin - [#33538](https://github.com/storybookjs/storybook/pull/33538), thanks @ndelangen! + ## 10.2.0-alpha.18 - Build: Fix `ejslint` execution path in lint-staged - [#33504](https://github.com/storybookjs/storybook/pull/33504), thanks @Yeonny0723! diff --git a/code/package.json b/code/package.json index 0ad1cad39cd2..f5553d7c8580 100644 --- a/code/package.json +++ b/code/package.json @@ -220,5 +220,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "10.2.0-alpha.19" } diff --git a/docs/versions/next.json b/docs/versions/next.json index 3463827282f5..77b644a04af7 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"10.2.0-alpha.18","info":{"plain":"- Build: Fix `ejslint` execution path in lint-staged - [#33504](https://github.com/storybookjs/storybook/pull/33504), thanks @Yeonny0723!\n- CLI: Detect free port when running dev during initiate - [#33532](https://github.com/storybookjs/storybook/pull/33532), thanks @ndelangen!\n- Core: Improve path handling in arg types data extraction - [#33536](https://github.com/storybookjs/storybook/pull/33536), thanks @yannbf!\n- Core: Refactor channel initialization - [#33520](https://github.com/storybookjs/storybook/pull/33520), thanks @yannbf!\n- Telemetry: Add `packageJson.type` - [#33525](https://github.com/storybookjs/storybook/pull/33525), thanks @ndelangen!\n- UI: Improve landmark navigation - [#33457](https://github.com/storybookjs/storybook/pull/33457), thanks @Sidnioulz!"}} \ No newline at end of file +{"version":"10.2.0-alpha.19","info":{"plain":"- CLIInitiate: Simplify the CLI init port flag detection - [#33546](https://github.com/storybookjs/storybook/pull/33546), thanks @ndelangen!\n- CSF-Factories: Allow kebab-case HTML attribute names in web components args - [#33526](https://github.com/storybookjs/storybook/pull/33526), thanks @kasperpeulen!\n- CSF-Factories: Export WebComponentsTypes and VueTypes - [#33521](https://github.com/storybookjs/storybook/pull/33521), thanks @kasperpeulen!\n- Initiate: Fix used port flag handling - [#33544](https://github.com/storybookjs/storybook/pull/33544), thanks @ndelangen!\n- Manager: Fix system query parameters being overridable - [#33535](https://github.com/storybookjs/storybook/pull/33535), thanks @JReinhold!\n- NextJSVite: Upgrade plugin - [#33538](https://github.com/storybookjs/storybook/pull/33538), thanks @ndelangen!"}} \ No newline at end of file