Tutorial

Introduction to Using Storybook for Angular

Published on March 8, 2018
author

Alligator.io

Introduction to Using Storybook for Angular

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.

Setup

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:

Initial Storybook example

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.

Your First Stories

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:

card.component.html
<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:

card.component.ts
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:

index.stories.ts
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:

  • As you can see, stories are created by chaining calls to add() on a call to storyOf().
  • add() takes a name for the story and a function that returns an object with the component and props (inputs and outputs).
  • Actions triggered by outputs can be logged using the action addon.
  • Notes can be added to a story using the withNotes addon.

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:

preview-head.html
<style>
  body {
    background: #f3f3f3;
    font-family: Roboto, sans-serif;
    color: #6ba083;
  }
</style>

…and here’s what our Storybook now looks like:

Storybook with card stories

Building a Storybook for Deployment

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.

Learn more about our products

About the authors
Default avatar
Alligator.io

author

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.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.