Developing UI components is sometimes a highly visual effort. We continuously want to have feedback on how a particular change affects our component rendering and adjust accordingly. Most often, as a developer, we include these components in their target applications, just to get that visual feedback. This is far from ideal though.
Storybook solves exactly this! It allows you to develop components in isolation and experiment with the inputs and outputs of a component. Furthermore, once the Storybook story is fully developed, it can serve as documentation for other developers to explore.
Prefer to read along as well? Here's the accompanying article.
Instructor: [0:00] On my current blog on yuri.dev, I have this Collections page. This is nothing else than a collection of all of my categories I've been writing about. You can see here Nx, Next.js, Angular, React, Node, and so on, and many other topics.
[0:13] Now, what I would want to have on my new blog is something similar. To get started, let's create the infrastructure for such a button, so we can use it on a new blog as well. The first step, again, would be to create a new library. I'm going to call it Shared-UI, which would contain all those shared UI components which I might use across my Nx workspace.
[0:36] Let's use, again, nx console, click Generate, and hit Library. I want to create a React library in this case. Let's call it ui. We use CSS. The directory is shared, because I want to place it under this shared directory which we already have for the MDX elements. We can leave all the other parts as they are right now. Let me hit Run and generate this library. We can see under that shared folder, we have our new UI library. It is set up already with Jest and Babel, and all the config which we need for our React library. It also created for me here, such an empty spec module CSS, and also an empty component.
[1:19] Let me create a new topic button in this new library. I'm using the Nx generator again. This time, I'm using the component generator. The name is topic-button. I'm using style.css. The project would be Shared-UI. Then, we can hit Enter.
[1:38] We also want to export the button, to be used outside. We have this new button inside, here inside a specific folder. Right now, it is empty. We can start implementing it here. Let's also clean up here, these React components which you might not need anymore. We also should make sure that we remove them here from the index.ts file.
[2:00] When we start developing our button, we definitely want to do this in an interactive fashion, where we want to see how the UI changes as we add new stuff to our button. One way to do that would be to directly embed it into one of the pages of our Next.js application right now, but we want to do it even in a more elegant fashion. We want to use Storybook for that purpose.
[2:21] Storybook allows you to develop these components independently, by launching it inside so-called Storybook, where we can see all the configuration options the component has, we can test them out interactively, directly while rendering the component, which leads to a very nice developer experience.
[2:37] Furthermore, you can also then use those stories as a documentation for other developers to understand and explore, what components are available within your workspace.
[2:46] Let's add some Storybook support to our library. Luckily, Nx already comes with a generator also for Storybook. We can go here to the Nx console again, invoke a generator now with the Storybook configuration. We give the project name, which is Shared-UI.
[3:04] Then, basically, it allows us to specify a couple of options here. We can give it a directory for our end-to-end tests. We can have here Storybook-e2e to group all the Storybook end-to-end tests in the sub-directory. We can also tell the generator to generate Cypress specs for us. We will do that, we will explore that in a later video.
[3:25] Also, to generate a Story, such that for our current topic Button, it would also generate out a Story. Let's hit Run here. Let's explore what we got from this generator. If we go back here to our explorer, we can see we got a new Storybook folder at the very top level of our workspace, which contains a main.js and a config.
[3:45] Now, this is the Storybook config that will apply to all the Stories that are, potentially, within our Nx workspace. This gives us the opportunity, for instance, to register common Storybook addons and presets, which we want to have at a global level.
[3:58] Furthermore, here in the Apps folder, we got that Storybook-e2e folder with our UI-e2e folder as well. This is a new Cypress project that has already been set up for our Storybook. As I mentioned, we will explore this in a bit.
[4:12] In our library, in our Shared-UI, we also got a Storybook setup with the project-specific Storybook configuration. You can see here, the Stories are being loaded in. There is also a preset register that comes from the @nrwl/react package. This will make sure that it works seamlessly with the Nx workspace. Furthermore, you can then add standard Storybook configurations in here.
[4:35] Another thing that happened, is also the generation of such a Story for us. Here, we can see that generator already created a simple scaffold of a story, which we then can use and expand furthermore, as we need it.
[4:47] Finally, in our workspace.json, which is at the very root of our Nx monorepo, we have a new Storybook target that has been added to our library. Our Shared-UI now has the ESLint and test, but it now also has a Storybook target, as well as this build-storybook target. These allow us, first of all, to add additional configuration, but also to launch our Storybook locally.
[5:11] Let's have a look at how that works. We can now invoke the target just as we would usually, by invoking nx storybook shared-ui. This now bootstraps Storybook for us. We can go to localhost:4400 and then see our Storybook in action. Here, you see now the topic Button which you created, which renders the button in the Storybook.
Are you running into any issue Michael? In case, can you post some details here?
If anyone has a solution to this I am all ears.