Skip to content

Commit

Permalink
Merge branch 'next' of github.com:storybookjs/storybook into next
Browse files Browse the repository at this point in the history
  • Loading branch information
shilman committed Mar 13, 2022
2 parents 4abb9f9 + 208d2f9 commit 9ff7ee1
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 39 deletions.
26 changes: 25 additions & 1 deletion docs/configure/css-troubleshooting/angular.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,28 @@ Additionally, if you need Storybook specific styles that are separate from your
}
}
}
```
```

### Nx with Angular 13
If you're working with Storybook and [NX libraries](https://nx.dev/structure/library-types), you can extend your project's configuration (i.e., `project.json`) and provide the application's styles. For example:

```json
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/angular",
"outputPath": "dist/storybook/example-lib",
"config": {
"configFolder": "libs/example-lib/storybook/.storybook"
},
"projectBuildConfig": "example-lib:build-storybook",
"styles": ["apps/example-app/src/styles.scss"]
},
"configurations": {
"ci": {
"quiet": true
}
}
}
```
60 changes: 30 additions & 30 deletions docs/essentials/controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ It works as long as you type a valid string into the auto-generated text control

We can specify which controls get used by declaring a custom [argType](../api/argtypes.md) for the `variant` property. ArgTypes encode basic metadata for args, such as name, description, defaultValue for an arg. These get automatically filled in by Storybook Docs.

ArgTypes can also contain arbitrary annotations, which the user can override. Since `variant` is a property of the component, let's put that annotation on the default export.
`ArgTypes` can also contain arbitrary annotations, which the user can override. Since `variant` is a property of the component, let's put that annotation on the default export.

<!-- prettier-ignore-start -->

Expand Down Expand Up @@ -105,7 +105,7 @@ To do so, use the `matchers` property in the `controls` parameter:

## Fully custom args

Up until now, we only used auto-generated controls based on the component we're writing stories for. If we are writing [complex stories](../writing-stories/stories-for-multiple-components.md), we may want to add controls for args that aren’t part of the component.
Until now, we only used auto-generated controls based on the component we're writing stories for. If we are writing [complex stories](../writing-stories/stories-for-multiple-components.md), we may want to add controls for args that aren’t part of the component.

<!-- prettier-ignore-start -->

Expand Down Expand Up @@ -135,7 +135,7 @@ Using `argTypes`, you can change the display and behavior of each control.

### Dealing with complex values

You'll notice that when dealing with non-primitive values, you'll run into some limitations. The most obvious issue is that not every value can be represented as part of the `args` param in the URL, losing the ability to share and deeplink to such a state. Beyond that, complex values such as JSX cannot be synchronized between the manager (e.g., Controls addon) and the preview (your story).
When dealing with non-primitive values, you'll notice that you'll run into some limitations. The most obvious issue is that not every value can be represented as part of the `args` param in the URL, losing the ability to share and deeplink to such a state. Beyond that, complex values such as JSX cannot be synchronized between the manager (e.g., Controls addon) and the preview (your story).

One way to deal with this is to use primitive values (e.g., strings) as arg values and add a custom `render` function to convert these values to their complex counterpart before rendering. It isn't the nicest way to do it (see below), but certainly the most flexible.

Expand All @@ -157,7 +157,7 @@ One way to deal with this is to use primitive values (e.g., strings) as arg valu

<!-- prettier-ignore-end -->

Unless you need the flexibility of a function, an easier way to map primitives to complex values before rendering is to define a `mapping`. Additionally, you can specify `control.labels` to configure custom labels for your checkbox, radio, or select input.
Unless you need the flexibility of a function, an easier way to map primitives to complex values before rendering is to define a `mapping`, additionally, you can specify `control.labels` to configure custom labels for your checkbox, radio, or select input.

<!-- prettier-ignore-start -->

Expand All @@ -180,29 +180,29 @@ The Controls addon can be configured in two ways:

### Annotation

As shown above, you can configure individual controls with the “control" annotation in the [argTypes](../api/argtypes) field of either a component or story.

Here is the full list of available controls you can use:

| Data Type | Control Type | Description | Options |
| :---------- | :----------: | :------------------------------------------------------- | :------------: |
| **boolean** | boolean | checkbox input | - |
| **number** | number | a numeric text box input | min, max, step |
| | range | a range slider input | min, max, step |
| **object** | object | json editor text input | - |
| **array** | object | json editor text input | - |
| | file | a file input that gives you a array of urls | accept |
| **enum** | radio | radio buttons input | - |
| | inline-radio | inline radio buttons input | - |
| | check | multi-select checkbox input | - |
| | inline-check | multi-select inline checkbox input | - |
| | select | select dropdown input | - |
| | multi-select | multi-select dropdown input | - |
| **string** | text | simple text input | - |
| | color | color picker input that assumes strings are color values | presetColors |
| | date | date picker input | - |

If you need to customize a control for a number data type in your story, you can do it like so:
As shown above, you can configure individual controls with the “control" annotation in the [argTypes](../api/argtypes) field of either a component or story. Below is a condensed example and table featuring all available controls.

| Data Type | Control | Description |
| ----------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **boolean** | `boolean` | Provides a toggle for switching between possible states.<br/> `argTypes: { active: { control: 'boolean' }}` |
| **number** | `number` | Provides a numeric input to include the range of all possible values.<br/> `argTypes: { even: { control: { type: 'number', min:1, max:30, step: 2 } }}` |
| | `range` | Provides a range slider component to include all possible values.<br/> `argTypes: { odd: { control: { type: 'range', min: 1, max: 30, step: 3 } }}` |
| **object** | `object` | Provides a JSON-based editor component to handle the object's values.<br/> Also allows edition in raw mode.<br/> `argTypes: { user: { control: 'object' }}` |
| **array** | `object` | Provides a JSON-based editor component to handle the values of the array.<br/> Also allows edition in raw mode.<br/> `argTypes: { odd: { control: 'object' }}` |
| | `file` | Provides a file input component that returns an array of URLs.<br/> Can be further customized to accept specific file types.<br/> `argTypes: { avatar: { control: { type: 'file', accept: '.png' } }}` |
| **enum** | `radio` | Provides a set of radio buttons based on the available options.<br/> `argTypes: { contact: { control: 'radio', options: ['email', 'phone', 'mail'] }}` |
| | `inline-radio` | Provides a set of inlined radio buttons based on the available options.<br/> `argTypes: { contact: { control: 'inline-radio', options: ['email', 'phone', 'mail'] }}` |
| | `check` | Provides a set of checkbox components for selecting multiple options.<br/> `argTypes: { contact: { control: 'check', options: ['email', 'phone', 'mail'] }}` |
| | `inline-check` | Provides a set of inlined checkbox components for selecting multiple options.<br/> `argTypes: { contact: { control: 'inline-check', options: ['email', 'phone', 'mail'] }}` |
| | `select` | Provides a drop-down list component to handle single value selection. `argTypes: { age: { control: 'select', options: [20, 30, 40, 50] }}` |
| | `multi-select` | Provides a drop-down list that allows multiple selected values. `argTypes: { countries: { control: 'multi-select', options: ['USA', 'Canada', 'Mexico'] }}` |
| **string** | `text` | Provides a freeform text input. <br/> `argTypes: { label: { control: 'text' }}` |
| | `color` | Provides a color picker component to handle color values.<br/> Can be additionally configured to include a set of color presets.<br/> `argTypes: { color: { control: { type: 'color', presetsColors: ['red', 'green']} }}` |
| | `date` | Provides a datepicker component to handle date selection. `argTypes: { startDate: { control: 'date' }}` |

<div class="aside">
💡 The <code>date</code> control will convert the date into a UNIX timestamp when the value changes. It's a known limitation that will be fixed in a future release. If you need to represent the actual date, you'll need to update the story's implementation and convert the value into a date object.
</div>

<!-- prettier-ignore-start -->

Expand All @@ -216,7 +216,7 @@ If you need to customize a control for a number data type in your story, you can
<!-- prettier-ignore-end -->

<div class="aside">
💡 If you don't provide a specific one, it defaults to the number control type.
💡 Numeric data types will default to a <code>number</code> control unless additional configuration is provided.
</div>

### Parameters
Expand Down Expand Up @@ -257,7 +257,7 @@ For `color` controls, you can specify an array of `presetColors`, either on the

<!-- prettier-ignore-end -->

Color presets can be defined as an object with `color` and `title` or a simple CSS color string. These will then be available as swatches in the color picker. When you hover over the color swatch, you'll be able to see its title. If none is specified, it will default to the nearest CSS color name instead.
Color presets can be defined as an object with `color` and `title` or a simple CSS color string. These will then be available as swatches in the color picker. When you hover over the color swatch, you'll be able to see its title. It will default to the nearest CSS color name if none is specified.

### Disable controls for specific properties

Expand Down Expand Up @@ -348,4 +348,4 @@ Consider the following snippet to force required args first:
]}
/>

<!-- prettier-ignore-end -->
<!-- prettier-ignore-end -->
39 changes: 38 additions & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,4 +363,41 @@ Although valid, it introduces additional boilerplate code to the story definitio

## Why is Storybook's source loader returning undefined with curried functions?

This is a known issue with Storybook. If you're interested in getting it fixed, open an issue with a [working reproduction](./contribute/how-to-reproduce) so that it can be triaged and fixed in future releases.
This is a known issue with Storybook. If you're interested in getting it fixed, open an issue with a [working reproduction](./contribute/how-to-reproduce) so that it can be triaged and fixed in future releases.


## Why are my args no longer displaying the default values?

Before version 6.3, unset args were set to the `argTypes.defaultValue` if specified or inferred from the component's properties (e.g., React's prop types, Angular inputs, Vue props). Starting with version 6.3, Storybook no longer infers default values but instead defines the arg's value as `undefined` when unset, allowing the framework to supply its default value.

If you are using `argTypes.defaultValue` to fix the above, you no longer need to, and you can safely remove it from your stories.

Additionally, suppose you were using `argTypes.defaultValue` or relying on inference to set a default value for an arg. In that case, you should define the arg's value at the component level instead:

```js
// MyComponent.stories.js

export default {
component: MyComponent,
args: {
//👇 Defining the arg's value at the component level.
text: 'Something',
},
};
```

For Storybook's Docs, you can manually configure the displayed value by configuring the `table.defaultValue` setting:

```js
// MyComponent.stories.js

export default {
component: MyComponent,
argTypes: {
//👇 Defining the arg's display value in docs.
text: {
table: { defaultValue: { summary: 'SomeType<T>' } },
},
},
};
```
52 changes: 48 additions & 4 deletions docs/snippets/common/gizmo-story-controls-customization.js.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,58 @@ import { Gizmo } from './Gizmo';

export default {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: 'Gizmo',
component: Gizmo,
argTypes: {
canRotate: {
control: 'boolean',
},
width: {
control: { type: 'range', min: 400, max: 1200, step: 50 },
control: { type: 'number', min: 400, max: 1200, step: 50 },
},
height: {
control: { type: 'range', min: 200, max: 1500, step: 50 },
},
rawData: {
control: 'object',
},
coordinates: {
control: 'object',
},
texture: {
control: {
type: 'file',
accept: '.png',
},
},
position: {
control: 'radio',
options: ['left', 'right', 'center'],
},
rotationAxis: {
control: {
type: 'check',
options: ['x', 'y', 'z'],
},
},
scaling: {
control: 'select',
options: [10, 50, 75, 100, 200],
},
label: {
control: 'text',
},
meshColors: {
control: {
type: 'color',
presetsColors: ['#ff0000', '#00ff00', '#0000ff'],
},
},
revisionDate: {
control: 'date',
},
},
};
Expand Down
53 changes: 51 additions & 2 deletions docs/snippets/common/gizmo-story-controls-customization.mdx.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,63 @@ import { Gizmo } from './Gizmo';
title="Gizmo"
component={Gizmo}
argTypes={{
canRotate: {
control:'boolean',
},
width: {
control: {
type: 'range',
type: 'number',
min: 400,
max: 1200,
step: 50,
},
},
}}
height: {
control: {
type: 'range',
min: 200,
max: 1500,
step: 50,
},
},
rawData: {
control: 'object',
},
coordinates: {
control: 'object',
},
texture: {
control: {
type: 'file',
accept: '.png',
}
},
position: {
control: 'radio',
options: ['left', 'right', 'center'],
},
rotationAxis: {
control: {
type: 'check',
options: ['x', 'y', 'z'],
},
},
scaling: {
control: 'select',
options: [10, 50, 75, 100, 200],
},
label: {
control: 'text',
},
meshColors: {
control: {
type: 'color',
presetsColors: ['#ff0000', '#00ff00', '#0000ff'],
},
},
revisionDate: {
control: 'date',
},
}}
/>
```
2 changes: 1 addition & 1 deletion docs/writing-tests/importing-stories-in-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ With Playwright, you can write a test to check if the inputs are filled and matc

<!-- prettier-ignore-end -->

Once you execute Playwright, it opens a new browser window, load Storybook's isolated iframe, asserts if the inputs contain the specified values, and displays the test results in the terminal.
Once you execute Playwright, it opens a new browser window, loads Storybook's isolated iframe, asserts if the inputs contain the specified values, and displays the test results in the terminal.

---

Expand Down

0 comments on commit 9ff7ee1

Please sign in to comment.