Introduction
Storybook is a great tool for testing, and visualizing your components in different states.
Storybook allows teams to collaborate to develop durable UIs in isolation. It allows users to implement reusable components without fussing with data, APIs, or business logic.
In this article, we will discuss how to integrate Storybook in a SvelteKit project with TypeScript, and SCSS support.
Zero-config set up
To get started, run the following in the root of an existing Svelte project:
npx sb@next init
This detects the project type, installs @storybook/svelte, and adds some sample files to demonstrate the basics of Storybook. Running npm run storybook
gives you the following zero-config set up on http://localhost:6006
Project Structure
Our project structure is already set up by SvelteKit, and Storybook initialization has created a .storybook
folder. Still, we need to make some changes to the Storybook file extension, since our project is in TypeScript. This is a snippet of the folders in our project:
βββ .storybook
βββ main.cjs
βββ preview.js
βββ preview-head.html
βββ vite.config.ts
βββ src
Add SCSS support
To add SCSS support, we need the @storybook/preset-scss
addon.
Install sass
, @storybook/preset-scss
, and other relevant style loaders.
npm i -D sass @storybook/preset-scss css-loader sass-loader style-loader
Navigate to storybook/main.cjs
Add @storybook/preset-scss
to the addons' array.
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/preset-scss' // add here
],
Add $lib alias support
Navigate to .storybook/main.cjs
.
Import mergeConfig
from Vite. This deeply merges two Vite configs.
Import path
. The path
module provides utilities for working with file, and directory paths.
Finally, we need to resolve the $lib
to point to ../src/lib
for Storybook.
async viteFinal(config) {
return mergeConfig(config, {
resolve: {
alias: { $lib: path.resolve(__dirname, '../src/lib') }
}
});
}
Your .storybook/main.cjs
should contain the following:
// .storybook/main.cjs
const { mergeConfig } = require("vite");
const path = require("path");
module.exports = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/preset-scss",
],
framework: {
name: "@storybook/sveltekit",
options: {},
},
docs: {
autodocs: "tag",
},
async viteFinal(config) {
return mergeConfig(config, {
resolve: {
alias: { $lib: path.resolve(__dirname, "../src/lib") },
},
});
},
};
Creating Stories
We will start by creating a Greeting.svelte
file that receives a message from our server.
<script lang="ts">
export let message: string;
</script>
<div class="fetch-container">
<header>
<h1>SvelteKit Fetch Data from API</h1>
</header>
<div>
Message: {message}
</div>
</div>
<style lang="scss">
.fetch-container {
text-align: center;
header {
margin: 1.25rem auto;
width: 40%;
h1 {
padding: 0.9375rem 0;
font-size: 2rem;
text-align: center;
border-bottom: 5px solid #1d4ed8;
}
}
div {
font-size: 1.2rem;
display: flex;
justify-content: center;
}
}
</style>
Then a Greeting.stories.ts
with a message argument:
import Greeting from './Greeting.svelte';
export default {
component: Greeting,
title: 'Example/Greeting',
excludeStories: /.*Data$/,
argTypes: {
message: 'from Storybook',
},
};
const Template = ({ ...args }) => ({
Component: Greeting,
props: args,
});
export const Default = Template.bind({});
Default.args = {
message: 'from This Dotβ,
};
Simply run npm run storybook
to see if your story is running:
You can edit the argument to test different messages.
Conclusion
In this article, we learned how to set up Storybook in a SvelteKit project, and created our first story.
If you are looking to bootstrap your next project, check out our starter kit that uses SvelteKit and SCSS.
Thanks for reading!
If you have any questions or run into any trouble, feel free to reach out on Twitter.