Skip to content

storybookjs/marko

Repository files navigation

Marko & Storybook Logo

Storybook for Marko
TypeScript Styled with prettier Build status NPM Version Downloads

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 Screenshot

Storybook runs outside of your app. So you can develop UI components in isolation without worrying about app specific dependencies and requirements.

Getting Started

@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

Example Stories

Basic

Story functions in Marko are expected to return an object with two properties.

  1. component: the template to render
  2. input: the input to render the template with
// button.stories.js
import Button from "./button.marko";

export const Primary = () => ({
  component: Button,
  input: {
    primary: true,
    label: "Button",
  },
});

Common component for stories

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",
  },
});

Using Args

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",
  },
};

Using Decorators

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: {
    // ...
  },
};

Using with TypeScript

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!
  },
};

Testing

@storybook/marko also ships with tools to make loading and rendering your stories in your tests easy! See our testing documentation for more details.

Docs