Exploring Storybook with Sveltekit
2023-06-20Challenge
I want to use Storybook with Svelte for my svelte component library. I have something that works, but I would like to take something off my plate for maintenance.
Today I’ll look into the implementation of Storybook for Svelte and see if it suites what I want
Installation
I’m going to try to add to this to my sveltekit kuix project
pnpm dlx storybook@latest init
Now try to run it…
pnpm run storybook
Did it work?
Nope. No builder configured error. Fun.
Looks like there is a package to help with specific sveltekit implementation:
https://github.com/storybookjs/storybook/tree/next/code/frameworks/sveltekit
Round 2 installation
pnpm dlx storybook@latest init
Oh wait it looks like it was already detecting it and using the svelkit prackage but still failing.
Dug a little further, looks like it configured it for @storybook/sveltekit but the package wasn’t installed
>pnpm install -D @storybook/sveltekit
Run it?
>pnpm run storybook
Beauty.
Now what?
So based on the preset items, a folder is now generated in the src folder called stories .
And in this folder you have a .svelte component file, and .stories.ts file for the doc configs
My components live in the lib folder as this is this the folder that is exported into a package from svelte-pacakge . That is okay because the stories just import the component. However, I do see the appeal of co-locating the story files with the component… but for now lets keep the components where they are.
In my lib, I have a very a basic Button component.
<script>
/**
* @type {boolean}
* @default false
*/
export let disabled = false;
/**
* @type {'regular' | 'small' | 'large'}
* @default 'regular'
*/
export let size = 'regular';
</script>
<style>
.regular {
@apply px-2.5 py-1.5;
}
</style>
<button class="bg-blue-500 rounded-md {size}" {disabled}>
<slot />
</button>
I’m going to create a Button.stories.ts file to configure the stories for this component
import Button from '$lib/prime/Button.svelte';
const meta = {
title: 'example/Button',
component: Button,
tags: ['autodocs'],
argTypes: {
size: {
control: { type: 'select' },
options: ['small', 'regular', 'large']
}
}
} satisfies Meta<Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
disabled: false
}
};
Just following the provided examples, it works rendered. Except, my Button relies on the slot to render the label, so nothing is being shown.
Can I configure the example slot?
Cannot do this with the default configuration. However, there is a package called @storybook/addon-svelte-csf that allows you to write the stories in Svelte syntax.
$ pnpm install -D @storybook/addon-svelte-csf
Then go into ./storybook/main.ts and add it to the addons
...
addons: [..., '@storybook/addon-svelte-csf'],
...
Also need to update the main.ts configuration to look for .stories.svelte files
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx|svelte)'],
Okay so it works. Great.
Conclusion
Okay to speed right to the conclusion, I ended this endeavor quite quickly. I got around to trying to write the docs and using the .mdx extension and it just became a mess.
You can embed the code into the docs, but you can’t read the source code in the snippet because its trapped behind some proxy.
Looks like more work needs to be put in to make it more usable with svelte. Perhaps in another year. I could try to hack my way through it but it just seems like you’re jumping through hoops to force something that is built for React.