How to Setup Storybook.js for Angular Material Components

How to Setup Storybook.js for Angular Material Components

Let's explore how to configure Storybook.js for "<mat-progress-bar>" Angular Material component

Introduction to Storybook.js

Storybook is an open-source tool for building UI components and pages in isolation. It streamlines UI development, testing, and documentation.

It helps us to develop and demo projects with just components instead of creating the actual pages in a website. Style guide generated using StoryBook has living documentation on how the components work and interact.

Built with

  • Angular V12
  • Angular CLI V12
  • Storybook V6.3
  • Node V14.17
  • npm 6.14.13

1. Create Angular project

Let's create a new Angular project using the below command:

ng new storybook-ng-material

2. Setup Storybook.js in the Angular app

Run the below command from the root of your project to set up Storybook.js. This is the out-of-the-box support from Storybook.js.

npx sb init

This command identifies the project type, installs @storybook/angular, and adds demo examples.

$ npx sb init

 sb init - the simplest way to add a Storybook to your project.

 • Detecting project type. ✓
 • Adding Storybook support to your "Angular" app npm WARN deprecated ts-simple-ast@12.4.0: NOTICE: ts-simple-ast has been renamed to ts-morph, and version reset to 1.0.0. Switch at your leisure...

3. Run Storybook demo

It added a couple of examples while setting it up in the previous step. Go ahead and run the demo just to make sure everything works fine.

npm run storybook

It should have opened http://localhost:6006/?path=/story/example-introduction--page in your default browser, and you must see stories over there as shown in the screenshot below.

image.png

4. Setup Angular Material

Let's set up Angular Material in the Angular app we created, and we will create a style guide (Stories) for the "<mat-progress-bar>" material component.

4.1 Install Angular Material

Run the below command to install Angular Material. You can find more info here.

ng add @angular/material

Choose a pre-built theme, typography, and animation support through interactive command-line:

image.png

4.2 Create Progressbar component to render "<mat-progress-bar>"

Go ahead and create a simple component to render the Material Progress Bar component. This creates HTML, TS, CSS, and Spec.ts files.

ng g c progress-bar

Import MatProgressBarModule in App Module (app.module.ts)

import { NgModule } from '@angular/core';
.
.
import { ProgressBarComponent } from './progress-bar/progress-bar.component';

@NgModule({
  declarations: [AppComponent, ProgressBarComponent],
  imports: [
      BrowserModule, 
      BrowserAnimationsModule, 
      MatProgressBarModule
  ],
  providers: [],
  bootstrap: [AppComponent],
})

Add below piece of code to ProgressBarComponent (progress-bar.component.html)

<mat-progress-bar mode="indeterminate" value="40"></mat-progress-bar>

Render <app-progress-bar> in App Component (app.component.html)

Remove the default code created by ng CLI under app.component.html with the below code.

<div style="margin-top: 50px; padding: 50px;">
  <app-progress-bar></app-progress-bar>
</div>

Build and serve the Application

Run the angular application ng serve -o to see if the progress bar renders fine.

image.png

4.3 Add @Input() decorator to ProgressBar component to pass values

Okay, let's add @Input() decorator to ProgressBar properties, I am going to include all properties that are supported in Angular Material ProgressBar.

Add input properties in progress-bar.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { ThemePalette } from '@angular/material/core';
import { ProgressBarMode } from '@angular/material/progress-bar';

@Component({
  selector: 'app-progress-bar',
  templateUrl: './progress-bar.component.html',
  styleUrls: ['./progress-bar.component.css']
})
export class ProgressBarComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

  /**
   * ProgressBar mode - determinate | indeterminate | Buffer | Query
   */
  @Input()
  mode: ProgressBarMode = 'determinate';

  /**
   * ProgressBar Value (0 -100) - Applicable only for Determinate and Buffer modes
   */
  @Input()
  value: number = 40;

   /**
   * ProgressBar BufferValue (0 -100) - Applicable only for Buffer mode
   */
  @Input()
  bufferValue: number = 60;

  /**
   * ProgressBar Color - primary (Theme color) | accent | warn
   */
  @Input()
  color: ThemePalette = 'primary';

}

Add input properties in progress-bar.component.html

<mat-progress-bar 
    [mode]="mode"
    [value]="value"
    [bufferValue]="bufferValue"
    [color]="color">
</mat-progress-bar>

5. It's time to write Stories

Create Stories TypeScript file under src/stories folder for ProgressBar component:

// Change directory to Stories
cd src\stories
// Create a new TypeScript file
touch Progressbar.stories.ts

Copy the below chunks of code (in the order listed) to the TypeScript file you just created. My explanation goes along with the code chunks.

Chunk #1 - Import statements

import { Story, Meta } from '@storybook/angular/types-6-0';
import { moduleMetadata } from '@storybook/angular';
import { ProgressBarComponent } from '../app/progress-bar/progress-bar.component';
import { MatProgressBarModule } from '@angular/material/progress-bar';

Chunk #2 - Create MetaData that gets consumed by Storybook

The default export metadata controls how Storybook lists your stories.

  1. title - Title of the stories
  2. component - The component name
  3. decorators - Specify Module dependencies for the component
  4. argTypes - This creates a radio button to play with the color of ProgressBar

Importing MatProgressBarModule helps in renderingthe MatProgressBar within ProgressBarComponent.

Remember to include other third-party modules as well under moduleMetadata to render the components belong to those modules.

export default {
  title: 'Angular Material/Progressbar',
  component: ProgressBarComponent,
  decorators: [
    moduleMetadata({
      imports: [MatProgressBarModule]      
    }),
  ],
  argTypes: {
    color: {
      options: ['primary', 'accent', 'warn'],
      control: { type: 'radio'},
    }
  },
} as Meta;

Chunk #3 - Define a master template for ProgressBar stories

This template allows you to pass "args", basically the input properties of the ProgressBar component.

const Template: Story<ProgressBarComponent> = (args: ProgressBarComponent) => ({
  props: args,
});

Chunk #4 - Story for "Determinate" ProgressBar

Let's create our first story for ProgressBar with mode 'Determinate'. It takes value and color properties as well.

This type of ProgressBar shows the determinate indicator in the value range (0 - 100).

export const Determinate = Template.bind({});
Determinate.args = {
  mode: 'determinate',
  value: 35,
  color: "primary" // primary | accent | warn
};

Play around by changing value and color to see how the ProgressBar renders.

determinate-pb.gif

Chunk #5 - Story for "Indeterminate" ProgressBar

Similarly, create a story for ProgressBar with "Indeterminate" as its mode. No need to set the value since the ProgressBar is not having "Determinate" indicator (0 - 100).

export const Indeterminate = Template.bind({});
Indeterminate.args = {
  mode: 'indeterminate',
  color: "accent" // primary | accent | warn
};

Change the ProgressBar color from controls in StoryBook and see how that looks.

indeterminate-pb.gif

Chunk #6 - Story for "Buffer" ProgressBar

This type of ProgressBar is used to indicate some activity or loading from the server.

We need to pass value for mode, value, bufferValue, and color properties.

export const Buffer = Template.bind({});
Buffer.args = {
  mode: 'buffer',  
  value: 35,
  bufferValue: 65,
  color: "warn" // primary | accent | warn
};

Change the bufferValue and see how it reflects in the ProgressBar.

buffer-pb.gif

Chunk #7 - Story for "Query" ProgressBar

Okay, the final story that's going to render ProgressBar in "Query" mode. This is often used to indicate "Preloading" before the actual loading starts.

export const Query = Template.bind({});
Query.args = {
  mode: 'query',
  color: "warn" // primary | accent | warn
};

Play with the color and see the change on ProgressBar.

query-pb.gif

6. Live Demo

I deployed this example as a static website in GitHub Pages.

image.png

Take me to Live Demo

7. Grab the code from GitHub

I just checked in the code to GitHub, you can either download or clone to work on this example further.

If you got any questions, feel free to post them in the comments section down below.

Happy learning!

I tweet a lot about Web development, Java, and Productivity Hacks, so feel free to follow me on Twitter at AskUdhay.

Here is one of my recent tweets:

Further Reading

  1. My recent talk on creating Style Guide for an Angular application using StoryBook.js

Did you find this article valuable?

Support Udhayakumar Govindarajan by becoming a sponsor. Any amount is appreciated!