Angular Library + Storybook
Tags: angular, component, library, storybook
Published: 2021-09-19 13:29:34

[Storybook](https://storybook.js.org/) 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
```
> See: [Angular - Creating Libraries](https://angular.io/guide/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'
```

### 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
```
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](https://storybook.js.org/docs/angular/get-started/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",
}
```

Commit your changes again.
```
git add .
git commit -m 'install storybook'
```


### 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
](https://dev.to/saulodias/adding-global-css-to-an-angular-library-storybook-agm)

Add the `"storybook"` setttings in the code below to the `"projects"` property in the `angular.json` file.
```json
{
  "projects": {
    "my-lib": { ... },
    "storybook": {
      "projectType": "application",
      "root": "stories",
      "sourceRoot": "stories",
      "architect": {
        "build": {
          "options": {
            "tsConfig": "tsconfig.json",
            "styles": [],
            "scripts": []
          }
        }
      }
    }
  }
}

```

### 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
```
## 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.

```json
{
  "compilerOptions": {
    "paths": {
      "my-lib": ["projects/my-lib/src/public-api"]
    }
  }
}
```
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`](https://docs.npmjs.com/cli/v7/commands/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`.

```typescript
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>;
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3y8qo84a5i7s8hl6lyq2.png)

Here is the git repository with the code for this post. 
{% github saulodias/my-workspace no-readme %}

### You might also want to check this out:

{% link saulodias/working-with-ng-content-on-storybook-4o3a %}