Skip to content

Latest commit

 

History

History
283 lines (219 loc) · 9.17 KB

plugin-angular.md

File metadata and controls

283 lines (219 loc) · 9.17 KB

Storybook

Storybook logo

Storybook is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.

This guide will briefly walk you through using Storybook within an Nx workspace.

Setting Up Storybook

Add the Storybook plugin

yarn add --dev @nrwl/storybook

Using Storybook

Generating Storybook Configuration

You can generate Storybook configuration for an individual project with this command:

nx g @nrwl/angular:storybook-configuration project-name

Running Storybook

Serve Storybook using this command:

nx run project-name:storybook

Anatomy of the Storybook setup

When running the Nx Storybook generator, it'll configure the Nx workspace to be able to run Storybook seamlessly. It'll create

  • a global Storybook configuration
  • a project specific Storybook configuration

The global Storybook configuration allows to set addon-ons or custom webpack configuration at a global level that applies to all Storybook's within the Nx workspace. You can find that folder at .storybook/ at the root of the workspace.

<workspace name>/
├── .storybook/
│   ├── main.js
│   ├── tsconfig.json
├── apps/
├── libs/
├── nx.json
├── package.json
├── README.md
└── etc...

The project-specific Storybook configuration is pretty much similar to what you would have for a non-Nx setup of Storybook. There's a .storybook folder within the project root folder.

<project root>/
├── .storybook/
│   ├── main.js
│   ├── preview.js
│   ├── tsconfig.json
├── src/
├── README.md
├── tsconfig.json
└── etc...

Using Addons

To register a Storybook addon for all storybook instances in your workspace:

  1. In /.storybook/main.js, in the addons array of the module.exports object, add the new addon:

    module.exports = {
    stories: [...],
    ...,
    addons: [..., '@storybook/addon-essentials'],
    };
  2. If a decorator is required, in each project's <project-path>/.storybook/preview.js, you can export an array called decorators.

    import someDecorator from 'some-storybook-addon';
    export const decorators = [someDecorator];

-- OR --

To register an addon for a single storybook instance, go to that project's .storybook folder:

  1. In main.js, in the addons array of the module.exports object, add the new addon:

    module.exports = {
    stories: [...],
    ...,
    addons: [..., '@storybook/addon-essentials'],
    };
  2. If a decorator is required, in preview.js you can export an array called decorators.

    import someDecorator from 'some-storybook-addon';
    export const decorators = [someDecorator];

Auto-generate Stories

The @nrwl/angular:storybook-configuration generator has the option to automatically generate *.stories.ts files for each component declared in the library.

<some-folder>/
├── my.component.ts
└── my.component.stories.ts

You can re-run it at a later point using the following command:

nx g @nrwl/angular:stories <project-name>

Cypress tests for Stories

Both storybook-configuration generator gives the option to set up an e2e Cypress app that is configured to run against the project's Storybook instance.

To launch Storybook and run the Cypress tests against the iframe inside of Storybook:

nx run project-name-e2e:e2e

The url that Cypress points to should look like this:

'/iframe.html?id=buttoncomponent--primary&args=text:Click+me!;padding;style:default'

  • buttoncomponent is a lowercase version of the Title in the *.stories.ts file.
  • primary is the name of an individual story.
  • style=default sets the style arg to a value of default.

Changing args in the url query parameters allows your Cypress tests to test different configurations of your component. You can read the documentation for more information.

Example Files

*.component.stories.ts file

import { moduleMetadata, Story, Meta } from '@storybook/angular';
import { ButtonComponent } from './button.component';

export default {
  title: 'ButtonComponent',
  component: ButtonComponent,
  decorators: [
    moduleMetadata({
      imports: [],
    }),
  ],
} as Meta<ButtonComponent>;

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

export const Primary = Template.bind({});
Primary.args = {
  text: 'Click me!',
  padding: 0,
  style: 'default',
};

Cypress *.spec.ts file

describe('shared-ui', () => {
  beforeEach(() =>
    cy.visit(
      '/iframe.html?id=buttoncomponent--primary&args=text:Click+me!;padding;style:default'
    )
  );

  it('should render the component', () => {
    cy.get('storybook-trial-button').should('exist');
  });
});

Storybook uses browserTarget for Angular

Nx is using the original Storybook executor for Angular to serve and build Storybook. If you're using Storybook in your Angular project, you will notice that browserTarget is specified for the storybook and build-storybook targets, much like it is done for serve or other targets. Angular needs the browserTarget for Storybook in order to know which configuration to use for the build. If your project is buildable (it has a build target, and uses the main Angular builder - @angular-devkit/build-angular:browser) the browserTarget for Storybook will use the build target, if it's not buildable it will use the build-storybook target.

    "storybook": {
      "executor": "@storybook/angular:start-storybook",
      "options": {
         ...
        "browserTarget": "my-project:build"
      },
      ...
    },
    "build-storybook": {
      "executor": "@storybook/angular:build-storybook",
       ...
      "options": {
         ...
        "browserTarget": "my-project:build"
      },
     ...
    }

This setup instructs Nx to use the configuration under the build target of my-project when using the storybook and build-storybook executors.

Configuring styles and preprocessor options

Angular supports including extra entry-point files for styles. Also, in case you use Sass, you can add extra base paths that will be checked for imports. In your project's project.json file you can use the styles and stylePreprocessorOptions properties in your storybook and build-storybook target options, as you would in your Storybook or your Angular configurations. Check out the Angular Workspace Configuration documentation for more information.

    "storybook": {
      "executor": "@storybook/angular:start-storybook",
      "options": {
         ...
        "styles": ["some-styles.css"],
        "stylePreprocessorOptions": {
          "includePaths": ["some-style-paths"]
        }
      },
      ...
    },
    "build-storybook": {
      "executor": "@storybook/angular:build-storybook",
       ...
      "options": {
         ...
        "styles": ["some-styles.css"],
        "stylePreprocessorOptions": {
          "includePaths": ["some-style-paths"]
        }
      },
     ...
    }

Note: Chances are, you will most probably need the same styles and stylePreprocessorOptions for your storybook and your build-storybook targets. Since you're using browserTarget, that means that Storybook will use the options of build or build-storybook when executing the storybook task (when compiling your Storybook). In that case, you only need to add the styles or stylePreprocessorOptions to the corresponding target (build or build-storybook) that the browserTarget is pointing to. In that case, for example, the configuration shown above would look like this:

    "storybook": {
      "executor": "@storybook/angular:start-storybook",
      "options": {
         ...
         "browserTarget": "my-project:build-storybook"
      },
      ...
    },
    "build-storybook": {
      "executor": "@storybook/angular:build-storybook",
       ...
      "options": {
         ...
        "browserTarget": "my-project:build-storybook",
        "styles": ["some-styles.css"],
        "stylePreprocessorOptions": {
          "includePaths": ["some-style-paths"]
        }
      },
     ...
    }

More Documentation

For more on using Storybook, see the official Storybook documentation.

Migration Scenarios

Here's more information on common migration scenarios for Storybook with Nx. For Storybook specific migrations that are not automatically handled by Nx please refer to the official Storybook page