storybookjs / addon-svelte-csf

[Incubation] CSF using Svelte components.
MIT License
98 stars 29 forks source link

Export typed Story and Template components #155

Open j3rem1e opened 8 months ago

j3rem1e commented 8 months ago

Should implements #152

I`m not sure about the syntax however, but it works in vscode (invalid args or use of args are flagged as errors)

<script context="meta">
  import { makeFrom } from "@storybook/addon-svelte-csf";
  import Button from "./Button.svelte";
  const { Template, Story } = makeFrom(Button);

  export const meta = {
    component: Button
  }
</script>

<Template let:args>
  <!- args is typed here -->
   <Button {...args}/>
</Template>

<!-- args is type checked here -->
<Story args={{rounded: false}}/>
j3rem1e commented 7 months ago

@JReinhold what do you think of this PR ? I have doubts about the syntax/name of the export..

JReinhold commented 7 months ago

Hmm, I see what you're trying to do. Is there a type-only way to achieve this, without the helper function? That would be closer to regular CSF.

<script context="module">
  import type { Meta, StoryObj } from '@storybook/svelte';
  import * as SvelteCsf from "@storybook/addon-svelte-csf";
  import Button from "./Button.svelte";

  export const meta = {
    component: Button,
  } satisfies Meta<Button>;

  const { Template, Story } = SvelteCsf as {
    Template: SvelteCsf.Template<typeof meta>;
    Story: SvelteCsf.Story<typeof meta>
  }
</script>

<Template let:args>
  <!- args is typed here -->
   <Button {...args}/>
</Template>

<!-- args is type checked here -->
<Story args={{rounded: false}}/>
For reference, here's the regular CSF version that works today: ```ts import type { Meta, StoryObj } from '@storybook/svelte'; import { Button } from './Button'; const meta = { component: Button, } satisfies Meta

I also see your helper function makes it less verbose though, which is nice.

  1. I'd recommend it's based on the meta and not on the component, since you could define custom argTypes on the meta that can't be inferred from the component
  2. how about typed() instead?
<script context="module">
  import { typed } from "@storybook/addon-svelte-csf";
  import Button from "./Button.svelte";

  export const meta = {
    component: Button,
    argTypes: {...}
  }

  const { Template, Story } = typed(meta);
</script>

<Template let:args>
  <!- args is typed here -->
   <Button {...args}/>
</Template>

<!-- args is type checked here -->
<Story args={{rounded: false}}/>
j3rem1e commented 7 months ago

I implemented your advice: it's spelled "typed" now, and accepts a meta export as the argument (as well as a Component). However, it doesn't work if I add a custom argTypes in the export with an obscure typescript error..

with:

export function typed<Args>(meta?: Meta<Args>): StoriesComponents<Props>;

image

it works with a meta without argTypes, or a component though.

xeho91 commented 1 month ago

I don't want this PR to go stale, so I'd like to bump.

For the backwards compatibility of this addon (for svelte v4). Should we continue with this pattern of using typed(meta) helper function, or directly consume meta as prop to components? - <Story {meta} /> / <Template {meta} />

Discussion on Discord for reference: https://discord.com/channels/486522875931656193/1237378119678300190/1239432547184676945

JReinhold commented 1 month ago

However, it doesn't work if I add a custom argTypes in the export with an obscure typescript error..

I still think this is a blocker here.

Should we continue with this pattern of using typed(meta) helper function, or directly consume meta as prop to components? - <Story {meta} /> / <Template {meta} />

Personally I like the second option best because it's more direct, but no string opinion.