Adding Storybook into Your Nx Monorepo
When your project scaling up, it’s becoming increasingly important to have a single source of truth which contains all the knowledge about your UI components.
To achieve this goal we will use Storybook. it’s a popular open-source tool that provides a centralized environment for showcasing components, testing them, and documenting their use and behavior.
Prerequisites:
Creating Nx workspace
run the following command in order to create a new Nx workspace
npx create-nx-workspace@latest my-workspace
choose the following options in the interactive cli (based on v15.7.0):
- what to create: integrated monorepo
- What to create in the new workspace: Angular
- Application name: your angular app name for example client-app
- Would you like to use Standalone Components in your application? no
- Would you like to add routing? yes
- Default stylesheet format: Sass
- Enable distributed caching to make your CI faster: No
now grab a cup of coffee while the cli installs all the dependancies and creates your workspace.
For the example we are going to create a single button component inside an Angular library.
Create a new library by running the following command:
if @nrwl/cli not installed globally on your machine run the following command
npm i -g @nrwl/cli@latest
nx g @nrwl/angular:library ui-lib --publishable --importPath @my-workspace/ui-lib
Setting Up Storybook
first we are going to install @nrwl/storybook package
open terminal in your workspace directory and run the following command:
npm install -D @nrwl/storybook
now we will generate storybook configuration to our project.
nx g @nrwl/storybook:configuration ui-lib --tsConfiguration=true
choose the following options in the interactive cli:
- What UI framework plugin should storybook use: @storybook/angular
- Configure a cypress e2e app to run against the storybook instance: true
- Which Storybook builder do you want to use: Webpack
Nx will take care about all the installation and configuration, so seat back and relax.
Creating first story in storybook
in order serve storybook locally, run the following command:
nx run ui-lib:storybook
now your should be able to navigate to http://localhost:4400 and see an empty storybook
lets create our button component inside ui-lib library
nx g @nrwl/angular:component button --project ui-lib
and generate story by running the following command:
nx g @nrwl/angular:stories ui-lib
choose the following options in the interactive cli:
- do you want to generate Cypress specs as well? yes
UI component implementation
button.component.ts:
import { Component, Input } from '@angular/core';
@Component({
selector: 'my-workspace-button',
template: `<button [disabled]="isDisabled">{{ btnText }}</button> `,
styleUrls: ['./button.component.scss'],
})
export class ButtonComponent {
@Input() isDisabled = false;
@Input() btnText = '';
}
button.component.scss:
:host {
button {
height: 43px;
border-radius: 24.5px;
font-size: 16px;
min-width: 200px;
min-height: 45px;
background-color: #c61f13;
color: #fff;
border: none;
cursor: pointer;
&:disabled {
cursor: not-allowed;
filter: grayscale(100%);
}
}
}
button.component.stories.ts:
import { moduleMetadata, Story, Meta } from '@storybook/angular';
import { ButtonComponent } from './button.component';
export default {
title: 'ButtonComponent',
component: ButtonComponent,
decorators: [
moduleMetadata({
imports: [],
}),
],
} as Meta<ButtonComponent>;
const Template: Story<ButtonComponent> = (args: ButtonComponent) => ({
props: args,
});
export const Primary = Template.bind({});
Primary.args = {
isDisabled: false,
btnText: 'Learn More',
};
export const Disabled = Template.bind({});
Disabled.args = {
isDisabled: true,
btnText: 'Learn More',
};
we are passing button Inputs by args property:
Primary.args = {
isDisabled: true,
btnText: 'Learn More',
};
and the end result should be:
Conclusion
Storybook provides a powerful platform for creating, reviewing and testing UI components. By using it as a single source of truth for the project UI components, it allows to build and maintain a consistent design system.
In this article, we’ve seen how to integrate Storybook into Nx monorepo, create a new UI component, and configure Storybook to display different states of the UI component.