Storybook is a tool that allows to test an app’s components in isolation and in a flat hierarchy. A storybook is a series of stories that display our components with specified inputs and outputs in a nice browser view.
Storybook has been getting really popular for React projects, and support for Angular and Vue projects was added with v3.3.0 so we can now just as easily use it for creating stories for Angular components.
Let’s quickly go over setting up Storybook for Angular as well as basic usage.
Storybook now comes with a CLI tool that makes it really easy to add it to a project. First, install the @storybook/cli package globally:
# Yarn:
$ yarn global add @storybook/cli
# or npm:
$ npm i @storybook/cli -g
Now, in the root of an Angular project, run the getstorybook command:
$ getstorybook
This command will autodetect that it’s an Angular project and will add the necessary configurations, devDependencies and npm scripts.
For example, at the time of this writing, the following devDependencies are added to the project:
"@storybook/angular": "^3.3.15",
"@storybook/addon-notes": "^3.3.15",
"@storybook/addon-actions": "^3.3.15",
"@storybook/addon-links": "^3.3.15",
"@storybook/addons": "^3.3.15",
"babel-core": "^6.26.0"
And the following npm scripts are also added to the project’s package.json file:
"scripts": {
...
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
You can now try it out by invoking the storybook npm script:
$ npm run storybook
This will start a local webpack server on port 6006 and you can visit the generated storybook by going to http://localhost:6006/. What you’ll see is an example Storybook that was generated from an index.stories.ts file under a stories folder at the root of the project. Here’s what the generated Storybook looks like:
The local server is equiped with webpack’s Hot Module Replacement (HMR) so changes to your stories will be reflected automatically in your generated storybook.
You can have a look at the generated sample stories in /stories/index.stories.ts for an example of the syntax and API.
Let’s now create a simple Card component and a few stories for it to give you an overview of Storybook’s usage. Here’s our component’s template:
<h1>{{ title }}</h1>
<h2>{{ subtitle }}</h2>
<hr *ngIf="title || subtitle">
<p>{{ content }}</p>
<button (click)="handleBtnClick()">Click me!</button>
And here’s our component’s class:
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styles: [
`
:host {
text-align: center;
background: white;
display: block;
padding: .45rem .65rem;
border-radius: 3px;
max-width: 325px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
h2 {
color: #c85f7f;
}
p {
text-align: center;
} `
]
})
export class CardComponent {
@Input('title') title;
@Input('subtitle') subtitle;
@Input('content') content = '😄';
@Output() btnClicked = new EventEmitter<boolean>();
constructor() {}
As you can see, it’s a very simple component that uses a few inputs and one output. We’re also making use of the :host selector to style our component’s shell.
Now let’s modify index.stories.ts to add a few stories for our card component:
import { storiesOf } from '@storybook/angular';
import { withNotes } from '@storybook/addon-notes';
import { action } from '@storybook/addon-actions';
import { CardComponent } from '../src/app/card/card.component';
storiesOf('Card', module)
.add('empty', () => ({
component: CardComponent,
props: {}
}))
.add('with title', () => ({
component: CardComponent,
props: {
title: 'Hello card!'
}
}))
.add('with title and subtitle', () => ({
component: CardComponent,
props: {
title: 'Hello card!',
subtitle: 'Well hello there 👋'
}
}))
.add(
'with notes',
withNotes('Just a few notes about this story...')(() => ({
component: CardComponent,
props: {}
}))
)
.add('with action', () => ({
component: CardComponent,
props: {
title: 'A card...',
subtitle: 'Waiting to be clicked-on',
btnClicked: action('👊 Button was clicked')
}
}));
Here are a few things to note:
See this page for a list of other addons that can be used with Storybook.
For this example, I wanted the global styles of my Angular app to be reflected in the generated Storybook. It’s as simple as adding a file called preview-head.html in the .config folder that’s added by Storybook to the root of the project. In that file, you can add anything that would go into the head of a document. So let’s add our global styles:
<style>
body {
background: #f3f3f3;
font-family: Roboto, sans-serif;
color: #6ba083;
}
</style>
It’s easy to generate a Storybook with static files that can be deployed to a static hosting service like Github pages. This allows to host a Storybook that other members of the team can easily consult.
Simply invoke the build-storybook npm script:
$ npm run build-storybook
It’ll generate a storybook-static folder at the root of the project with all the files ready to be uploaded to your static hosting service of choice. You can also try it out locally using npx and http-server:
$ cd storybook-static
$ npx http-server
📙 The End! Read more about Storybook’s usage in the official docs.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!