DEV Community

Saulo Dias
Saulo Dias

Posted on • Edited on

Angular Library + Storybook

Storybook is a tool that allows you to easily create and document UI components. It works with several different libraries and frameworks, such as Angular, React, Vue, and many others.

Create a new workspace and library

To create a new workspace and a component library on Angular, run the following commands.

ng new my-workspace --create-application=false
cd my-workspace
ng generate library my-lib
Enter fullscreen mode Exit fullscreen mode

See: Angular - Creating Libraries

When you create a new workspace, Angular automatically initializes a git repository. After generating a basic library, I recommend you commit your changes, just to keep things neat.

git add . 
git commit -m 'generate library'
Enter fullscreen mode Exit fullscreen mode

Install Storybook

Once you have created a new library you can run the storybook utility to get started. Run the following command.

npx sb init
Enter fullscreen mode Exit fullscreen mode

This should take a few minutes. This command will run the Storybook CLI, which should automatically detect the framework or library where you're installing Storybook on and create the basic configuration for it.

See: Storybook - Install

After configuring storybook make sure the .storybook/tsconfig.json file is extending the library tsconfig.lib.json. The extends property in your .storybook/tsconfig.json should look like this.

{
  "extends": "../projects/my-lib/tsconfig.lib.json",
}
Enter fullscreen mode Exit fullscreen mode

Commit your changes again.

git add .
git commit -m 'install storybook'
Enter fullscreen mode Exit fullscreen mode

Adding the Storybook project to the workspace

Before running Storybook, you have to add it to your Angular Workspace, so that Storybook knows where to look for possible additional configurations you might need. This will be analogous to when you create an Angular application in your workspace, but in this case we don't want to create a native angular application, just a default configuration for Storybook to use, where we can add other settings later, like global css styles, for example.

See: Adding Global CSS to an Angular Library Storybook

Add the "storybook" setttings in the code below to the "projects" property in the angular.json file.

{
  "projects": {
    "my-lib": { ... },
    "storybook": {
      "projectType": "application",
      "root": "stories",
      "sourceRoot": "stories",
      "architect": {
        "build": {
          "options": {
            "tsConfig": "tsconfig.json",
            "styles": [],
            "scripts": []
          }
        }
      }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Running Storybook

Once the Storybook CLI has finished setting up a basic configuration in your Angular workspace, you will be able to run storybook by running the following command.

npm run storybook
Enter fullscreen mode Exit fullscreen mode

Rendering a library component

Once you run storybook, you will see some default example components which come with Storybook, however what you most certainly want is to be able to render and develop your own library components using Storybook.

For this example let's use the default component which has been created when we created the library, MyLibComponent.

Adding an alias to the main library entry point

Creating aliases for the library entry points is very useful at this point. This will ensure that the path used to import your components to your stories will be the same the devs will use once you publish your components library on npm.

To add the main entry point to the tsconfig.json follow the example below.

{
  "compilerOptions": {
    "paths": {
      "my-lib": ["projects/my-lib/src/public-api"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

By default the "my-lib" path points to the dist folder of your library ["dist/my-lib/my-lib","dist/my-lib"], which means you would have to build your library before pointing to the components inside it. While that might sound like a good idea at first, that introduces one unnecessary step to your development process which also causes several issues on Storybook, since it was not written with compiled components in mind.

You are better off letting Webpack dynamically compile your library components during development. It simplifies your workflow and you will have a better experience developing on Storybook.

I highly recommend you keep the library compilation and build test process in a separate workflow, and use npm link to test it in your applications before publish it, but that's whole new story.

If at some point you need to create a secondary entry point you just have to add it to the "paths" property. E.g: "my-lib/secondary": ["projects/my-lib/secondary/public-api"]

Creating a new story

Now that you have created an alias which points to the library components we can import and use them in a new story.

In the folder stories create a new file named my-lib.stories.ts.

import { Story, Meta, moduleMetadata } from '@storybook/angular';
import { MyLibComponent, MyLibModule } from 'my-lib';

export default {
  title: 'Example/MyLib',
  component: MyLibComponent,
  decorators: [
    moduleMetadata({
      imports: [MyLibModule],
    }),
  ],
} as Meta;

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

export const Default = Template.bind({});

Default.args = {} as Partial<MyLibComponent>;
Enter fullscreen mode Exit fullscreen mode

We don't really need to import the MyLibModule here since MyLibComponent doesn't really have any major dependency. It's just a simple component which says "my-lib works!", but I left this just as an example of what you usually might need to create a simple story. That's basically it.

If everything went well, it should render like this:
image

Here is the git repository with the code for this post.

You might also want to check this out:

Top comments (2)

Collapse
 
ashwingairola profile image
Ashwin Gairola

Great post, man. Helped me out a lot.

Collapse
 
justinbauerweb profile image
Justin Bauer

Awesome post, super helpful!