DEV Community

Matheo Daninos for SensioLabs

Posted on

How to share your TwigComponent with your team ?

Quick Reminders

This article follows my previous one. If you haven't read it yet, you can do so here: Symfony Can Help You Fall in Love with Your Front-End Team.

To give you context, we are developing a small application that lets you listen to various live radio stations.

Our projects

We've adopted the principles from Component Architecture and, naturally, after designing various components of differing sizes and complexity, we are beginning to establish what is known as a design system.

Overwhelmed by All These Components?

It's common to feel overwhelmed as the number of components grows. In a team setting, or when developing new features, it's crucial to know what components are already available. When we create a new component, we want to share it immediately with our teammates.

So, how do we manage this?

Documenting everything? Yes, but it's time-consuming, and let's face it, we're developers—we tend to be a bit lazy.

But here’s some good news: there’s already a solution in the JavaScript world called Storybook!

What is Storybook?

Storybook is an exceptional tool for documenting components. It's specifically designed for this purpose, but it offers much more. It allows us to build components in isolation, test them, and mock them to see how they appear in different states or create specific end-to-end scenarios for each component, among many other features! And if you're still not convinced, just look at how beautiful your documentation can look with Storybook:

Storybook exemple

Here you can see an example of how I documented our Alert component. This documentation helps my teammates understand how to use the component and the different variations available.

Integrating Storybook with Symfony

Thanks to contributions from the community, you can now use the StorybookBundle for Symfony, developed by my friend Nicolas (not Grekas). I’m very excited about this release—not only because it involved a lot of work, but also because this bundle demonstrates that Symfony can match any front-end framework in capabilities.

To get started, install the bundle with Composer:

**composer require sensiolabs/storybook-bundle**
Enter fullscreen mode Exit fullscreen mode

Then you can use the init command to configure everything for you.

bin/console storybook:init
Enter fullscreen mode Exit fullscreen mode

Don’t run away! We gonna use npm but just to run the storybook. This will not have any impact to your project. And the bundle have an integration with AssetMapper, npm is just to start the storybook.

npm install
Enter fullscreen mode Exit fullscreen mode

And to finish

npm run storybook
Enter fullscreen mode Exit fullscreen mode

And just like that you are fully set up! You can go to: http://localhost:6006/ (it can be something else if your port is not available) to admire your storybook.

Write your first story

Let's get started! The first thing we want to do is show our Alert component in our Storybook.

import Alert from '../templates/components/Alert.html.twig';
import { twig } from '@sensiolabs/storybook-symfony-webpack5';

export default {
  component: (args) => ({
    components: {Alert},
    template: twig`
      <twig:Alert color="{{ color }}" size="{{ size }}" position="{{ position }}">
        {{ message }}
      </twig:Alert>
  `
  }),
  argTypes: {
    color: {
      options: ['blue', 'red', 'green'],
      control: {type: 'radio'},
    },
    size: {
      options: ['lg', 'md', 'sm'],
      control: {type: 'radio'},
    },
    position: {
      options: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
      control: {type: 'radio'},
    }
  }
}

export const Default = {
  args: {
    color: 'blue',
    size: 'sm',
    position: 'top-left',
    message: 'Hello world!'
  },
}
Enter fullscreen mode Exit fullscreen mode

Let me explain what we have here:

import Alert from '../templates/components/Alert.html.twig';
Enter fullscreen mode Exit fullscreen mode

We import our component template. Yes, this is Twig code, but thanks to the bundle, it works!

import { twig } from '@sensiolabs/storybook-symfony-webpack5';
Enter fullscreen mode Exit fullscreen mode

Then we import a twig function that allows us to write Twig code directly in our JavaScript.

export default {
  component: (args) => ({
    components: {Alert},
    template: twig`
      <twig:Alert color="{{ color }}" size="{{ size }}" position="{{ position }}">
        {{ message }}
      </twig:Alert>
  `
  }),
  argTypes: {
    color: {
      options: ['blue', 'red', 'green'],
      control: {type: 'radio'},
    },
    size: {
      options: ['lg', 'md', 'sm'],
      control: {type: 'radio'},
    },
    position: {
      options: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
      control: {type: 'radio'},
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Here is everything that is common to all stories related to our Alert component.

We have the component key that allows us to define our component, the Alert, and a template. We use the twig function, and everything inside can be any valid Twig code we want. Here, we simply render the Alert component and give this component props: color, size, and position.

Then we define some argTypes that allow us to describe the controls we want under the story.

Then we define our first story:

export const Default = {
  args: {
    color: 'blue',
    size: 'sm',
    position: 'top-left',
    message: 'Hello world!'
  },
}
Enter fullscreen mode Exit fullscreen mode

And just like that, we have the following result!

First story

You can play with the controls to test your component with different variations.

Then we can add more stories:

export const Large = {
  args: {
    color: 'blue',
    size: 'lg',
    position: 'top-left',
    message: 'Hello world!'
  },
}

export const Error = {
  args: {
    color: 'red',
    size: 'lg',
    position: 'top-left',
    message: 'Hello world!'
  },
}

export const Success = {
  args: {
    color: 'green',
    size: 'lg',
    position: 'top-right',
    message: 'Good job!'
  },
}
Enter fullscreen mode Exit fullscreen mode

So now, if we look at the menu of our Storybook, we have three stories:

More stories

This is great, but we can go a bit further. Add the tags: ['autodocs'] to your export default:

export default {
  component: (args) => ({
    components: {Alert},
    template: twig`
      <twig:Alert color="{{ color }}" size="{{ size }}" position="{{ position }}">
        {{ message }}
      </twig:Alert>
  `
  }),
  ...
  tags: ['autodocs']
Enter fullscreen mode Exit fullscreen mode

And just by adding this tag, Storybook creates a documentation page for us:

Storybook doc

And if that's not crazy enough, you can create a .mdx file:

import {Canvas, Controls, Meta, Story} from "@storybook/blocks";
import * as AlertStories from "./Alert.stories";

<Meta of={AlertStories} />

# Alert

An Alert display information to the user.

<Story of={AlertStories.Default} />

Here are the properties you can use on the alert component:

<Controls of={AlertStories.Default} />

## Error

For error message you can use:

<Canvas of={AlertStories.Error} />

## Success

For success message you can use

<Story of={AlertStories.Success} />
Enter fullscreen mode Exit fullscreen mode

As you can see in this .mdx file, we were able to import our stories into our documentation to make everything playable.

This is really cool! But you know what? This is only the beginning! We used Storybook to document a simple component, but Storybook can do much more. It can help with developing complex components or testing your components. We still have a lot to learn with Storybook, so stay tuned for the next article!

Thanks for reading. See you soon!

Top comments (1)

Collapse
 
youngfra profile image
Fraser Young

This was very informative! How would you handle documenting more complex components in Storybook? Would love to hear more about that in a future post!