Storybook for Marko is a UI development environment for your Marko components. With it, you can visualize different states of your UI components and develop them interactively.
Storybook runs outside of your app. So you can develop UI components in isolation without worrying about app specific dependencies and requirements.
@storybook/marko
>= 7 Only supports Marko 5+. For Marko 4 support use@storybook/marko@6
.
cd my-marko-app
npx sb init --type marko --builder webpack5
For more information visit: storybook.js.org
Story functions in Marko are expected to return an object with two properties.
component
: the template to renderinput
: theinput
to render the template with
// button.stories.js
import Button from "./button.marko";
export const Primary = () => ({
component: Button,
input: {
primary: true,
label: "Button",
},
});
Often a .stories.js
file will export multiple stories using the same .marko
template.
To simplify things you can set a component
property on the default export
meta data.
This will act as the default component
to render for each story function.
import Button from "./button.marko";
export default {
title: "Button",
component: Button,
};
export const Primary = () => ({
input: {
primary: true,
label: "Button",
},
});
export const Secondary = () => ({
input: {
primary: false,
label: "Button",
},
});
Storybooks args
provide a way to better document, simplify and configure the input passed to your templates.
Each story function will receive args
as the first parameter, or you can simply export an object with the story meta (including args
).
import Button from "./button.marko";
export default {
title: "Button",
component: Button,
};
// When exporting a function, args are received.
export const Primary = (args) => ({ input: args });
Primary.args = {
primary: true,
label: "Button",
};
// Alternatively export an object with args which
// will always render the default exported component.
export const Secondary = {
args: {
primary: false,
label: "Button",
},
};
Storybook decorators
provide a way to wrap a component with another component to provide context, styling, or additional functionality.
With @storybook/marko
your decorators must be a function that returns the same signature as the story functions.
The component
specified in the decorator will be provided a renderBody
which can be used to render the nested Story
or another decorator.
import Button from "./button.marko";
import Decorator from "./decorator.marko";
export default {
title: "Button",
component: Button,
decorators: [
() => ({
component: Decorator,
input: {
// optionally pass some input to the decorator
},
}),
],
};
export const Primary = {
args: {
// ...
},
};
Some types are exposed by this module to make it easier to write your stores using TypeScript. Here is a simple story using the exposed types.
import type { Story, Meta } from "@storybook/marko";
import Button from "./button.marko";
interface ButtonInput {
primary?: boolean;
label: string;
}
export default {
title: "Button",
component: Button,
} as Meta<ButtonInput>;
export const Primary: Story<ButtonInput> = {
args: {
primarrrrry: true, // Will error with typescript!
},
};
@storybook/marko
also ships with tools to make loading and rendering your stories in your tests easy! See our testing documentation for more details.