Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
@storybook/addon-svelte-csf
Advanced tools
Allows to write stories in Svelte syntax
This Storybook addon allows you to write Storybook stories using the Svelte language instead of ESM that regular CSF is based on.
npx storybook@latest add @storybook/addon-svelte-csf
Using the Svelte language makes it easier to write stories for composed components that rely on snippets or slots, which aren't easily re-created outside of Svelte files.
[!TIP] If you've initialized your Storybook project with Storybook version 8.2.0 or above, this addon is already set up for you!
[!IMPORTANT]
Not running the latest and greatest versions of Storybook or Svelte? Be sure to check the version compatibility section below.
The easiest way to install the addon is with storybook add
:
npx storybook@latest add @storybook/addon-svelte-csf
You can also add the addon manually. First, install the package:
npm install --save-dev @storybook/addon-svelte-csf
Then modify your main.ts
Storybook configuration to include the addon and include *.stories.svelte
files:
export default {
- stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
+ stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx|svelte)'],
addons: [
+ '@storybook/addon-svelte-csf',
...
],
...
}
Restart your Storybook server for the changes to take effect.
[!NOTE] The documentation here does not cover all of Storybook's features, only the aspects that are specific to the addon and Svelte CSF. We recommend that you familiarize yourself with Storybook's core concepts at https://storybook.js.org/docs.
The examples
directory contains examples describing each feature of the addon. The Button.stories.svelte
example is a good one to get started with. The Storybook with all the examples is published on Chromatic here.
Svelte CSF stories files must always have the .stories.svelte
extension.
All stories files must have a "meta" (aka. "default export") defined, and its structure follows what's described in the official docs on the subject. To define the meta in Svelte CSF, call the defineMeta
function within the module context, with the meta properties you want:
<script module>
// 👆 notice the module context, defineMeta does not work in a regular <script> tag - instance
import { defineMeta } from '@storybook/addon-svelte-csf';
import MyComponent from './MyComponent.svelte';
// 👇 Get the Story component from the return value
const { Story } = defineMeta({
title: 'Path/To/MyComponent',
component: MyComponent,
decorators: [
/* ... */
],
parameters: {
/* ... */
},
});
</script>
defineMeta
returns an object with a Story
component (see Defining stories below) that you must destructure out to use.
To define stories, you use the Story
component returned from the defineMeta
function. Depending on what you want the story to contain, there are multiple ways to use the Story
component. Common for all the use case is that all properties of a regular CSF story are passed as props to the Story
component, with the exception of the render
function, which does not have any effect in Svelte CSF.
All story requires either the name
prop or exportName
prop.
[!TIP] In versions prior to v5 of this addon, it was always required to define a template story with the
<Template>
component. This is no longer required and stories will default to render the component frommeta
if no template is set.
If your component only accepts props and doesn't require snippets or slots, you can use the simple form of defining stories, only using args:
<Story name="Primary" args={{ primary: true }} />
This will render the component defined in the meta, with the args passed as props.
If you need more customization of the story, like composing components or defining snippets, you can pass in children to the Story
, and write whatever component structure you desire:
<Story name="Composed">
<MyComponent>
<AChild label="Hello world!" />
</MyComponent>
</Story>
[!IMPORTANT]
This format completely ignores args, as they are not passed down to any of the child components defined. Even if your story has args and Controls, they won't have an effect. See the snippet-based formats below.
If you need composition/snippets but also want a dynamic story that reacts to args or the story context, you can define a children
snippet in the Story
component:
<Story name="Simple Children" args={{ simpleChild: true }}>
{#snippet children(args)}
<MyComponent {...args}>Component with args</MyComponent>
{/snippet}
</Story>
Often your stories are very similar and their only differences are args or play-functions. In this case it can be cumbersome to define the same children
snippet over and over again. You can share snippets by defining them at the top-level and passing them as props to Story
:
{#snippet template(args)}
<MyComponent {...args}>
{#if args.simpleChild}
<AChild data={args.childProps} />
{:else}
<ComplexChildA data={args.childProps} />
<ComplexChildB data={args.childProps} />
{/if}
</MyComponent>
{/snippet}
<Story name="Simple Children" args={{ simpleChild: true }} children={template} />
<Story name="Complex Children" args={{ simpleChild: false }} children={template} />
You can also use this pattern to define multiple templates and share the different templates among different stories.
If you only need a single template that you want to share, it can be tedious to include children={template}
in each Story
component. Like in th example below:
<Story name="Primary" args={{ variant: 'primary' }} children={template} />
<Story name="Secondary" args={{ variant: 'secondary' }} children={template} />
<Story name="Tertiary" args={{ variant: 'tertiary' }} children={template} />
<!-- ... more ... -->
<Story name="Denary" args={{ variant: 'denary' }} children={template} />
In this case you can use the setTemplate()
helper function that sets a default template for all stories. In regular CSF terms, this is the equivalent of defining a meta-level render
-function versus story-level render
-functions:
<script module>
import { defineMeta, setTemplate } from '@storybook/addon-svelte-csf';
// 👆 import the function
import MyComponent from './MyComponent.svelte';
const { Story } = defineMeta({
/* ... */
});
</script>
<script>
// 👆 note this must be within a instance (regular) <script> tag as the module context can not reference snippets defined in the markup
setTemplate(template);
// 👆 the name of the snippet as defined below (can be any name)
</script>
{#snippet template(args)}
<MyComponent {...args}>
{#if args.simpleChild}
<AChild data={args.childProps} />
{:else}
<ComplexChildA data={args.childProps} />
<ComplexChildB data={args.childProps} />
{/if}
</MyComponent>
{/snippet}
<Story name="Simple Children" args={{ simpleChild: true }} />
<Story name="Complex Children" args={{ simpleChild: false }} />
Stories can still override this default snippet using any of the methods for defining story-level content.
Behind-the-scenes, each <Story />
definition is compiled to a variable export like export const MyStory = ...;
. In most cases you don't have to care about this detail, however sometimes naming conflicts can arise from this. The variable names are simplifications of the story names - to make them valid JavaScript variables.
This can cause conflicts, eg. two stories with the names "my story!" and "My Story" will both be simplified to MyStory
.
You can explicitly define the variable name of any story by passing the exportName
prop:
<Story exportName="MyStory1" name="my story!" />
<Story exportName="MyStory2" name="My Story" />
At least one of the name
or exportName
props must be passed to the Story
component - passing both is also valid.
If for some reason you need to access the Story context (e.g. for mocking) while rendering the story, then <Story />
's attribute children
snippet provides an optional second argument.
<Story name="Default">
{#snippet children(args, context)}
<!-- 👆 use the optional second argument to access Story context -->
<MyComponent {...args}>
{/snippet}
</Story>
Story snippets and args can be type-safe when necessary. The type of the args are inferred from the component props passed to defineMeta
.
You can make your snippets type-safe with the Args
and StoryContext
helper types:
<script module lang="ts">
import { defineMeta, type Args, type StoryContext } from '@storybook/addon-svelte-csf';
// 👆 👆 import those type helpers from this addon -->
import MyComponent from './MyComponent.svelte';
const { Story } = defineMeta({
component: MyComponent,
});
</script>
<!-- 👇 use to infer `args` type from the `Story` component -->
{#snippet template(args: Args<typeof Story>, context: StoryContext<typeof Story>)}
<!-- 👆 use to infer `context` type from the `Story` component -->
<MyComponent {...args} />
{/snippet}
If you need to customize the type of the args
, you can pass in a generic type parameter to defineMeta
that will override the types inferred from the component:
const { Story } = defineMeta<{ anotherProp: boolean }>( ... );
Version 5 of the addon changes the API from v4 in key areas, as described above. However a feature flag has been introduced to maintain support for the <Template>
-based legacy API as it was prior to v5.
To enable supoprt for the legacy API, make the following change to your main Storybook config:
export default {
addons: [
- '@storybook/addon-svelte-csf',
+ {
+ name: '@storybook/addon-svelte-csf',
+ options: {
+ legacyTemplate: true
+ },
...
],
...
}
This can make the overall experience slower, because it adds more transformation steps on top of the existing ones. It should only be used temporarily while migrating to the new API. It's highly likely that the legacy support will be dropped in future major versions of the addon.
The legacy support is not bullet-proof, and it might not work in all scenarios that previously worked. If you're experiencing issues or getting errors after upgrading to v5, try migrating the problematic stories files to the modern API.
Version 5 and up of this addon requires at least:
Dependency | Version |
---|---|
Storybook | v8.0.0 |
Svelte | v5.0.0 |
Vite | v5.0.0 |
@sveltejs/vite-plugin-svelte | v4.0.0 |
[!IMPORTANT] As of
v5
this addon does not support Webpack.
npm install --save-dev @storybook/addon-svelte-csf@^4
Version 4 of this addon requires at least:
@sveltejs/vite-plugin-svelte
v2 (if using Vite)npm install --save-dev @storybook/addon-svelte-csf@^3
Version 3 of this addon requires at least:
npm install --save-dev @storybook/addon-svelte-csf@^2
If you're using Storybook between v6.4.20 and v7.0.0, you should use version ^2.0.0
of this addon.
This project uses pnpm for dependency management.
pnpm install
pnpm start
.FAQs
Allows to write stories in Svelte syntax
The npm package @storybook/addon-svelte-csf receives a total of 33,341 weekly downloads. As such, @storybook/addon-svelte-csf popularity was classified as popular.
We found that @storybook/addon-svelte-csf demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.