DEV Community

SeongKuk Han
SeongKuk Han

Posted on

React TS Storybook: Using Custom Props in a Story

React TS Storybook: Appending Custom Props to a Story

Let's say you have a list component like below,

import { HTMLAttributes } from "react";

const List = ({ children, ...props }: HTMLAttributes<HTMLUListElement>) => {
  return <ul {...props}>{children}</ul>;
};

const ListItem = ({ children, ...props }: HTMLAttributes<HTMLLIElement>) => {
  return <li {...props}>{children}</li>;
};

List.Item = ListItem;

export default List;
Enter fullscreen mode Exit fullscreen mode

And for explaining how to add List.Item as List's children, you append a custom props itemCount that how many List.Item List has.

import { useMemo } from "react";
import { ComponentStory, ComponentMeta } from "@storybook/react";

import List from "./List";

export default {
  title: "Example/List",
  component: List,
  args: {
    itemCount: 1,
  },
  argTypes: {
    itemCount: { control: "number" },
  },
} as ComponentMeta<typeof List>;

const Template: ComponentStory<typeof List> = ({ itemCount, ...args }) => {
  const liComponents = useMemo(() => {
    const components = [];

    for (let i = 1; i <= itemCount; i++) {
      components.push(<List.Item>{i} Item</List.Item>);
    }

    return components;
  }, [itemCount]);

  return <List {...args}>{liComponents}</List>;
};

export const ListExample = Template.bind({});
Enter fullscreen mode Exit fullscreen mode

When you try to use the custom prop, you would get an error message like this
Property 'itemCount' does not exist on type '[Component's Props]'..

In this case, use Meta and Story instead of ComponentMeta and ComponentStory.

import { ComponentProps, useMemo } from "react";
import { Story, Meta } from "@storybook/react";

import List from "./List";

type CustomListProps = ComponentProps<typeof List> & { itemCount: number };

export default {
  title: "Example/List",
  component: List,
  args: {
    itemCount: 1,
  },
  argTypes: {
    itemCount: { control: "number" },
  },
} as Meta<CustomListProps>;

const Template: Story<CustomListProps> = ({ itemCount, ...args }) => {
  const liComponents = useMemo(() => {
    const components = [];

    for (let i = 1; i <= itemCount; i++) {
      components.push(<List.Item>{i} Item</List.Item>);
    }

    return components;
  }, [itemCount]);

  return <List {...args}>{liComponents}</List>;
};

export const ListExample = Template.bind({});
Enter fullscreen mode Exit fullscreen mode

I defined a new custom type with union operator, and I used it Meta and Story as a generic type.

first storybook example

second storybook example

Now, you can adjust a value itemCount on the website like this.


I hope this is helpful for someone :)

Happy Coding!

Top comments (0)