From d9eb4d8f2f8e6a95c187758d5a56c44ff310422c Mon Sep 17 00:00:00 2001 From: katerina Date: Fri, 25 Jun 2021 15:42:28 +0300 Subject: [PATCH] feat(storybook): from addon-knobs to controls --- docs/angular/guides/storybook-plugin.md | 98 ++--- docs/react/guides/storybook-plugin.md | 88 +++-- e2e/angular/src/storybook.test.ts | 73 ++-- .../latest/angular/guides/storybook-plugin.md | 136 ++++--- .../latest/react/guides/storybook-plugin.md | 124 +++--- package.json | 1 + .../component-cypress-spec.spec.ts.snap | 6 +- .../component-cypress-spec.ts | 4 +- .../__componentFileName__.spec.ts__tmpl__ | 13 +- ...ult-value.ts => get-args-default-value.ts} | 5 +- .../component-story.spec.ts.snap | 35 +- .../component-story/component-story.ts | 4 +- .../__componentFileName__.stories.ts__tmpl__ | 29 +- ...ult-value.ts => get-args-default-value.ts} | 2 +- .../__snapshots__/stories-lib.spec.ts.snap | 41 +- .../storybook-configuration.spec.ts | 4 +- .../angular/src/generators/utils/storybook.ts | 4 +- .../component-cypress-spec.spec.ts | 2 +- .../component-cypress-spec.ts | 6 +- .../files/__componentName__.spec.__fileExt__ | 11 +- .../component-story/component-story.spec.ts | 150 ++++--- .../component-story/component-story.ts | 18 +- .../__componentFileName__.stories.__fileExt__ | 21 +- packages/storybook/migrations.json | 10 +- .../build-storybook.impl.spec.ts | 4 +- .../storybook/storybook.impl.spec.ts | 4 +- .../configuration/configuration.spec.ts | 6 +- .../.storybook/preview.js__tmpl__ | 4 - .../root-files/.storybook/main.js | 2 +- .../init/__snapshots__/init.spec.ts.snap | 2 +- .../src/generators/init/init.spec.ts | 8 +- .../storybook/src/generators/init/init.ts | 6 +- .../update-11-6-0/update-storybook.spec.ts | 14 +- .../update-11-6-0/update-storybook.ts | 8 +- .../install-addon-essentials.spec.ts | 38 ++ .../update-12-5-0/install-addon-essentials.ts | 63 +++ scripts/depcheck/missing.ts | 1 + yarn.lock | 365 +++++++++++++++--- 38 files changed, 914 insertions(+), 496 deletions(-) rename packages/angular/src/generators/component-cypress-spec/lib/{get-knob-default-value.ts => get-args-default-value.ts} (75%) rename packages/angular/src/generators/component-story/lib/{get-knob-default-value.ts => get-args-default-value.ts} (82%) create mode 100644 packages/storybook/src/migrations/update-12-5-0/install-addon-essentials.spec.ts create mode 100644 packages/storybook/src/migrations/update-12-5-0/install-addon-essentials.ts diff --git a/docs/angular/guides/storybook-plugin.md b/docs/angular/guides/storybook-plugin.md index f6ad66cd2edace..bf69248116b304 100644 --- a/docs/angular/guides/storybook-plugin.md +++ b/docs/angular/guides/storybook-plugin.md @@ -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` control 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; + +const Template: Story = (args: ButtonComponent) => ({ + component: ButtonComponent, + props: args, }); + +export const Primary = Template.bind({}); +Primary.args = { + text: 'Click me!', + padding: 0, + style: 'default', +}; ``` **Cypress \*.spec.ts file** @@ -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' ) ); @@ -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 `/.storybook/preview.js` use the `addDecorator` function. +2. If a decorator is required, in each project's `/.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 --** @@ -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 that 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). @@ -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. @@ -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/'; -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: @@ -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). diff --git a/docs/react/guides/storybook-plugin.md b/docs/react/guides/storybook-plugin.md index b869de93bc7daa..48baaa69ee8354 100644 --- a/docs/react/guides/storybook-plugin.md +++ b/docs/react/guides/storybook-plugin.md @@ -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` control 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 = () => ( -