Skip to content

Commit

Permalink
feat(storybook): from addon-knobs to controls (#6068)
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini authored Jun 25, 2021
1 parent ea0c6a3 commit e13b423
Show file tree
Hide file tree
Showing 38 changed files with 914 additions and 496 deletions.
98 changes: 55 additions & 43 deletions docs/angular/guides/storybook-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,37 +80,43 @@ nx run project-name-e2e:e2e

The url that Cypress points to should look like this:

`'/iframe.html?id=buttoncomponent--primary&knob-text=Click me!&knob-padding&knob-style=default'`
`'/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.
- `knob-style=default` sets the `style` knob to a value of `default`.
- `style=default` sets the `style` arg to a value of `default`.

Changing knobs in the url query parameters allows your Cypress tests to test different configurations of your component.
Changing args in the url query parameters allows your Cypress tests to test different configurations of your component. You can [read the documentation](https://storybook.js.org/docs/angular/writing-stories/args#setting-args-through-the-url) for more information.

### Example Files

**\*.component.stories.ts file**

```typescript
import { text, number } from '@storybook/addon-knobs';
import { moduleMetadata, Story, Meta } from '@storybook/angular';
import { ButtonComponent } from './button.component';

export default {
title: 'ButtonComponent',
};

export const primary = () => ({
moduleMetadata: {
imports: [],
},
component: ButtonComponent,
props: {
text: text('text', 'Click me!'),
padding: number('padding', 0),
style: text('style', 'default'),
},
decorators: [
moduleMetadata({
imports: [],
}),
],
} as Meta<ButtonComponent>;

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

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

**Cypress \*.spec.ts file**
Expand All @@ -119,7 +125,7 @@ export const primary = () => ({
describe('shared-ui', () => {
beforeEach(() =>
cy.visit(
'/iframe.html?id=buttoncomponent--primary&knob-text=Click me!&knob-padding&knob-style=default'
'/iframe.html?id=buttoncomponent--primary&args=text:Click+me!;padding;style:default'
)
);

Expand All @@ -138,16 +144,14 @@ To register an [addon](https://storybook.js.org/addons/) for all storybook insta
module.exports = {
stories: [...],
...,
addons: [..., '@storybook/addon-knobs/register'],
addons: [..., '@storybook/addon-essentials'],
};
```
2. If a decorator is required, in each project's `<project-path>/.storybook/preview.js` use the `addDecorator` function.
2. If a decorator is required, in each project's `<project-path>/.storybook/preview.js`, you can export an array called `decorators`.

```typescript
import { configure, addDecorator } from '@storybook/angular';
import { withKnobs } from '@storybook/addon-knobs';
addDecorator(withKnobs);
import someDecorator from 'some-storybook-addon';
export const decorators = [someDecorator];
```

**-- OR --**
Expand All @@ -159,22 +163,40 @@ To register an [addon](https://storybook.js.org/addons/) for a single storybook
module.exports = {
stories: [...],
...,
addons: [..., '@storybook/addon-knobs/register'],
addons: [..., '@storybook/addon-essentials'],
};
```
2. If a decorator is required, in `preview.js` use the `addDecorator` function.
2. If a decorator is required, in `preview.js` you can export an array called `decorators`.

```typescript
import { configure, addDecorator } from '@storybook/angular';
import { withKnobs } from '@storybook/addon-knobs';

addDecorator(withKnobs);
import someDecorator from 'some-storybook-addon';
export const decorators = [someDecorator];
```

### More Information

For more on using Storybook, see the [official Storybook documentation](https://storybook.js.org/docs/basics/introduction/).

## From knobs to controls

Storybook v6 moves from "knobs" to args and controls when it comes to defining and manipulating your storybook
component properties. More can be found [on the official Storybook docs](https://storybook.js.org/docs/react/writing-stories/args).

From **Nx v12.5** and on, the `@nrwl/storybook` package will be using `@storybook/addon-controls` instead of `@storybook/addon-knobs` to generate stories.

### For new Nx workspaces

- Generators will generate your Storybook configuration files and your Stories using Controls/args instead of knobs
- The `storybook-configuration` generator will install the [`@storybook/addon-essentials`](https://storybook.js.org/docs/riot/essentials/introduction) package, part of which is `@storybook/addon-controls`. This includes some more "essential" Storybook features (eg. `docs`). You can [disable features you do not need](https://storybook.js.org/docs/riot/essentials/introduction#disabling-addons) anytime in your `main.js`.
- Cypress e2e tests will be generated, [using the args URL](https://storybook.js.org/docs/react/writing-stories/args#setting-args-through-the-url) to set args in the controls.

### For existing Nx workspaces

- If you `nx migrate` to the latest version, your `package.json` will be updated to include the `@storybook/addon-essentials` package. The `@storybook/addon-essentials` addon will be added in your `addons` array in your root `main.js` file. You will need to run `npm/yarn install` to have it installed.
- If you install manually the latest version of `@nrwl/storybook`, `@nrwl/workspace` and `@nrwl/angular` or `@nrwl/react`, you will need to manually do `yarn add -D @storybook/addon-essentials`. You will also need to add the addon manually in your `addons` array in your root `main.js` file.
- All the stories you generate from that moment on will be using controls/args
- Your existing stories will not be touched and will still work

## Upgrading to Storybook 6 (and Nx versions >10.1.x)

Nx now comes with [Storybook version 6](https://storybook.js.org/releases/6.0). Chances are, if you used Nx version `10.1.x` or older with Storybook, you are using [Storybook version 5.3](https://storybook.js.org/releases/5.3) with configuration files of [Storybook version 5.2](https://storybook.js.org/releases/5.2).
Expand Down Expand Up @@ -290,11 +312,11 @@ If you have not changed the content of the files which the `storybook-configurat
```typescript
module.exports = {
stories: [],
addons: ['@storybook/addon-knobs/register'],
addons: ['@storybook/addon-essentials'],
};
```

- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. If you are using the default generated files without any changes, you should only have the `@storybook/addon-knobs/register` addon, which we already put in the array. You can now delete the `addons.js` file.
- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. If you are using the default generated files without any changes, you should not have any addons. You can now delete the `addons.js` file.

- The other two files remain unchanged.

Expand Down Expand Up @@ -323,10 +345,10 @@ After you add any addons in the `main.js` file, you can safely delete the `addon
- Rename the file `config.js` to `preview.js` and remove the last line where your stories paths are configured. Now, the contents of the `preview.js` file will look like this:

```typescript
import { addDecorator } from '<%= uiFramework %>';
import { withKnobs } from '@storybook/addon-knobs';
import { addDecorator } from '@storybook/angular';
import { YourDecorator } from '@storybook/<something>';
addDecorator(withKnobs);
addDecorator(YourDecorator);
```

- Modify the contents of `webpack.config.js`. Remove the following lines, which are the TypeScript configuration, which is not needed by Storybook any more:
Expand Down Expand Up @@ -372,13 +394,3 @@ Your folder structure should now look like this:
├── README.md
└── etc...
```
### Storybook v6 args and controls
Storybook v6 moves from "knobs" to args and controls when it comes to defining and manipulating your storybook
component properties. Feel free to use the new args way of defining stories. More can be found
[on the official Storybook docs](https://storybook.js.org/docs/angular/writing-stories/args).
> **Note:** Nx does not yet automatically generate stories that use the args syntax. The main reason is that args don't
> yet support being loaded via the iframe URL which is used in Nx to setup your Storybook based e2e tests. Once support
> is present in Storybook v6, we will provide a way to generate args & controls based stories. More on the progress [here](https://github.com/storybookjs/storybook/issues/12291).
88 changes: 50 additions & 38 deletions docs/react/guides/storybook-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,35 @@ nx run project-name-e2e:e2e

The url that Cypress points to should look like this:

`'/iframe.html?id=buttoncomponent--primary&knob-text=Click me!&knob-padding&knob-style=default'`
`'/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.
- `knob-style=default` sets the `style` knob to a value of `default`.
- `style=default` sets the `style` arg to a value of `default`.

Changing knobs in the url query parameters allows your Cypress tests to test different configurations of your component.
Changing args in the url query parameters allows your Cypress tests to test different configurations of your component. You can [read the documentation](https://storybook.js.org/docs/react/writing-stories/args#setting-args-through-the-url) for more information.

### Example Files

**\*.stories.tsx file**

```typescript
import React from 'react';
import { text, number } from '@storybook/addon-knobs';
import { Button } from './button';
import { Story, Meta } from '@storybook/react';
import { Button, ButtonProps } from './button';

export default { title: 'Button' };
export default {
component: Button,
title: 'Button',
} as Meta;

export const primary = () => (
<Button padding={number('Padding', 0)} text={text('Text', 'Click me')} />
);
const Template: Story<ButtonProps> = (args) => <Button {...args} />;

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

**Cypress \*.spec.ts file**
Expand All @@ -101,7 +108,7 @@ export const primary = () => (
describe('shared-ui', () => {
beforeEach(() =>
cy.visit(
'/iframe.html?id=buttoncomponent--primary&knob-text=Click me!&knob-padding&knob-style=default'
'/iframe.html?id=buttoncomponent--primary&args=text:Click+me!;padding;style:default'
)
);

Expand All @@ -120,16 +127,14 @@ To register an [addon](https://storybook.js.org/addons/) for all storybook insta
module.exports = {
stories: [...],
...,
addons: [..., '@storybook/addon-knobs/register'],
addons: [..., '@storybook/addon-essentials'],
};
```
2. If a decorator is required, in each project's `<project-path>/.storybook/preview.js` use the `addDecorator` function.
2. If a decorator is required, in each project's `<project-path>/.storybook/preview.js`, you can export an array called `decorators`.

```typescript
import { configure, addDecorator } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
addDecorator(withKnobs);
import someDecorator from 'some-storybook-addon';
export const decorators = [someDecorator];
```

**-- OR --**
Expand All @@ -141,22 +146,40 @@ To register an [addon](https://storybook.js.org/addons/) for a single storybook
module.exports = {
stories: [...],
...,
addons: [..., '@storybook/addon-knobs/register'],
addons: [..., '@storybook/addon-essentials'],
};
```
2. If a decorator is required, in `preview.js` use the `addDecorator` function.
2. If a decorator is required, in `preview.js` you can export an array called `decorators`.

```typescript
import { configure, addDecorator } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';

addDecorator(withKnobs);
import someDecorator from 'some-storybook-addon';
export const decorators = [someDecorator];
```

### More Information

For more on using Storybook, see the [official Storybook documentation](https://storybook.js.org/docs/basics/introduction/).

## From knobs to controls

Storybook v6 moves from "knobs" to args and controls when it comes to defining and manipulating your storybook
component properties. More can be found [on the official Storybook docs](https://storybook.js.org/docs/react/writing-stories/args).

From **Nx v12.5** and on, the `@nrwl/storybook` package will be using `@storybook/addon-controls` instead of `@storybook/addon-knobs` to generate stories.

### For new Nx workspaces

- Generators will generate your Storybook configuration files and your Stories using Controls/args instead of knobs
- The `storybook-configuration` generator will install the [`@storybook/addon-essentials`](https://storybook.js.org/docs/riot/essentials/introduction) package, part of which is `@storybook/addon-controls`. This includes some more "essential" Storybook features (eg. `docs`). You can [disable features you do not need](https://storybook.js.org/docs/riot/essentials/introduction#disabling-addons) anytime in your `main.js`.
- Cypress e2e tests will be generated, [using the args URL](https://storybook.js.org/docs/react/writing-stories/args#setting-args-through-the-url) to set args in the controls.

### For existing Nx workspaces

- If you `nx migrate` to the latest version, your `package.json` will be updated to include the `@storybook/addon-essentials` package. The `@storybook/addon-essentials` addon will be added in your `addons` array in your root `main.js` file. You will need to run `npm/yarn install` to have it installed.
- If you install manually the latest version of `@nrwl/storybook`, `@nrwl/workspace` and `@nrwl/angular` or `@nrwl/react`, you will need to manually do `yarn add -D @storybook/addon-essentials`. You will also need to add the addon manually in your `addons` array in your root `main.js` file.
- All the stories you generate from that moment on will be using controls/args
- Your existing stories will not be touched and will still work

## Upgrading to Storybook 6 (and Nx versions >10.1.x)

Nx now comes with [Storybook version 6](https://storybook.js.org/releases/6.0). Chances are, if you used Nx version `10.1.x` or older with Storybook, you are using [Storybook version 5.3](https://storybook.js.org/releases/5.3) with configuration files of [Storybook version 5.2](https://storybook.js.org/releases/5.2).
Expand Down Expand Up @@ -270,11 +293,11 @@ If you have not changed the content of the files which the `storybook-configurat
```typescript
module.exports = {
stories: [],
addons: ['@storybook/addon-knobs/register'],
addons: ['@storybook/addon-essentials'],
};
```

- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. If you are using the default generated files without any changes, you should only have the `@storybook/addon-knobs/register` addon, which we already put in the array. You can now delete the `addons.js` file.
- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. If you are using the default generated files without any changes, you should not have any addons. You can now delete the `addons.js` file.

- The other two files remain unchanged.

Expand Down Expand Up @@ -303,10 +326,9 @@ After you add any addons in the `main.js` file, you can safely delete the `addon
- Rename the file `config.js` to `preview.js` and remove the last line where your stories paths are configured. Now, the contents of the `preview.js` file will look like this:

```typescript
import { addDecorator } from '<%= uiFramework %>';
import { withKnobs } from '@storybook/addon-knobs';
import { addDecorator } from '@storybook/react';
addDecorator(withKnobs);
addDecorator(<YourDecorator>);
```

- Modify the contents of `webpack.config.js`. Remove the following lines, which are the TypeScript configuration, which is not needed by Storybook any more:
Expand Down Expand Up @@ -352,13 +374,3 @@ Your folder structure should now look like this:
├── README.md
└── etc...
```
### Storybook v6 args and controls
Storybook v6 moves from "knobs" to args and controls when it comes to defining and manipulating your storybook
component properties. Feel free to use the new args way of defining stories. More can be found
[on the official Storybook docs](https://storybook.js.org/docs/react/writing-stories/args).
> **Note:** Nx does not yet automatically generate stories that use the args syntax. The main reason is that args don't
> yet support being loaded via the iframe URL which is used in Nx to setup your Storybook based e2e tests. Once support
> is present in Storybook v6, we will provide a way to generate args & controls based stories. More on the progress [here](https://github.com/storybookjs/storybook/issues/12291).
Loading

1 comment on commit e13b423

@vercel
Copy link

@vercel vercel bot commented on e13b423 Jun 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.