Search code examples
reactjstypescriptstorybook

Storybook - How to pass separate args to children component and modify them through controls


I have an Accordion component that has Accordion.Item as children. Accordion.Item can have props such as size etc. How to I pass props seperate props just for children items so that I could visually control them through storybook UI?

export const AlternativesSizes: TStory = {
  args: {
    spacing: 'sm',
    variant: 'alternative',
    hasBackgroundColor: true,
  },
  render: (args) => (
    <Accordion {...args}>
      <Accordion.Item
        id="story-17"
        title="This accordion is size 'large'"
        size="large"
      >
        <Text>
          This is the expanded content for an accordion item <b>#1</b>.{' '}
          <i>
            Here you can use various HTML <sup>tags</sup>{' '}
          </i>
          <b>
            <a href="https://cooppank.ee">And even links</a>
          </b>
          <br />
          <ul>
            <li>Use lists and other various elements</li>
            <li>Use lists and other various elements</li>
            <li>Use lists and other various elements</li>
          </ul>
        </Text>
      </Accordion.Item>
      <Accordion.Item
        id="story-18"
        title="This accordion is size 'small'"
        size="small"
      >
        This is the expanded content for an accordion item #2
      </Accordion.Item>
    </Accordion>
  ),
};

As you can see I have passe size='large' manually as a prop


Solution

  • Why not use such a structure?

      args: {
        spacing: 'sm',
        variant: 'alternative',
        hasBackgroundColor: true,
        items: [
          {
            id: 'story-17',
            title: "This accordion is size 'large'",
            size: 'large'
          },
          {
            id: 'story-18',
            title: "This accordion is size 'small'",
            size: 'small'
          }
        ]
      },

    And apply it such:

      render: (args) => (
        <Accordion {...args}>
          {args.items.map(item => 
            <Accordion.Item
              key={item.id}
              id={item.id}
              title={item.title}
              size={item.size}
            >
              //...
            </Accordion.Item>
          )}
        </Accordion>
      ),