storybookjs / addon-svelte-csf

[Incubation] CSF using Svelte components.
MIT License
111 stars 32 forks source link

Request: typescript usage examples #162

Open Masstronaut opened 11 months ago

Masstronaut commented 11 months ago

The docs don't have great examples demonstrating how to use the svelte CSF with typescript support. as an example, with <Meta> now deprecated in favor of

<script context="module">
export const meta = { //... 
}
</script>

It would be great to have an example of how to correctly type this (and possibly add the necessary typescript typings as well). I would imagine it should look something like this, but as far as I can tell there is only MetaProps which is not a generic so isn't really type safe for a specific component (ie args):

<script context="module" lang="ts">
import type {MetaProps} from "@storybookjs/addon-svelte-csf"
import MyComponent from "./MyComponent.svelte"
export const meta = ({
 // ...
}) satisfies MetaArgs<MyComponent>;
</script>

If someone can point me to the right type I'm happy to make a PR for the docs changes myself.

Similarly, it would be great to have a generic typing for StoryProps for the same reason.

sacrosanctic commented 9 months ago
<script context="module" lang="ts">
import type { Meta } from '@storybook/svelte'
import MyComponent from './MyComponent.svelte'

export const meta: Meta = {
  // ...
}
</script>

Is this the same thing?

xeho91 commented 5 months ago
<script   context="module" lang="ts">
import type { Meta } from '@storybook/svelte'
import MyComponent from './MyComponent.svelte'

export const meta: Meta = {
  // ...
}
</script>

Is this the same thing?

Late to the party, but the correct usage would be:

<script context="module" lang="ts">
import type { Meta } from '@storybook/svelte'
import MyComponent from './MyComponent.svelte'

- export const meta: Meta = {
+ export const meta = {
  // ...
- }
+ } satisfies Meta<MyComponent>;
</script>
Masstronaut commented 3 months ago

Okay I've looked at it again and believe I've figured out how to get everything typed. Can you confirm this looks correct to you @xeho91 ?

<!-- MyComponent.stories.svelte -->
<script lang="ts" context="module">
  import MyComponent from './MyComponent.svelte';
  import type { Meta } from '@storybook/svelte';
  export const meta = {
    component: MyComponent,
    // title, parameters, etc... 
  } satisfies Meta<MyComponent>;
</script>
<script lang="ts">
  import { Story, Template } from '@storybook/addon-svelte-csf';
  import type { StoryObj } from '@storybook/svelte';

  type StoryArgs = StoryObj<typeof Meta>;

  const aStory = {
    args: {
      // component props for this story go here
    },
    // NOTE: Specifying the name here causes storybook to fail to dynamically import the component
    // name: "MyComponent story"
  } satisfies StoryArgs;
</script>

<!-- setup the template for rendering stories -->
<Template let:args>
  <MyComponent {...args} />
</Template>

<!-- Uses the template. Note the name MUST be specified here, not in the StoryArgs objects -->
<Story name="MyComponent story" {...aStory} />

This seems to be fully typed on my end, with the caveat (bug?) that setting name or storyName on a StoryArgs object instead of directly on a <Story name="..."> tag causes the storybook renderer to fail.

If you're happy with this usage/example I'm happy to open a PR updating the example stories and readme to reflect this usage.

JReinhold commented 2 months ago

That looks correct from a typings perspective, it does have some caveats though. As you've found out, name has to be defined as a direct prop, as do template and tags, as we do static analysis to extract those on the server.

Feel free to open a PR to document this.

As a sidenote, the name StoryArgs feels off, as it contains args as property and other things. StoryProps might be better?

Finally, the upcoming major version of the addon that supports Svelte 5 will have a different API that is a lot more typesafe by default without these workarounds. See https://github.com/storybookjs/addon-svelte-csf/discussions/191