mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-04 15:11:10 +08:00
Merge branch 'next' into feature/knobs-performance-debouncing
This commit is contained in:
commit
636a02dc91
@ -200,6 +200,25 @@ jobs:
|
||||
command: |
|
||||
cd examples-native/crna-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
frontpage:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
name: Restore core dependencies cache
|
||||
keys:
|
||||
- core-dependencies-v3-{{ checksum "yarn.lock" }}
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: yarn install
|
||||
- run:
|
||||
name: Trigger build
|
||||
command: ./scripts/build-frontpage.js
|
||||
- save_cache:
|
||||
name: Cache core dependencies
|
||||
key: core-dependencies-v3-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
docs:
|
||||
<<: *defaults
|
||||
steps:
|
||||
@ -288,6 +307,7 @@ workflows:
|
||||
jobs:
|
||||
- build
|
||||
- docs
|
||||
- frontpage
|
||||
- lint:
|
||||
requires:
|
||||
- docs
|
||||
|
@ -18,3 +18,8 @@ lib/cli/test
|
||||
!.eslintrc-markdown.js
|
||||
!.jest.config.js
|
||||
!.storybook
|
||||
|
||||
REACT_NATIVE
|
||||
examples-native
|
||||
react-native
|
||||
ondevice-*
|
@ -39,6 +39,7 @@ object OpenSourceProjects_Storybook_Build_2 : BuildType({
|
||||
}
|
||||
retryBuild {
|
||||
delaySeconds = 60
|
||||
enabled = false
|
||||
}
|
||||
finishBuildTrigger {
|
||||
enabled = false
|
||||
|
@ -43,7 +43,9 @@ object OpenSourceProjects_Storybook_CliTestLatestCra : BuildType({
|
||||
+:next
|
||||
""".trimIndent()
|
||||
}
|
||||
retryBuild {}
|
||||
retryBuild {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
features {
|
||||
|
189
CHANGELOG.md
189
CHANGELOG.md
@ -1,3 +1,191 @@
|
||||
## 5.1.0-alpha.4 (March 11, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* CLI: Fix welcome component in dark theme ([#5998](https://github.com/storybooks/storybook/pull/5998))
|
||||
* Polymer: Fix re-rendering lit-html elements after non-lit-html element ([#5868](https://github.com/storybooks/storybook/pull/5868))
|
||||
* Addon-a11y: Fix respect 'element' arg in config ([#5996](https://github.com/storybooks/storybook/pull/5996))
|
||||
* Addon-a11y: Fix design icons ([#5991](https://github.com/storybooks/storybook/pull/5991))
|
||||
* Addon-viewport: Fix viewport iframe dimensions ([#5993](https://github.com/storybooks/storybook/pull/5993))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* ADD parameters to compile-js to no longer copy .ts files into dist ([#5844](https://github.com/storybooks/storybook/pull/5844))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* build(deps): bump react-is from 16.8.3 to 16.8.4 ([#6010](https://github.com/storybooks/storybook/pull/6010))
|
||||
* build(deps): bump react-dev-utils from 7.0.3 to 8.0.0 ([#6011](https://github.com/storybooks/storybook/pull/6011))
|
||||
|
||||
## 5.1.0-alpha.3 (March 9, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* Addon-a11y: add 'incomplete' tab ([#5984](https://github.com/storybooks/storybook/pull/5984))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: fix `selectStory` with one parameter ([#5983](https://github.com/storybooks/storybook/pull/5983))
|
||||
* Core: remove custom presets warning ([#5911](https://github.com/storybooks/storybook/pull/5911))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Addon-viewport: Change styling to more closely match v4 ([#5979](https://github.com/storybooks/storybook/pull/5979))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* Bump babel-preset-react-app from 7.0.1 to 7.0.2 ([#5937](https://github.com/storybooks/storybook/pull/5937))
|
||||
* Bump ts-node from 8.0.2 to 8.0.3 ([#5938](https://github.com/storybooks/storybook/pull/5938))
|
||||
* Bump react from 16.8.3 to 16.8.4 ([#5902](https://github.com/storybooks/storybook/pull/5902))
|
||||
* Bump marko from 4.15.3 to 4.15.4 ([#5939](https://github.com/storybooks/storybook/pull/5939))
|
||||
|
||||
## 5.0.1 (March 9, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Remove custom presets warning ([#5911](https://github.com/storybooks/storybook/pull/5911))
|
||||
* Core: support unicode chars in story IDs ([#5964](https://github.com/storybooks/storybook/pull/5964))
|
||||
* Core: Add core-js dependencies where it was missing ([#5961](https://github.com/storybooks/storybook/pull/5961))
|
||||
* CLI: Fix missing iframe.html in absolute path output directory([#5947](https://github.com/storybooks/storybook/pull/5947))
|
||||
* Addon-knobs: Added debouncing between keystrokes to speed up component rendering ([#5811](https://github.com/storybooks/storybook/pull/5811))
|
||||
* UI: Fix search in production mode ([#5909](https://github.com/storybooks/storybook/pull/5909))
|
||||
|
||||
## 4.1.14 (March 8, 2019)
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* React-native: Fix RN 0.58.5 / support 0.59 via react-native-modal-datetime-picker 6.0.0 ([#4425](https://github.com/storybooks/storybook/pull/4425))
|
||||
|
||||
## 5.1.0-alpha.2 (March 8, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: support unicode chars in story IDs ([#5964](https://github.com/storybooks/storybook/pull/5964))
|
||||
* Core: Add core-js dependencies where it was missing ([#5961](https://github.com/storybooks/storybook/pull/5961))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Addon-a11y: Migrate to typescript ([#5738](https://github.com/storybooks/storybook/pull/5738))
|
||||
|
||||
## 5.1.0-alpha.1 (March 7, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* CLI: Fix missing iframe.html in absolute path output directory ([#5947](https://github.com/storybooks/storybook/pull/5947))
|
||||
* Addon-knobs: Added debouncing between keystrokes to speed up component rendering ([#5811](https://github.com/storybooks/storybook/pull/5811))
|
||||
* UI: Fix search in production mode ([#5909](https://github.com/storybooks/storybook/pull/5909))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* ADD delay to rendering the acceptance stories ([#5943](https://github.com/storybooks/storybook/pull/5943))
|
||||
* Split versions.json into two files ([#5896](https://github.com/storybooks/storybook/pull/5896))
|
||||
|
||||
## 5.1.0-alpha.0 (March 6, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* UI: Custom scrollbars ([#5714](https://github.com/storybooks/storybook/pull/5714))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix: Move `react-select` dependency to 2.2 ([#5867](https://github.com/storybooks/storybook/pull/5867))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Cleanup unused dependencies ([#5453](https://github.com/storybooks/storybook/pull/5453))
|
||||
* Add directory attribute to repositories in package.json files ([#5643](https://github.com/storybooks/storybook/pull/5643))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* Project-wide dependency upgrades ([#5740](https://github.com/storybooks/storybook/pull/5740))
|
||||
* Bump react-is from 16.8.1 to 16.8.3 ([#5743](https://github.com/storybooks/storybook/pull/5743))
|
||||
* Bump danger from 7.0.13 to 7.0.14 ([#5744](https://github.com/storybooks/storybook/pull/5744))
|
||||
* Bump babel-plugin-named-asset-import from 0.3.0 to 0.3.1 ([#5745](https://github.com/storybooks/storybook/pull/5745))
|
||||
* Bump eslint-plugin-json from 1.3.2 to 1.4.0 ([#5719](https://github.com/storybooks/storybook/pull/5719))
|
||||
* Bump react-native-modal-datetime-picker from 5.1.0 to 6.0.0 ([#4425](https://github.com/storybooks/storybook/pull/4425))
|
||||
* Bump immer from 1.12.0 to 2.0.0 ([#5694](https://github.com/storybooks/storybook/pull/5694))
|
||||
* Bump danger from 7.0.11 to 7.0.13 ([#5696](https://github.com/storybooks/storybook/pull/5696))
|
||||
* Bump eslint-plugin-jsx-a11y from 6.2.0 to 6.2.1 ([#5698](https://github.com/storybooks/storybook/pull/5698))
|
||||
* Bump @angular/platform-browser-dynamic from 7.2.4 to 7.2.6 ([#5697](https://github.com/storybooks/storybook/pull/5697))
|
||||
* Bump eslint from 5.12.1 to 5.14.1 ([#5653](https://github.com/storybooks/storybook/pull/5653))
|
||||
* Bump babel-preset-react-app from 7.0.0 to 7.0.1 ([#5674](https://github.com/storybooks/storybook/pull/5674))
|
||||
* Bump react from 16.8.1 to 16.8.2 ([#5673](https://github.com/storybooks/storybook/pull/5673))
|
||||
* Bump @angular/cli from 7.3.0 to 7.3.2 ([#5654](https://github.com/storybooks/storybook/pull/5654))
|
||||
* Bump @types/jest from 24.0.0 to 24.0.6 ([#5655](https://github.com/storybooks/storybook/pull/5655))
|
||||
* Bump lint-staged from 8.1.3 to 8.1.4 ([#5606](https://github.com/storybooks/storybook/pull/5606))
|
||||
* Bump @types/lodash from 4.14.120 to 4.14.121 ([#5609](https://github.com/storybooks/storybook/pull/5609))
|
||||
* Bump webpack from 4.29.0 to 4.29.3 ([#5570](https://github.com/storybooks/storybook/pull/5570))
|
||||
* update modal manager for rn 0.58 support ([#5581](https://github.com/storybooks/storybook/pull/5581))
|
||||
* Bump danger from 7.0.7 to 7.0.11 ([#5568](https://github.com/storybooks/storybook/pull/5568))
|
||||
* Bump jest-jasmine2 from 24.0.0 to 24.1.0 ([#5569](https://github.com/storybooks/storybook/pull/5569))
|
||||
* Bump jest-jasmine2 from 24.0.0 to 24.1.0 ([#5567](https://github.com/storybooks/storybook/pull/5567))
|
||||
* Bump handlebars from 4.0.12 to 4.1.0 ([#5576](https://github.com/storybooks/storybook/pull/5576))
|
||||
* Bump esm from 3.2.1 to 3.2.4 ([#5556](https://github.com/storybooks/storybook/pull/5556))
|
||||
* Bump @types/jest from 23.3.13 to 24.0.0 ([#5554](https://github.com/storybooks/storybook/pull/5554))
|
||||
* Bump webpack-dev-middleware from 3.5.1 to 3.5.2 ([#5552](https://github.com/storybooks/storybook/pull/5552))
|
||||
* Bump @emotion/core from 10.0.6 to 10.0.7 ([#5555](https://github.com/storybooks/storybook/pull/5555))
|
||||
* Bump terser-webpack-plugin from 1.2.1 to 1.2.2 ([#5553](https://github.com/storybooks/storybook/pull/5553))
|
||||
* Bump fuse.js from 3.3.1 to 3.4.2 ([#5538](https://github.com/storybooks/storybook/pull/5538))
|
||||
* Bump @angular/platform-browser-dynamic from 7.2.3 to 7.2.4 ([#5540](https://github.com/storybooks/storybook/pull/5540))
|
||||
* Bump emotion-theming from 10.0.6 to 10.0.7 ([#5541](https://github.com/storybooks/storybook/pull/5541))
|
||||
* Bump eslint-config-prettier from 3.6.0 to 4.0.0 ([#5539](https://github.com/storybooks/storybook/pull/5539))
|
||||
|
||||
## 5.0.0 (March 5, 2019)
|
||||
|
||||
Storybook 5.0 is a completely new UI with the following improvements:
|
||||
|
||||
- 🌓 New design with light and dark themes
|
||||
- 🛠 Canvas toolbar for easy access to addons
|
||||
- 🗺 Overhauled navigation sidebar with an intuitive menu
|
||||
- 🗜 Redesigned addons panel with handy buttons to toggle visibility and orientation
|
||||
- ⌨️ Improved keyboard shortcuts that are user configurable
|
||||
- 🌍 New URL structure that eliminates long strings of query parameters
|
||||
|
||||
5.0 contains hundreds more fixes, features, and tweaks. Browse the changelogs matching `5.0.0-alpha.*`, `5.0.0-beta.*`, and `5.0.0-rc.*` for the full list of changes. See [MIGRATION.md](https://github.com/storybooks/storybook/blob/next/MIGRATION.md) to ugprade from `4.x`.
|
||||
|
||||
## 5.0.0-rc.11 (March 5, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* UI: Fix base theme initialization and theme bootup ([#5843](https://github.com/storybooks/storybook/pull/5843))
|
||||
* UI: Fix SidebarItem feels "laggy" when clicked ([#5850](https://github.com/storybooks/storybook/pull/5850))
|
||||
|
||||
## 5.0.0-rc.10 (March 4, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Addon-viewports: Restore v4 behaviour ([#5829](https://github.com/storybooks/storybook/pull/5829))
|
||||
* Addon-backgrounds: Remove previously deprecated default export ([#5828](https://github.com/storybooks/storybook/pull/5828))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Addon-a11y: Cleanup and document migration ([#5833](https://github.com/storybooks/storybook/pull/5833))
|
||||
|
||||
## 5.0.0-rc.9 (March 3, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* Core: Allow local decorators via params ([#5806](https://github.com/storybooks/storybook/pull/5806))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Add warning for decorators added "mid-kind" ([#5819](https://github.com/storybooks/storybook/pull/5819))
|
||||
* Addon-notes: Support inline code markdown ([#5802](https://github.com/storybooks/storybook/pull/5802))
|
||||
* Theming: Fix theme loading bugs ([#5787](https://github.com/storybooks/storybook/pull/5787))
|
||||
* CLI: Fix build-storybook with simplebar esm files ([#5816](https://github.com/storybooks/storybook/pull/5816))
|
||||
|
||||
## 5.0.0-rc.8 (March 1, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* Core: Allow local decorators via params ([#5806](https://github.com/storybooks/storybook/pull/5806))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* UI: Sort storiesHash so grouped keys appear together ([#5805](https://github.com/storybooks/storybook/pull/5805))
|
||||
* UI: Close tooltips on iframe clicks on keypresses ([#5807](https://github.com/storybooks/storybook/pull/5807))
|
||||
* Addon-Info: Add font family to info panel ([#5759](https://github.com/storybooks/storybook/pull/5759))
|
||||
|
||||
## 5.0.0-rc.7 (February 28, 2019)
|
||||
|
||||
### Features
|
||||
@ -83,6 +271,7 @@
|
||||
### Features
|
||||
|
||||
* UI: Allow collapsing active story and use separate expansion for filtered ([#5625](https://github.com/storybooks/storybook/pull/5625))
|
||||
* UI: Handle prerelease versions in version check ([#5641](https://github.com/storybooks/storybook/pull/5641))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
196
MIGRATION.md
196
MIGRATION.md
@ -2,8 +2,16 @@
|
||||
|
||||
- [From version 4.1.x to 5.0.x](#from-version-41x-to-50x)
|
||||
- [Webpack config simplification](#webpack-config-simplification)
|
||||
- [Theming overhaul](#theming-overhaul)
|
||||
- [Story hierarchy defaults](#story-hierarchy-defaults)
|
||||
- [Options addon deprecated](#options-addon-deprecated)
|
||||
- [Individual story decorators](#individual-story-decorators)
|
||||
- [Addon backgrounds uses parameters](#addon-backgrounds-uses-parameters)
|
||||
- [Addon cssresources name attribute renamed](#addon-cssresources-name-attribute-renamed)
|
||||
- [Addon viewport uses parameters](#addon-viewport-uses-parameters)
|
||||
- [Addon a11y uses parameters](#addon-a11y-uses-parameters-decorator-renamed)
|
||||
- [New keyboard shortcuts defaults](#new-keyboard-shortcuts-defaults)
|
||||
- [New URL structure](#new-url-structure)
|
||||
- [From version 4.0.x to 4.1.x](#from-version-40x-to-41x)
|
||||
- [Private addon config](#private-addon-config)
|
||||
- [React 15.x](#react-15x)
|
||||
@ -45,7 +53,7 @@
|
||||
|
||||
Storybook 5.0 includes sweeping UI changes as well as changes to the addon API and custom webpack configuration. We've tried to keep backwards compatibility in most cases, but there are some notable exceptions documented below.
|
||||
|
||||
## Webpack config simplifcation
|
||||
## Webpack config simplification
|
||||
|
||||
The API for custom webpack configuration has been simplifed in 5.0, but it's a breaking change.
|
||||
|
||||
@ -54,13 +62,17 @@ Storybook's "full control mode" for webpack allows you to override the webpack c
|
||||
In Storybook 5 there is a single signature for full-control mode that takes a parameters object with the fields `config` and `mode`:
|
||||
|
||||
```js
|
||||
module.exports = ({ config, mode }) => { config.modules.rules.push(...); return config; }
|
||||
module.exports = ({ config, mode }) => { config.module.rules.push(...); return config; }
|
||||
```
|
||||
|
||||
In contrast, the 4.x configuration function accepted either two or three arguments (`(baseConfig, mode)`, or `(baseConfig, mode, defaultConfig)`). The `config` object in the 5.x signature is equivalent to 4.x's `defaultConfig`.
|
||||
|
||||
Please see the [current custom webpack documentation](https://github.com/storybooks/storybook/blob/next/docs/src/pages/configurations/custom-webpack-config/index.md) for more information on custom webpack config.
|
||||
|
||||
## Theming overhaul
|
||||
|
||||
Theming has been rewritten in v5. If you used theming in v4, please consult the [theming docs](https://github.com/storybooks/storybook/blob/next/docs/src/pages/configurations/theming/index.md) to learn about the new API.
|
||||
|
||||
## Story hierarchy defaults
|
||||
|
||||
Storybook's UI contains a hierarchical tree of stories that can be configured by `hierarchySeparator` and `hierarchyRootSeparator` [options](./addons/options/README.md).
|
||||
@ -139,6 +151,164 @@ Here is the mapping from old options to new:
|
||||
|
||||
Storybook v5 removes the search dialog box in favor of a quick search in the navigation view, so `showSearchBox` has been removed.
|
||||
|
||||
## Individual story decorators
|
||||
|
||||
The behavior of adding decorators to a kind has changed in SB5 ([#5781](https://github.com/storybooks/storybook/issues/5781)).
|
||||
|
||||
In SB4 it was possible to add decorators to only a subset of the stories of a kind.
|
||||
|
||||
```js
|
||||
storiesOf('Stories', module)
|
||||
.add('noncentered', () => 'Hello')
|
||||
.addDecorator(centered)
|
||||
.add('centered', () => 'Hello');
|
||||
```
|
||||
|
||||
The semantics has changed in SB5 so that calling `addDecorator` on a kind adds a decorator to all its stories, no mater the order. So in the previous example, both stories would be centered.
|
||||
|
||||
To allow for a subset of the stories in a kind to be decorated, we've added the ability to add decorators to individual stories using parameters:
|
||||
|
||||
```js
|
||||
storiesOf('Stories', module)
|
||||
.add('noncentered', () => 'Hello')
|
||||
.add('centered', () => 'Hello', { decorators: [centered] });
|
||||
```
|
||||
|
||||
## Addon backgrounds uses parameters
|
||||
|
||||
Similarly, `@storybook/addon-backgrounds` uses parameters to pass background options. If you previously had:
|
||||
|
||||
```js
|
||||
import { withBackgrounds } from `@storybook/addon-backgrounds`;
|
||||
|
||||
storiesOf('Stories', module)
|
||||
.addDecorator(withBackgrounds(options));
|
||||
```
|
||||
|
||||
You should replace it with:
|
||||
|
||||
```js
|
||||
storiesOf('Stories', module).addParameters({ backgrounds: options });
|
||||
```
|
||||
|
||||
You can pass `backgrounds` parameters at the global level (via `addParameters` imported from `@storybook/react` et al.), and the story level (via the third argument to `.add()`).
|
||||
|
||||
## Addon cssresources name attribute renamed
|
||||
|
||||
In the options object for `@storybook/addon-cssresources`, the `name` attribute for each resource has been renamed to `id`. If you previously had:
|
||||
|
||||
```js
|
||||
import { withCssResources } from '@storybook/addon-cssresources';
|
||||
import { addDecorator } from '@storybook/react';
|
||||
|
||||
addDecorator(
|
||||
withCssResources({
|
||||
cssresources: [
|
||||
{
|
||||
name: `bluetheme`, // Previous
|
||||
code: `<style>body { background-color: lightblue; }</style>`,
|
||||
picked: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
You should replace it with:
|
||||
|
||||
```js
|
||||
import { withCssResources } from '@storybook/addon-cssresources';
|
||||
import { addDecorator } from '@storybook/react';
|
||||
|
||||
addDecorator(
|
||||
withCssResources({
|
||||
cssresources: [
|
||||
{
|
||||
id: `bluetheme`, // Renamed
|
||||
code: `<style>body { background-color: lightblue; }</style>`,
|
||||
picked: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
## Addon viewport uses parameters
|
||||
|
||||
Similarly, `@storybook/addon-viewport` uses parameters to pass viewport options. If you previously had:
|
||||
|
||||
```js
|
||||
import { configureViewport } from `@storybook/addon-viewport`;
|
||||
|
||||
configureViewport(options);
|
||||
```
|
||||
|
||||
You should replace it with:
|
||||
|
||||
```js
|
||||
import { addParameters } from '@storybook/react'; // or others
|
||||
|
||||
addParameters({ viewport: options });
|
||||
```
|
||||
|
||||
The `withViewport` decorator is also no longer supported and should be replaced with a parameter based API as above. Also the `onViewportChange` callback is no longer supported.
|
||||
|
||||
See the [viewport addon README](https://github.com/storybooks/storybook/blob/master/addons/viewport/README.md) for more information.
|
||||
|
||||
## Addon a11y uses parameters, decorator renamed
|
||||
|
||||
Similarly, `@storybook/addon-a11y` uses parameters to pass a11y options. If you previously had:
|
||||
|
||||
```js
|
||||
import { configureA11y } from `@storybook/addon-a11y`;
|
||||
|
||||
configureA11y(options);
|
||||
```
|
||||
|
||||
You should replace it with:
|
||||
|
||||
```js
|
||||
import { addParameters } from '@storybook/react'; // or others
|
||||
|
||||
addParameters({ a11y: options });
|
||||
```
|
||||
|
||||
You can also pass `a11y` parameters at the component level (via `storiesOf(...).addParameters`), and the story level (via the third argument to `.add()`).
|
||||
|
||||
Furthermore, the decorator `checkA11y` has been deprecated and renamed to `withA11y` to make it consistent with other Storybook decorators.
|
||||
|
||||
See the [a11y addon README](https://github.com/storybooks/storybook/blob/master/addons/a11y/README.md) for more information.
|
||||
|
||||
## New keyboard shortcuts defaults
|
||||
|
||||
Storybook's keyboard shortcuts are updated in 5.0, but they are configurable via the menu so if you want to set them back you can:
|
||||
|
||||
| Shorctut | Old | New |
|
||||
| ---------------------- | ----------- | ----- |
|
||||
| Toggle sidebar | cmd-shift-X | S |
|
||||
| Toggle addons panel | cmd-shift-Z | A |
|
||||
| Toggle addons position | cmd-shift-G | D |
|
||||
| Toggle fullscreen | cmd-shift-F | F |
|
||||
| Next story | cmd-shift-→ | alt-→ |
|
||||
| Prev story | cmd-shift-← | alt-← |
|
||||
| Next component | | alt-↓ |
|
||||
| Prev component | | alt-↑ |
|
||||
| Search | | / |
|
||||
|
||||
## New URL structure
|
||||
|
||||
We've update Storybook's URL structure in 5.0. The old structure used URL parameters to save the UI state, resulting in long ugly URLs. v5 respects the old URL parameters, but largely does away with them.
|
||||
|
||||
The old structure encoded `selectedKind` and `selectedStory` among other parameters. Storybook v5 respects these parameters but will issue a deprecation message in the browser console warning of potential future removal.
|
||||
|
||||
The new URL structure looks like:
|
||||
|
||||
```
|
||||
https://url-of-storybook?path=/story/<storyId>
|
||||
```
|
||||
|
||||
The structure of `storyId` is a slugified `<selectedKind>--<selectedStory>` (slugified = lowercase, hyphen-separated). Each `storyId` must be unique. We plan to build more features into Storybook in upcoming versions based on this new structure.
|
||||
|
||||
## From version 4.0.x to 4.1.x
|
||||
|
||||
There are are a few migrations you should be aware of in 4.1, including one unintentionally breaking change for advanced addon usage.
|
||||
@ -168,17 +338,19 @@ However, if you're developing React components, this means you need to upgrade t
|
||||
Also, here's the error you'll get if you're running an older version of React:
|
||||
|
||||
```
|
||||
|
||||
core.browser.esm.js:15 Uncaught TypeError: Object(...) is not a function
|
||||
at Module../node_modules/@emotion/core/dist/core.browser.esm.js (core.browser.esm.js:15)
|
||||
at **webpack_require** (bootstrap:724)
|
||||
at fn (bootstrap:101)
|
||||
at Module../node_modules/@emotion/styled-base/dist/styled-base.browser.esm.js (styled-base.browser.esm.js:1)
|
||||
at **webpack_require** (bootstrap:724)
|
||||
at fn (bootstrap:101)
|
||||
at Module../node_modules/@emotion/styled/dist/styled.esm.js (styled.esm.js:1)
|
||||
at **webpack_require** (bootstrap:724)
|
||||
at fn (bootstrap:101)
|
||||
at Object../node_modules/@storybook/components/dist/navigation/MenuLink.js (MenuLink.js:12)
|
||||
at Module../node_modules/@emotion/core/dist/core.browser.esm.js (core.browser.esm.js:15)
|
||||
at **webpack_require** (bootstrap:724)
|
||||
at fn (bootstrap:101)
|
||||
at Module../node_modules/@emotion/styled-base/dist/styled-base.browser.esm.js (styled-base.browser.esm.js:1)
|
||||
at **webpack_require** (bootstrap:724)
|
||||
at fn (bootstrap:101)
|
||||
at Module../node_modules/@emotion/styled/dist/styled.esm.js (styled.esm.js:1)
|
||||
at **webpack_require** (bootstrap:724)
|
||||
at fn (bootstrap:101)
|
||||
at Object../node_modules/@storybook/components/dist/navigation/MenuLink.js (MenuLink.js:12)
|
||||
|
||||
```
|
||||
|
||||
### Generic addons
|
||||
|
30
README.md
30
README.md
@ -85,18 +85,18 @@ For additional help, join us [in our Discord](https://discord.gg/sMFvFsG) or [Sl
|
||||
|
||||
| Framework | Demo | |
|
||||
| -------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| [React](app/react) | [v4.0.0](https://storybooks-official.netlify.com) | [](app/react) |
|
||||
| [React](app/react) | [v5.0.0](https://storybooks-official.netlify.com) | [](app/react) |
|
||||
| [React Native](app/react-native) | - | [](app/react-native) |
|
||||
| [Vue](app/vue) | [v4.0.0](https://storybooks-vue.netlify.com/) | [](app/vue) |
|
||||
| [Angular](app/angular) | [v4.0.0](https://storybooks-angular.netlify.com/) | [](app/angular) |
|
||||
| [Polymer](app/polymer) | [v4.0.0](https://storybooks-polymer.netlify.com/) | [](app/polymer) |
|
||||
| [Mithril](app/mithril) | [v4.0.0](https://storybooks-mithril.netlify.com/) | [](app/mithril) |
|
||||
| [Marko](app/marko) | [v4.0.0](https://storybooks-marko.netlify.com/) | [](app/marko) |
|
||||
| [HTML](app/html) | [v4.0.0](https://storybooks-html.netlify.com/) | [](app/html) |
|
||||
| [Svelte](app/svelte) | [v4.0.0](https://storybooks-svelte.netlify.com/) | [](app/svelte) |
|
||||
| [Riot](app/riot) | [v4.0.0](https://storybooks-riot.netlify.com/) | [](app/riot) |
|
||||
| [Ember](app/ember) | [v4.0.0](https://storybooks-ember.netlify.com/) | [](app/ember) |
|
||||
| [Preact](app/preact) | [v4.0.0](https://storybooks-preact.netlify.com/) | [](app/preact) |
|
||||
| [Vue](app/vue) | [v5.0.0](https://storybooks-vue.netlify.com/) | [](app/vue) |
|
||||
| [Angular](app/angular) | [v5.0.0](https://storybooks-angular.netlify.com/) | [](app/angular) |
|
||||
| [Polymer](app/polymer) | [v5.0.0](https://storybooks-polymer.netlify.com/) | [](app/polymer) |
|
||||
| [Mithril](app/mithril) | [v5.0.0](https://storybooks-mithril.netlify.com/) | [](app/mithril) |
|
||||
| [Marko](app/marko) | [v5.0.0](https://storybooks-marko.netlify.com/) | [](app/marko) |
|
||||
| [HTML](app/html) | [v5.0.0](https://storybooks-html.netlify.com/) | [](app/html) |
|
||||
| [Svelte](app/svelte) | [v5.0.0](https://storybooks-svelte.netlify.com/) | [](app/svelte) |
|
||||
| [Riot](app/riot) | [v5.0.0](https://storybooks-riot.netlify.com/) | [](app/riot) |
|
||||
| [Ember](app/ember) | [v5.0.0](https://storybooks-ember.netlify.com/) | [](app/ember) |
|
||||
| [Preact](app/preact) | [v5.0.0](https://storybooks-preact.netlify.com/) | [](app/preact) |
|
||||
|
||||
### Sub Projects
|
||||
|
||||
@ -131,10 +131,10 @@ See [Addon / Framework Support Table](ADDONS_SUPPORT.md)
|
||||
|
||||
We have a badge! Link it to your live Storybook example.
|
||||
|
||||

|
||||

|
||||
|
||||
```md
|
||||
[](link to site)
|
||||
[](link to site)
|
||||
```
|
||||
|
||||
If you're looking for material to use in your presentation about storybook, like logo's video material and the colors we use etc, you can find all of that at our [press repo](https://github.com/storybooks/press).
|
||||
@ -153,9 +153,9 @@ We welcome contributions to Storybook!
|
||||
|
||||
- 📥 Pull requests and 🌟 Stars are always welcome.
|
||||
- Read our [contributing guide](CONTRIBUTING.md) to get started.
|
||||
or find us on [Discord](https://discord.gg/sMFvFsG), we're will take the time to guide you
|
||||
or find us on [Discord](https://discord.gg/sMFvFsG), we're will take the time to guide you
|
||||
|
||||
Looking for a first issue to tackle?
|
||||
Looking for a first issue to tackle?
|
||||
|
||||
- We tag issues with [](https://github.com/storybooks/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) when we think they are well suited for people who are new to the codebase or OSS in general.
|
||||
- [Talk to us](https://discord.gg/sMFvFsG), we'll find something to suits your skills and learning interest.
|
||||
|
@ -20,16 +20,16 @@ Add this line to your `addons.js` file (create this file inside your storybook c
|
||||
import '@storybook/addon-a11y/register';
|
||||
```
|
||||
|
||||
import the `withA11Y` decorator to check your stories for violations within your components.
|
||||
import the `withA11y` decorator to check your stories for violations within your components.
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { withA11Y } from '@storybook/addon-a11y';
|
||||
import { withA11y } from '@storybook/addon-a11y';
|
||||
|
||||
// should only be added once
|
||||
// best place is in config.js
|
||||
addDecorator(withA11Y)
|
||||
addDecorator(withA11y)
|
||||
|
||||
storiesOf('button', module)
|
||||
.add('Accessible', () => (
|
||||
@ -51,9 +51,9 @@ You can override these options at story level too.
|
||||
import React from 'react';
|
||||
import { storiesOf, addDecorator, addParameters } from '@storybook/react';
|
||||
|
||||
import { withA11Y } from '@storybook/addon-a11y';
|
||||
import { withA11y } from '@storybook/addon-a11y';
|
||||
|
||||
addDecorator(withA11Y)
|
||||
addDecorator(withA11y)
|
||||
addParameters({
|
||||
a11y: {
|
||||
// ... axe options
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-a11y",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "a11y addon for storybook",
|
||||
"keywords": [
|
||||
"a11y",
|
||||
@ -21,25 +21,27 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/client-logger": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/client-logger": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"axe-core": "^3.1.2",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"memoizerific": "^1.11.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.2",
|
||||
"react": "^16.8.4",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/common-tags": "^1.8.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
@ -1,16 +1,14 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { styled } from '@storybook/theming';
|
||||
|
||||
import { STORY_RENDERED } from '@storybook/core-events';
|
||||
import { ActionBar, Icons } from '@storybook/components';
|
||||
import { ActionBar, Icons, ScrollArea } from '@storybook/components';
|
||||
|
||||
import { ScrollArea } from '@storybook/components/dist/ScrollArea/ScrollArea';
|
||||
import EVENTS from '../constants';
|
||||
|
||||
import Tabs from './Tabs';
|
||||
import Report from './Report';
|
||||
import { AxeResults, Result } from 'axe-core';
|
||||
import { Report } from './Report';
|
||||
import { Tabs } from './Tabs';
|
||||
import { EVENTS } from '../constants';
|
||||
|
||||
const Icon = styled(Icons)(
|
||||
{
|
||||
@ -18,7 +16,7 @@ const Icon = styled(Icons)(
|
||||
width: '12px',
|
||||
marginRight: '4px',
|
||||
},
|
||||
({ status, theme }) =>
|
||||
({ status, theme }: any) =>
|
||||
status === 'running'
|
||||
? {
|
||||
animation: `${theme.animation.rotate360} 1s linear infinite;`,
|
||||
@ -34,20 +32,32 @@ const Violations = styled.span(({ theme }) => ({
|
||||
color: theme.color.negative,
|
||||
}));
|
||||
|
||||
class A11YPanel extends Component {
|
||||
static propTypes = {
|
||||
active: PropTypes.bool.isRequired,
|
||||
api: PropTypes.shape({
|
||||
on: PropTypes.func,
|
||||
emit: PropTypes.func,
|
||||
off: PropTypes.func,
|
||||
}).isRequired,
|
||||
};
|
||||
const Incomplete = styled.span(({ theme }) => ({
|
||||
color: theme.color.warning,
|
||||
}));
|
||||
|
||||
state = {
|
||||
interface A11YPanelState {
|
||||
status: string;
|
||||
passes: Result[];
|
||||
violations: Result[];
|
||||
incomplete: Result[];
|
||||
}
|
||||
|
||||
interface A11YPanelProps {
|
||||
active: boolean;
|
||||
api: {
|
||||
on(event: string, callback: (data: any) => void): void;
|
||||
off(event: string, callback: (data: any) => void): void;
|
||||
emit(event: string): void;
|
||||
};
|
||||
}
|
||||
|
||||
export class A11YPanel extends Component<A11YPanelProps, A11YPanelState> {
|
||||
state: A11YPanelState = {
|
||||
status: 'ready',
|
||||
passes: [],
|
||||
violations: [],
|
||||
incomplete: [],
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
@ -57,7 +67,7 @@ class A11YPanel extends Component {
|
||||
api.on(EVENTS.RESULT, this.onUpdate);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
componentDidUpdate(prevProps: A11YPanelProps) {
|
||||
// TODO: might be able to remove this
|
||||
const { active } = this.props;
|
||||
|
||||
@ -73,12 +83,13 @@ class A11YPanel extends Component {
|
||||
api.off(EVENTS.RESULT, this.onUpdate);
|
||||
}
|
||||
|
||||
onUpdate = ({ passes, violations }) => {
|
||||
onUpdate = ({ passes, violations, incomplete }: AxeResults) => {
|
||||
this.setState(
|
||||
{
|
||||
status: 'ran',
|
||||
passes,
|
||||
violations,
|
||||
incomplete,
|
||||
},
|
||||
() => {
|
||||
setTimeout(() => {
|
||||
@ -109,7 +120,7 @@ class A11YPanel extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { passes, violations, status } = this.state;
|
||||
const { passes, violations, incomplete, status } = this.state;
|
||||
const { active } = this.props;
|
||||
|
||||
let actionTitle;
|
||||
@ -143,7 +154,13 @@ class A11YPanel extends Component {
|
||||
},
|
||||
{
|
||||
label: <Passes>{passes.length} Passes</Passes>,
|
||||
panel: <Report passes items={passes} empty="No a11y check passed" />,
|
||||
panel: <Report passes items={passes} empty="No a11y check passed." />,
|
||||
},
|
||||
{
|
||||
label: <Incomplete>{incomplete.length} Incomplete</Incomplete>,
|
||||
panel: (
|
||||
<Report passes={false} items={incomplete} empty="No a11y incomplete found." />
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@ -153,5 +170,3 @@ class A11YPanel extends Component {
|
||||
) : null;
|
||||
}
|
||||
}
|
||||
|
||||
export default A11YPanel;
|
@ -16,7 +16,7 @@ const ColorIcon = styled.span(
|
||||
height: '1rem',
|
||||
width: '1rem',
|
||||
},
|
||||
({ filter }) => ({
|
||||
({ filter }: { filter: string | null }) => ({
|
||||
filter: filter === 'mono' ? 'grayscale(100%)' : `url('#${filter}')`,
|
||||
}),
|
||||
({ theme }) => ({
|
||||
@ -24,13 +24,21 @@ const ColorIcon = styled.span(
|
||||
})
|
||||
);
|
||||
|
||||
class ColorBlindness extends Component {
|
||||
state = {
|
||||
// tslint:disable-next-line:no-empty-interface
|
||||
interface ColorBlindnessProps {}
|
||||
|
||||
interface ColorBlindnessState {
|
||||
expanded: boolean;
|
||||
filter: string | null;
|
||||
}
|
||||
|
||||
export class ColorBlindness extends Component<ColorBlindnessProps, ColorBlindnessState> {
|
||||
state: ColorBlindnessState = {
|
||||
expanded: false,
|
||||
filter: null,
|
||||
};
|
||||
|
||||
setFilter = filter => {
|
||||
setFilter = (filter: string | null) => {
|
||||
const iframe = getIframe();
|
||||
|
||||
if (iframe) {
|
||||
@ -44,6 +52,8 @@ class ColorBlindness extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
onVisibilityChange = (s: boolean) => this.setState({ expanded: s });
|
||||
|
||||
render() {
|
||||
const { filter, expanded } = this.state;
|
||||
|
||||
@ -69,10 +79,12 @@ class ColorBlindness extends Component {
|
||||
if (filter !== null) {
|
||||
colorList = [
|
||||
{
|
||||
id: 'reset',
|
||||
title: 'Reset color filter',
|
||||
onClick: () => {
|
||||
this.setFilter(null);
|
||||
},
|
||||
right: undefined,
|
||||
},
|
||||
...colorList,
|
||||
];
|
||||
@ -83,7 +95,7 @@ class ColorBlindness extends Component {
|
||||
placement="top"
|
||||
trigger="click"
|
||||
tooltipShown={expanded}
|
||||
onVisibilityChange={s => this.setState({ expanded: s })}
|
||||
onVisibilityChange={this.onVisibilityChange}
|
||||
tooltip={<TooltipLinkList links={colorList} />}
|
||||
closeOnClick
|
||||
>
|
||||
@ -94,5 +106,3 @@ class ColorBlindness extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ColorBlindness;
|
@ -1,60 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { styled } from '@storybook/theming';
|
||||
|
||||
import Rules from './Rules';
|
||||
|
||||
const Item = styled.li({
|
||||
fontWeight: 600,
|
||||
});
|
||||
const ItemTitle = styled.span({
|
||||
borderBottom: '1px solid rgb(130, 130, 130)',
|
||||
width: '100%',
|
||||
display: 'inline-block',
|
||||
paddingBottom: '4px',
|
||||
marginBottom: '4px',
|
||||
});
|
||||
|
||||
function Element({ element, passes }) {
|
||||
const { any, all, none } = element;
|
||||
|
||||
const rules = [...any, ...all, ...none];
|
||||
|
||||
return (
|
||||
<Item>
|
||||
<ItemTitle>{element.target[0]}</ItemTitle>
|
||||
<Rules rules={rules} passes={passes} />
|
||||
</Item>
|
||||
);
|
||||
}
|
||||
Element.propTypes = {
|
||||
element: PropTypes.shape({
|
||||
any: PropTypes.array.isRequired,
|
||||
all: PropTypes.array.isRequired,
|
||||
none: PropTypes.array.isRequired,
|
||||
}).isRequired,
|
||||
passes: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
const Elements = ({ elements, passes }) => (
|
||||
<ol>
|
||||
{elements.map((element, index) => (
|
||||
<Element passes={passes} element={element} key={index} />
|
||||
))}
|
||||
</ol>
|
||||
);
|
||||
|
||||
Elements.propTypes = {
|
||||
elements: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
any: PropTypes.array.isRequired,
|
||||
all: PropTypes.array.isRequired,
|
||||
none: PropTypes.array.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
passes: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default Elements;
|
48
addons/a11y/src/components/Report/Elements.tsx
Normal file
48
addons/a11y/src/components/Report/Elements.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React, { FunctionComponent } from 'react';
|
||||
|
||||
import { styled } from '@storybook/theming';
|
||||
|
||||
import { NodeResult } from 'axe-core';
|
||||
import { Rules } from './Rules';
|
||||
|
||||
const Item = styled.li({
|
||||
fontWeight: 600,
|
||||
});
|
||||
const ItemTitle = styled.span({
|
||||
borderBottom: '1px solid rgb(130, 130, 130)',
|
||||
width: '100%',
|
||||
display: 'inline-block',
|
||||
paddingBottom: '4px',
|
||||
marginBottom: '4px',
|
||||
});
|
||||
|
||||
interface ElementProps {
|
||||
element: NodeResult;
|
||||
passes: boolean;
|
||||
}
|
||||
|
||||
const Element: FunctionComponent<ElementProps> = ({ element, passes }) => {
|
||||
const { any, all, none } = element;
|
||||
|
||||
const rules = [...any, ...all, ...none];
|
||||
|
||||
return (
|
||||
<Item>
|
||||
<ItemTitle>{element.target[0]}</ItemTitle>
|
||||
<Rules rules={rules} passes={passes} />
|
||||
</Item>
|
||||
);
|
||||
};
|
||||
|
||||
interface ElementsProps {
|
||||
elements: NodeResult[];
|
||||
passes: boolean;
|
||||
}
|
||||
|
||||
export const Elements: FunctionComponent<ElementsProps> = ({ elements, passes }) => (
|
||||
<ol>
|
||||
{elements.map((element, index) => (
|
||||
<Element passes={passes} element={element} key={index} />
|
||||
))}
|
||||
</ol>
|
||||
);
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
|
||||
import { styled } from '@storybook/theming';
|
||||
import { Result } from 'axe-core';
|
||||
|
||||
const Wrapper = styled.div(({ theme }) => ({
|
||||
backgroundColor: theme.background.bar,
|
||||
@ -18,7 +18,11 @@ const Link = styled.a({
|
||||
display: 'block',
|
||||
});
|
||||
|
||||
function Info({ item }) {
|
||||
interface InfoProps {
|
||||
item: Result;
|
||||
}
|
||||
|
||||
export const Info: FunctionComponent<InfoProps> = ({ item }) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<Help>{item.help}</Help>
|
||||
@ -27,13 +31,4 @@ function Info({ item }) {
|
||||
</Link>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Info.propTypes = {
|
||||
item: PropTypes.shape({
|
||||
help: PropTypes.node,
|
||||
helpUrl: PropTypes.string,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default Info;
|
@ -1,18 +1,19 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { styled } from '@storybook/theming';
|
||||
import { Icons } from '@storybook/components';
|
||||
|
||||
import Info from './Info';
|
||||
import Tags from './Tags';
|
||||
import Elements from './Elements';
|
||||
import { Result } from 'axe-core';
|
||||
import { Info } from './Info';
|
||||
import { Elements } from './Elements';
|
||||
import { Tags } from './Tags';
|
||||
|
||||
const Wrapper = styled.div();
|
||||
|
||||
const Icon = styled(Icons)(({ theme }) => ({
|
||||
const Icon = styled<any, any>(Icons)(({ theme }) => ({
|
||||
height: 10,
|
||||
width: 10,
|
||||
minWidth: 10,
|
||||
color: theme.color.mediumdark,
|
||||
marginRight: '10px',
|
||||
transition: 'transform 0.1s ease-in-out',
|
||||
@ -28,6 +29,7 @@ const HeaderBar = styled.button(({ theme }) => ({
|
||||
border: 0,
|
||||
background: 'none',
|
||||
color: 'inherit',
|
||||
textAlign: 'left',
|
||||
|
||||
borderLeft: '3px solid transparent',
|
||||
|
||||
@ -37,16 +39,16 @@ const HeaderBar = styled.button(({ theme }) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
class Item extends Component {
|
||||
static propTypes = {
|
||||
item: PropTypes.shape({
|
||||
description: PropTypes.string,
|
||||
nodes: PropTypes.array,
|
||||
tags: PropTypes.array,
|
||||
}).isRequired,
|
||||
passes: PropTypes.bool.isRequired,
|
||||
};
|
||||
interface ItemProps {
|
||||
item: Result;
|
||||
passes: boolean;
|
||||
}
|
||||
|
||||
interface ItemState {
|
||||
open: boolean;
|
||||
}
|
||||
|
||||
export class Item extends Component<ItemProps, ItemState> {
|
||||
state = {
|
||||
open: false,
|
||||
};
|
||||
@ -84,5 +86,3 @@ class Item extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Item;
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { styled } from '@storybook/theming';
|
||||
|
||||
import { Icons } from '@storybook/components';
|
||||
import { CheckResult } from 'axe-core';
|
||||
|
||||
const impactColors = {
|
||||
minor: '#f1c40f',
|
||||
@ -17,7 +17,7 @@ const List = styled.div({
|
||||
flexDirection: 'column',
|
||||
padding: '4px',
|
||||
fontWeight: '400',
|
||||
});
|
||||
} as any);
|
||||
|
||||
const Item = styled.div({
|
||||
display: 'flex',
|
||||
@ -29,20 +29,23 @@ const Message = styled.div({
|
||||
paddingLeft: '6px',
|
||||
});
|
||||
|
||||
const Status = styled.div(({ passes, impact }) => ({
|
||||
height: '16px',
|
||||
width: '16px',
|
||||
borderRadius: '8px',
|
||||
fontSize: '10px',
|
||||
const Status = styled.div(({ passes, impact }: { passes: boolean; impact: string }) => ({
|
||||
display: 'inline-flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
flex: '0 0 16px',
|
||||
color: passes ? impactColors.success : impactColors[impact],
|
||||
color: passes ? impactColors.success : (impactColors as any)[impact],
|
||||
'& > svg': {
|
||||
height: '16px',
|
||||
width: '16px',
|
||||
},
|
||||
}));
|
||||
|
||||
const Rule = ({ rule, passes }) => (
|
||||
interface RuleProps {
|
||||
rule: CheckResult;
|
||||
passes: boolean;
|
||||
}
|
||||
|
||||
const Rule: FunctionComponent<RuleProps> = ({ rule, passes }) => (
|
||||
<Item>
|
||||
<Status passes={passes || undefined} impact={rule.impact}>
|
||||
{passes ? <Icons icon="check" /> : <Icons icon="cross" />}
|
||||
@ -51,15 +54,12 @@ const Rule = ({ rule, passes }) => (
|
||||
</Item>
|
||||
);
|
||||
|
||||
Rule.propTypes = {
|
||||
rule: PropTypes.shape({
|
||||
message: PropTypes.node,
|
||||
}).isRequired,
|
||||
passes: PropTypes.bool.isRequired,
|
||||
};
|
||||
interface RulesProps {
|
||||
rules: CheckResult[];
|
||||
passes: boolean;
|
||||
}
|
||||
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
function Rules({ rules, passes }) {
|
||||
export const Rules: FunctionComponent<RulesProps> = ({ rules, passes }) => {
|
||||
return (
|
||||
<List>
|
||||
{rules.map((rule, index) => (
|
||||
@ -67,14 +67,4 @@ function Rules({ rules, passes }) {
|
||||
))}
|
||||
</List>
|
||||
);
|
||||
}
|
||||
Rules.propTypes = {
|
||||
rules: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
message: PropTypes.node,
|
||||
})
|
||||
).isRequired,
|
||||
passes: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default Rules;
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
|
||||
import { styled } from '@storybook/theming';
|
||||
import { TagValue } from 'axe-core';
|
||||
|
||||
const Wrapper = styled.div({
|
||||
display: 'flex',
|
||||
@ -16,7 +16,11 @@ const Item = styled.div(({ theme }) => ({
|
||||
borderRadius: theme.appBorderRadius,
|
||||
}));
|
||||
|
||||
function Tags({ tags }) {
|
||||
interface TagsProps {
|
||||
tags: TagValue[];
|
||||
}
|
||||
|
||||
export const Tags: FunctionComponent<TagsProps> = ({ tags }) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{tags.map(tag => (
|
||||
@ -24,9 +28,4 @@ function Tags({ tags }) {
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
Tags.propTypes = {
|
||||
tags: PropTypes.arrayOf(PropTypes.node).isRequired,
|
||||
};
|
||||
|
||||
export default Tags;
|
@ -1,29 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Placeholder } from '@storybook/components';
|
||||
|
||||
import Item from './Item';
|
||||
|
||||
const Report = ({ items, empty, passes }) => (
|
||||
<Fragment>
|
||||
{items.length ? (
|
||||
items.map(item => <Item passes={passes} item={item} key={item.id} />)
|
||||
) : (
|
||||
<Placeholder key="placeholder">{empty}</Placeholder>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
Report.propTypes = {
|
||||
items: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
description: PropTypes.string,
|
||||
nodes: PropTypes.array,
|
||||
tags: PropTypes.array,
|
||||
})
|
||||
).isRequired,
|
||||
empty: PropTypes.string.isRequired,
|
||||
passes: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default Report;
|
21
addons/a11y/src/components/Report/index.tsx
Normal file
21
addons/a11y/src/components/Report/index.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import React, { Fragment, FunctionComponent } from 'react';
|
||||
import { Placeholder } from '@storybook/components';
|
||||
|
||||
import { Result } from 'axe-core';
|
||||
import { Item } from './Item';
|
||||
|
||||
export interface ReportProps {
|
||||
items: Result[];
|
||||
empty: string;
|
||||
passes: boolean;
|
||||
}
|
||||
|
||||
export const Report: FunctionComponent<ReportProps> = ({ items, empty, passes }) => (
|
||||
<Fragment>
|
||||
{items.length ? (
|
||||
items.map(item => <Item passes={passes} item={item} key={item.id} />)
|
||||
) : (
|
||||
<Placeholder key="placeholder">{empty}</Placeholder>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
@ -1,5 +1,4 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { styled } from '@storybook/theming';
|
||||
// TODO: reuse the Tabs component from @storybook/theming instead
|
||||
@ -37,7 +36,7 @@ const Item = styled.button(
|
||||
borderBottom: `3px solid ${theme.color.secondary}`,
|
||||
},
|
||||
}),
|
||||
({ active, theme }) =>
|
||||
({ active, theme }: any) =>
|
||||
active
|
||||
? {
|
||||
opacity: 1,
|
||||
@ -46,12 +45,23 @@ const Item = styled.button(
|
||||
: {}
|
||||
);
|
||||
|
||||
class Tabs extends Component {
|
||||
state = {
|
||||
interface TabsProps {
|
||||
tabs: Array<{
|
||||
label: JSX.Element;
|
||||
panel: JSX.Element;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface TabsState {
|
||||
active: number;
|
||||
}
|
||||
|
||||
export class Tabs extends Component<TabsProps, TabsState> {
|
||||
state: TabsState = {
|
||||
active: 0,
|
||||
};
|
||||
|
||||
onToggle = index => {
|
||||
onToggle = (index: number) => {
|
||||
this.setState({
|
||||
active: index,
|
||||
});
|
||||
@ -80,14 +90,3 @@ class Tabs extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Tabs.propTypes = {
|
||||
tabs: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
label: PropTypes.node,
|
||||
panel: PropTypes.node,
|
||||
})
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
export default Tabs;
|
@ -5,4 +5,4 @@ export const PARAM_KEY = `a11y`;
|
||||
const RESULT = `${ADDON_ID}/result`;
|
||||
const REQUEST = `${ADDON_ID}/request`;
|
||||
|
||||
export default { RESULT, REQUEST };
|
||||
export const EVENTS = { RESULT, REQUEST };
|
@ -1,85 +0,0 @@
|
||||
import { document } from 'global';
|
||||
import axe from 'axe-core';
|
||||
import deprecate from 'util-deprecate';
|
||||
import { stripIndents } from 'common-tags';
|
||||
|
||||
import addons, { makeDecorator } from '@storybook/addons';
|
||||
import { STORY_RENDERED } from '@storybook/core-events';
|
||||
import EVENTS, { PARAM_KEY } from './constants';
|
||||
|
||||
const channel = addons.getChannel();
|
||||
let progress = Promise.resolve();
|
||||
let setup = {};
|
||||
|
||||
const getElement = () => {
|
||||
const storyRoot = document.getElementById('story-root');
|
||||
|
||||
if (storyRoot) {
|
||||
return storyRoot.children;
|
||||
}
|
||||
return document.getElementById('root');
|
||||
};
|
||||
|
||||
const report = input => {
|
||||
channel.emit(EVENTS.RESULT, input);
|
||||
};
|
||||
|
||||
const run = (c, o) => {
|
||||
progress = progress.then(() => {
|
||||
axe.reset();
|
||||
if (c) {
|
||||
axe.configure(c);
|
||||
}
|
||||
return axe
|
||||
.run(
|
||||
getElement(),
|
||||
o || {
|
||||
restoreScroll: true,
|
||||
}
|
||||
)
|
||||
.then(report);
|
||||
});
|
||||
};
|
||||
|
||||
export const withA11Y = makeDecorator({
|
||||
name: 'withA11Y',
|
||||
parameterName: PARAM_KEY,
|
||||
skipIfNoParametersOrOptions: false,
|
||||
allowDeprecatedUsage: false,
|
||||
|
||||
wrapper: (getStory, context, opt) => {
|
||||
setup = opt.parameters || opt.options || {};
|
||||
|
||||
return getStory(context);
|
||||
},
|
||||
});
|
||||
|
||||
channel.on(STORY_RENDERED, () => run(setup.config, setup.options));
|
||||
channel.on(EVENTS.REQUEST, () => run(setup.config, setup.options));
|
||||
|
||||
if (module && module.hot && module.hot.decline) {
|
||||
module.hot.decline();
|
||||
}
|
||||
|
||||
// TODO: REMOVE at v6.0.0
|
||||
export const checkA11y = deprecate(
|
||||
(...args) => withA11Y(...args),
|
||||
'checkA11y has been replaced with withA11Y'
|
||||
);
|
||||
|
||||
// TODO: REMOVE at v6.0.0
|
||||
export const configureA11y = deprecate(
|
||||
config => {
|
||||
setup = config;
|
||||
},
|
||||
stripIndents`
|
||||
configureA11y is deprecated, please configure addon-a11y using the addParameter api:
|
||||
|
||||
addParameters({
|
||||
a11y: {
|
||||
// ... axe options
|
||||
element: '#root', // optional selector which element to inspect
|
||||
},
|
||||
});
|
||||
`
|
||||
);
|
95
addons/a11y/src/index.ts
Normal file
95
addons/a11y/src/index.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { document } from 'global';
|
||||
import axe, { AxeResults, ElementContext, RunOptions, Spec } from 'axe-core';
|
||||
import deprecate from 'util-deprecate';
|
||||
import { stripIndents } from 'common-tags';
|
||||
|
||||
import addons, { StoryWrapper } from '@storybook/addons';
|
||||
import { STORY_RENDERED } from '@storybook/core-events';
|
||||
import { EVENTS, PARAM_KEY } from './constants';
|
||||
|
||||
const channel = addons.getChannel();
|
||||
let progress = Promise.resolve();
|
||||
let setup: {
|
||||
element?: ElementContext;
|
||||
config: Spec;
|
||||
options: RunOptions;
|
||||
} = { element: null, config: {}, options: {} };
|
||||
|
||||
const getElement = () => {
|
||||
const storyRoot = document.getElementById('story-root');
|
||||
|
||||
if (storyRoot) {
|
||||
return storyRoot.children;
|
||||
}
|
||||
return document.getElementById('root');
|
||||
};
|
||||
|
||||
const report = (input: AxeResults) => {
|
||||
channel.emit(EVENTS.RESULT, input);
|
||||
};
|
||||
|
||||
const run = (element: ElementContext, config: Spec, options: RunOptions) => {
|
||||
progress = progress.then(() => {
|
||||
axe.reset();
|
||||
if (config) {
|
||||
axe.configure(config);
|
||||
}
|
||||
return axe
|
||||
.run(
|
||||
element || getElement(),
|
||||
options ||
|
||||
// tslint:disable-next-line:no-object-literal-type-assertion
|
||||
({
|
||||
restoreScroll: true,
|
||||
} as RunOptions) // cast to RunOptions is necessary because axe types are not up to date
|
||||
)
|
||||
.then(report);
|
||||
});
|
||||
};
|
||||
|
||||
// NOTE: we should add paramaters to the STORY_RENDERED event and deprecate this
|
||||
export const withA11y: StoryWrapper = (getStory, context) => {
|
||||
const params = context.parameters[PARAM_KEY];
|
||||
if (params) {
|
||||
setup = params;
|
||||
}
|
||||
return getStory(context);
|
||||
};
|
||||
|
||||
channel.on(STORY_RENDERED, () => run(setup.element, setup.config, setup.options));
|
||||
channel.on(EVENTS.REQUEST, () => run(setup.element, setup.config, setup.options));
|
||||
|
||||
if (module && module.hot && module.hot.decline) {
|
||||
module.hot.decline();
|
||||
}
|
||||
|
||||
// TODO: REMOVE at v6.0.0
|
||||
export const withA11Y = deprecate(
|
||||
// @ts-ignore
|
||||
(...args: any[]) => withA11y(...args),
|
||||
'withA11Y has been renamed withA11y'
|
||||
);
|
||||
|
||||
// TODO: REMOVE at v6.0.0
|
||||
export const checkA11y = deprecate(
|
||||
// @ts-ignore
|
||||
(...args: any[]) => withA11y(...args),
|
||||
'checkA11y has been renamed withA11y'
|
||||
);
|
||||
|
||||
// TODO: REMOVE at v6.0.0
|
||||
export const configureA11y = deprecate(
|
||||
(config: any) => {
|
||||
setup = config;
|
||||
},
|
||||
stripIndents`
|
||||
configureA11y is deprecated, please configure addon-a11y using the addParameter api:
|
||||
|
||||
addParameters({
|
||||
a11y: {
|
||||
// ... axe options
|
||||
element: '#root', // optional selector which element to inspect
|
||||
},
|
||||
});
|
||||
`
|
||||
);
|
@ -1,17 +1,16 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import addons, { types } from '@storybook/addons';
|
||||
import React, { Fragment, FunctionComponent } from 'react';
|
||||
import { styled } from '@storybook/theming';
|
||||
|
||||
import Panel from './components/Panel';
|
||||
import ColorBlindness from './components/ColorBlindness';
|
||||
|
||||
import { ADDON_ID, PANEL_ID } from './constants';
|
||||
import { ColorBlindness } from './components/ColorBlindness';
|
||||
import { A11YPanel } from './components/A11YPanel';
|
||||
import { addons, types } from '@storybook/addons';
|
||||
|
||||
const Hidden = styled.div(() => ({
|
||||
display: 'none',
|
||||
}));
|
||||
|
||||
const PreviewWrapper = p => (
|
||||
const PreviewWrapper: FunctionComponent<{}> = p => (
|
||||
<Fragment>
|
||||
{p.children}
|
||||
<Hidden>
|
||||
@ -81,20 +80,21 @@ const PreviewWrapper = p => (
|
||||
|
||||
addons.register(ADDON_ID, api => {
|
||||
addons.add(PANEL_ID, {
|
||||
title: '',
|
||||
type: types.TOOL,
|
||||
match: ({ viewMode }) => viewMode === 'story',
|
||||
render: () => <ColorBlindness />,
|
||||
});
|
||||
|
||||
addons.add(PANEL_ID, {
|
||||
type: types.PANEL,
|
||||
title: 'Accessibility',
|
||||
// eslint-disable-next-line react/prop-types
|
||||
render: ({ active, key }) => <Panel key={key} api={api} active={active} />,
|
||||
type: types.PANEL,
|
||||
render: ({ active, key }) => <A11YPanel key={key} api={api} active={active} />,
|
||||
});
|
||||
|
||||
addons.add(PANEL_ID, {
|
||||
title: '',
|
||||
type: types.PREVIEW,
|
||||
render: PreviewWrapper,
|
||||
render: PreviewWrapper as any,
|
||||
});
|
||||
});
|
3
addons/a11y/src/typings.d.ts
vendored
Normal file
3
addons/a11y/src/typings.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// TODO: following packages need definition files or a TS migration
|
||||
declare module '@storybook/components';
|
||||
declare module 'global';
|
13
addons/a11y/tsconfig.json
Normal file
13
addons/a11y/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"types": ["webpack-env"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"src/__tests__/**/*"
|
||||
]
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-actions",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Action Logger addon for storybook",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -21,18 +21,18 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"global": "^4.3.2",
|
||||
"lodash": "^4.17.11",
|
||||
"prop-types": "^15.6.2",
|
||||
"polished": "^2.3.3",
|
||||
"react": "^16.8.2",
|
||||
"react-inspector": "^2.3.0",
|
||||
"polished": "^3.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.8.4",
|
||||
"react-inspector": "^2.3.1",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -16,7 +16,9 @@ export const Wrapper = styled(({ children, className }) => (
|
||||
padding: '10px 5px 20px',
|
||||
});
|
||||
|
||||
const ThemedInspector = withTheme(({ theme, ...props }) => <Inspector theme={theme.addonActionsTheme || 'chromeLight'} {...props} />);
|
||||
const ThemedInspector = withTheme(({ theme, ...props }) => (
|
||||
<Inspector theme={theme.addonActionsTheme || 'chromeLight'} {...props} />
|
||||
));
|
||||
|
||||
interface ActionLoggerProps {
|
||||
actions: ActionDisplay[];
|
||||
@ -30,7 +32,12 @@ export const ActionLogger = ({ actions, onClear }: ActionLoggerProps) => (
|
||||
<Action key={action.id}>
|
||||
{action.count > 1 && <Counter>{action.count}</Counter>}
|
||||
<InspectorContainer>
|
||||
<ThemedInspector sortObjectKeys showNonenumerable={false} name={action.data.name} data={action.data.args || action.data} />
|
||||
<ThemedInspector
|
||||
sortObjectKeys
|
||||
showNonenumerable={false}
|
||||
name={action.data.name}
|
||||
data={action.data.args || action.data}
|
||||
/>
|
||||
</InspectorContainer>
|
||||
</Action>
|
||||
))}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { styled } from '@storybook/theming';
|
||||
import { opacify } from 'polished';
|
||||
import { ActionBar } from '@storybook/components';
|
||||
|
||||
export const Action = styled.div({
|
||||
display: 'flex',
|
||||
|
@ -10,7 +10,9 @@ const applyDecorators = (decorators: DecoratorFunction[], actionCallback: Handle
|
||||
};
|
||||
};
|
||||
|
||||
export const decorateAction = (decorators: DecoratorFunction[]): ((name: string, options?: ActionOptions) => HandlerFunction) => {
|
||||
export const decorateAction = (
|
||||
decorators: DecoratorFunction[]
|
||||
): ((name: string, options?: ActionOptions) => HandlerFunction) => {
|
||||
return (name: string, options?: ActionOptions) => {
|
||||
const callAction = action(name, options);
|
||||
return applyDecorators(decorators, callAction);
|
||||
|
@ -50,7 +50,8 @@ const actionsSubscription = (...args: any[]) => {
|
||||
const handlers = createHandlers(...args);
|
||||
lastSubscription = () => {
|
||||
handlers.forEach(({ eventName, handler }) => root.addEventListener(eventName, handler));
|
||||
return () => handlers.forEach(({ eventName, handler }) => root.removeEventListener(eventName, handler));
|
||||
return () =>
|
||||
handlers.forEach(({ eventName, handler }) => root.removeEventListener(eventName, handler));
|
||||
};
|
||||
}
|
||||
return lastSubscription;
|
||||
|
@ -1 +0,0 @@
|
||||
module.exports = require('./dist/deprecated');
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-backgrounds",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "A storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -25,15 +25,15 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/client-logger": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/client-logger": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"memoizerific": "^1.11.3",
|
||||
"react": "^16.8.2",
|
||||
"react": "^16.8.4",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -10,5 +10,5 @@ export const ColorIcon = styled.span(
|
||||
}),
|
||||
({ theme }) => ({
|
||||
boxShadow: `${theme.appBorderColor} 0 0 0 1px inset`,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
@ -1,7 +1,2 @@
|
||||
export const ADDON_ID = 'storybook/background';
|
||||
export const PARAM_KEY = 'backgrounds';
|
||||
|
||||
export const EVENTS = {
|
||||
SET: `${ADDON_ID}:set`,
|
||||
UNSET: `${ADDON_ID}:unset`,
|
||||
};
|
||||
|
@ -31,7 +31,10 @@ const createBackgroundSelectorItem = memoize(1000)(
|
||||
})
|
||||
);
|
||||
|
||||
const getSelectedBackgroundColor = (list: BackgroundConfig[], currentSelectedValue: string): string => {
|
||||
const getSelectedBackgroundColor = (
|
||||
list: BackgroundConfig[],
|
||||
currentSelectedValue: string
|
||||
): string => {
|
||||
if (!list.length) {
|
||||
return 'transparent';
|
||||
}
|
||||
@ -51,30 +54,36 @@ const getSelectedBackgroundColor = (list: BackgroundConfig[], currentSelectedVal
|
||||
return 'transparent';
|
||||
};
|
||||
|
||||
const getDisplayableState = memoize(10)((props: BackgroundToolProps, state: BackgroundToolState, change) => {
|
||||
const data = props.api.getCurrentStoryData();
|
||||
const list: BackgroundConfig[] = (data && data.parameters && data.parameters[PARAM_KEY]) || [];
|
||||
const getDisplayableState = memoize(10)(
|
||||
(props: BackgroundToolProps, state: BackgroundToolState, change) => {
|
||||
const data = props.api.getCurrentStoryData();
|
||||
const list: BackgroundConfig[] = (data && data.parameters && data.parameters[PARAM_KEY]) || [];
|
||||
|
||||
const selectedBackgroundColor = getSelectedBackgroundColor(list, state.selected);
|
||||
const selectedBackgroundColor = getSelectedBackgroundColor(list, state.selected);
|
||||
|
||||
let availableBackgroundSelectorItems: BackgroundSelectorItem[] = [];
|
||||
let availableBackgroundSelectorItems: BackgroundSelectorItem[] = [];
|
||||
|
||||
if (selectedBackgroundColor !== 'transparent') {
|
||||
availableBackgroundSelectorItems.push(createBackgroundSelectorItem('reset', 'Clear background', 'transparent', null, change));
|
||||
if (selectedBackgroundColor !== 'transparent') {
|
||||
availableBackgroundSelectorItems.push(
|
||||
createBackgroundSelectorItem('reset', 'Clear background', 'transparent', null, change)
|
||||
);
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
availableBackgroundSelectorItems = [
|
||||
...availableBackgroundSelectorItems,
|
||||
...list.map(({ name, value }) =>
|
||||
createBackgroundSelectorItem(null, name, value, true, change)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
items: availableBackgroundSelectorItems,
|
||||
selectedBackgroundColor,
|
||||
};
|
||||
}
|
||||
|
||||
if (list.length) {
|
||||
availableBackgroundSelectorItems = [
|
||||
...availableBackgroundSelectorItems,
|
||||
...list.map(({ name, value }) => createBackgroundSelectorItem(null, name, value, true, change)),
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
items: availableBackgroundSelectorItems,
|
||||
selectedBackgroundColor,
|
||||
};
|
||||
});
|
||||
);
|
||||
|
||||
interface BackgroundToolProps {
|
||||
api: {
|
||||
@ -119,7 +128,11 @@ export class BackgroundSelector extends Component<BackgroundToolProps, Backgroun
|
||||
|
||||
render() {
|
||||
const { expanded } = this.state;
|
||||
const { items, selectedBackgroundColor } = getDisplayableState(this.props, this.state, this.change);
|
||||
const { items, selectedBackgroundColor } = getDisplayableState(
|
||||
this.props,
|
||||
this.state,
|
||||
this.change
|
||||
);
|
||||
|
||||
return items.length ? (
|
||||
<Fragment>
|
||||
@ -136,11 +149,17 @@ export class BackgroundSelector extends Component<BackgroundToolProps, Backgroun
|
||||
placement="top"
|
||||
trigger="click"
|
||||
tooltipShown={expanded}
|
||||
onVisibilityChange={(newVisibility: boolean) => this.setState({ expanded: newVisibility })}
|
||||
onVisibilityChange={(newVisibility: boolean) =>
|
||||
this.setState({ expanded: newVisibility })
|
||||
}
|
||||
tooltip={<TooltipLinkList links={items} />}
|
||||
closeOnClick
|
||||
>
|
||||
<IconButton key="background" active={selectedBackgroundColor !== 'transparent'} title="Change the background of the preview">
|
||||
<IconButton
|
||||
key="background"
|
||||
active={selectedBackgroundColor !== 'transparent'}
|
||||
title="Change the background of the preview"
|
||||
>
|
||||
<Icons icon="photo" />
|
||||
</IconButton>
|
||||
</WithTooltip>
|
||||
|
@ -1,8 +0,0 @@
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
import backgrounds from '.';
|
||||
|
||||
export default deprecate(
|
||||
backgrounds,
|
||||
"addon-backgrounds: framework-specific imports are deprecated, just use `import backgrounds from '@storybook/addon-backgrounds`"
|
||||
);
|
@ -1,43 +1,18 @@
|
||||
import { addons, makeDecorator, StoryContext, StoryGetter, WrapperSettings } from '@storybook/addons';
|
||||
import { makeDecorator, StoryContext, StoryGetter } from '@storybook/addons';
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
import { REGISTER_SUBSCRIPTION } from '@storybook/core-events';
|
||||
import { EVENTS } from './constants';
|
||||
import { BackgroundConfig } from './models';
|
||||
|
||||
let prevBackgrounds: BackgroundConfig[];
|
||||
|
||||
const subscription = () => () => {
|
||||
prevBackgrounds = null;
|
||||
addons.getChannel().emit(EVENTS.UNSET);
|
||||
};
|
||||
|
||||
export const withBackgrounds = makeDecorator({
|
||||
name: 'withBackgrounds',
|
||||
parameterName: 'backgrounds',
|
||||
skipIfNoParametersOrOptions: true,
|
||||
allowDeprecatedUsage: true,
|
||||
wrapper: (getStory: StoryGetter, context: StoryContext, { options, parameters }: WrapperSettings) => {
|
||||
const data = parameters || options || [];
|
||||
const backgrounds = Array.isArray(data) ? data : Object.values(data);
|
||||
|
||||
if (backgrounds.length === 0) {
|
||||
// This decorator is kept purely so we produce a decorator that is compatible with both
|
||||
// `addDecorator(withBackgrounds(...))` and `addDecorator(withBackgrounds)`
|
||||
export const withBackgrounds = deprecate(
|
||||
makeDecorator({
|
||||
name: 'withBackgrounds',
|
||||
parameterName: 'backgrounds',
|
||||
wrapper: (getStory: StoryGetter, context: StoryContext) => {
|
||||
return getStory(context);
|
||||
}
|
||||
|
||||
if (prevBackgrounds !== backgrounds) {
|
||||
addons.getChannel().emit(EVENTS.SET, backgrounds);
|
||||
prevBackgrounds = backgrounds;
|
||||
}
|
||||
addons.getChannel().emit(REGISTER_SUBSCRIPTION, subscription);
|
||||
|
||||
return getStory(context);
|
||||
},
|
||||
});
|
||||
|
||||
export default deprecate(
|
||||
withBackgrounds,
|
||||
'The default export of @storybook/addon-backgrounds is deprecated, please `import { withBackgrounds }` instead'
|
||||
},
|
||||
}),
|
||||
`Note that withBackgrounds(options) has been replaced by addParameters({ backgrounds: options})
|
||||
Read more about it in the migration guide: https://github.com/storybooks/storybook/blob/master/MIGRATION.md`
|
||||
);
|
||||
|
||||
if (module && module.hot && module.hot.decline) {
|
||||
|
@ -1 +0,0 @@
|
||||
module.exports = require('./dist/deprecated');
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-centered",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook decorator to center components",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -23,7 +23,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-cssresources",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "A storybook addon to switch between css resources at runtime for your story",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -25,12 +25,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.2"
|
||||
"react": "^16.8.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-events",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Add events to your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,13 +24,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"format-json": "^1.0.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.8.4",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"react-textarea-autosize": "^7.0.4",
|
||||
"util-deprecate": "^1.0.2"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-google-analytics",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook addon for google analytics",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -20,11 +20,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"react-ga": "^2.5.3"
|
||||
"react-ga": "^2.5.7"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-graphql",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook addon to display the GraphiQL IDE",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,11 +22,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"graphiql": "^0.12.0",
|
||||
"graphql": "^14.1.1",
|
||||
"prop-types": "^15.6.2"
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-info",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "A Storybook addon to show additional information for your stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,23 +22,23 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/client-logger": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/client-logger": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"marksy": "^6.1.0",
|
||||
"nested-object-assign": "^1.0.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.2",
|
||||
"react-addons-create-fragment": "^15.5.3",
|
||||
"react-is": "^16.8.3",
|
||||
"nested-object-assign": "^1.0.3",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.8.4",
|
||||
"react-addons-create-fragment": "^15.6.2",
|
||||
"react-is": "^16.8.4",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-test-renderer": "^16.8.1"
|
||||
"react-test-renderer": "^16.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-jest",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "React storybook addon that show component jest report",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,14 +28,14 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.8.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.8.4",
|
||||
"upath": "^1.1.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-knobs",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook Addon Prop Editor Component",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,21 +22,21 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"escape-html": "^1.0.3",
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"global": "^4.3.2",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
"qs": "^6.5.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"qs": "^6.6.0",
|
||||
"react-color": "^2.17.0",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"react-select": "^2.3.0"
|
||||
"react-select": "^2.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
|
@ -3,7 +3,7 @@ import { shallow, mount } from 'enzyme';
|
||||
import { STORY_CHANGED } from '@storybook/core-events';
|
||||
import { TabsState } from '@storybook/components';
|
||||
|
||||
import { ThemeProvider, themes } from '@storybook/theming';
|
||||
import { ThemeProvider, themes, convert } from '@storybook/theming';
|
||||
import Panel from '../Panel';
|
||||
import { CHANGE, SET } from '../../shared';
|
||||
import PropForm from '../PropForm';
|
||||
@ -191,7 +191,7 @@ describe('Panel', () => {
|
||||
// We have to do a full mount.
|
||||
|
||||
const root = mount(
|
||||
<ThemeProvider theme={themes.light}>
|
||||
<ThemeProvider theme={convert(themes.light)}>
|
||||
<Panel channel={testChannel} api={testApi} active />
|
||||
</ThemeProvider>
|
||||
);
|
||||
@ -225,7 +225,7 @@ describe('Panel', () => {
|
||||
|
||||
it('should have one tab per groupId and an empty ALL tab when all are defined', () => {
|
||||
const root = mount(
|
||||
<ThemeProvider theme={themes.light}>
|
||||
<ThemeProvider theme={convert(themes.light)}>
|
||||
<Panel channel={testChannel} api={testApi} active />
|
||||
</ThemeProvider>
|
||||
);
|
||||
@ -265,7 +265,7 @@ describe('Panel', () => {
|
||||
|
||||
it('the ALL tab should have its own additional content when there are knobs both with and without a groupId', () => {
|
||||
const root = mount(
|
||||
<ThemeProvider theme={themes.light}>
|
||||
<ThemeProvider theme={convert(themes.light)}>
|
||||
<Panel channel={testChannel} api={testApi} active />
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
@ -2,6 +2,7 @@ import addons from '@storybook/addons';
|
||||
import { STORY_CHANGED, FORCE_RE_RENDER, REGISTER_SUBSCRIPTION } from '@storybook/core-events';
|
||||
import debounce from 'lodash.debounce';
|
||||
|
||||
import debounce from 'lodash.debounce';
|
||||
import KnobManager from './KnobManager';
|
||||
import { CHANGE, CLICK, RESET, SET } from './shared';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-links",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Story Links addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,13 +22,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"qs": "^6.5.2"
|
||||
"prop-types": "^15.7.2",
|
||||
"qs": "^6.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-notes",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Write notes for your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -23,17 +23,18 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/client-logger": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/client-logger": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"markdown-to-jsx": "^6.9.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/prop-types": "^15.5.7",
|
||||
"@types/prop-types": "^15.5.9",
|
||||
"@types/util-deprecate": "^1.0.0",
|
||||
"@types/webpack-env": "^1.13.7"
|
||||
},
|
||||
|
23
addons/notes/src/Panel.test.js
Normal file
23
addons/notes/src/Panel.test.js
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { SyntaxHighlighter as SyntaxHighlighterBase } from '@storybook/components';
|
||||
import { SyntaxHighlighter } from './Panel.tsx';
|
||||
|
||||
describe('NotesPanel', () => {
|
||||
describe('SyntaxHighlighter component', () => {
|
||||
it('should return code if className is undefined', () => {
|
||||
const wrapper = shallow(<SyntaxHighlighter>some text</SyntaxHighlighter>);
|
||||
const code = wrapper.find('code');
|
||||
expect(code.exists()).toBeTruthy();
|
||||
expect(code.text()).toBe('some text');
|
||||
});
|
||||
it('should return SyntaxHighlighterBase if there is a className prop', () => {
|
||||
const wrapper = shallow(
|
||||
<SyntaxHighlighter className="lang-jsx">some text</SyntaxHighlighter>
|
||||
);
|
||||
const syntaxHighlighterBase = wrapper.find(SyntaxHighlighterBase);
|
||||
expect(syntaxHighlighterBase.exists()).toBeTruthy();
|
||||
expect(syntaxHighlighterBase.prop('language')).toBe('jsx');
|
||||
});
|
||||
});
|
||||
});
|
@ -4,7 +4,12 @@ import { types } from '@storybook/addons';
|
||||
import { styled } from '@storybook/theming';
|
||||
import { STORY_RENDERED } from '@storybook/core-events';
|
||||
|
||||
import { SyntaxHighlighter as SyntaxHighlighterBase, Placeholder, DocumentFormatting, Link } from '@storybook/components';
|
||||
import {
|
||||
SyntaxHighlighter as SyntaxHighlighterBase,
|
||||
Placeholder,
|
||||
DocumentFormatting,
|
||||
Link,
|
||||
} from '@storybook/components';
|
||||
import Giphy from './giphy';
|
||||
import Markdown from 'markdown-to-jsx';
|
||||
|
||||
@ -41,7 +46,15 @@ function read(param: Parameters | undefined): string | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
const SyntaxHighlighter = (props: any) => <SyntaxHighlighterBase bordered copyable {...props} />;
|
||||
export const SyntaxHighlighter = (props: any) => {
|
||||
// markdown-to-jsx does not add className to inline code
|
||||
if (props.className === undefined) {
|
||||
return <code>{props.children}</code>;
|
||||
}
|
||||
// className: "lang-jsx"
|
||||
const language = props.className.split('-');
|
||||
return <SyntaxHighlighterBase language={language[1]} bordered copyable {...props} />;
|
||||
};
|
||||
|
||||
const defaultOptions = {
|
||||
overrides: {
|
||||
@ -104,22 +117,33 @@ export default class NotesPanel extends React.Component<Props, NotesPanelState>
|
||||
}
|
||||
|
||||
// TODO: memoize
|
||||
const extraElements = Object.entries(api.getElements(types.NOTES_ELEMENT)).reduce((acc, [k, v]) => ({ ...acc, [k]: v.render }), {});
|
||||
const options = { ...defaultOptions, overrides: { ...defaultOptions.overrides, ...extraElements } };
|
||||
const extraElements = Object.entries(api.getElements(types.NOTES_ELEMENT)).reduce(
|
||||
(acc, [k, v]) => ({ ...acc, [k]: v.render }),
|
||||
{}
|
||||
);
|
||||
const options = {
|
||||
...defaultOptions,
|
||||
overrides: { ...defaultOptions.overrides, ...extraElements },
|
||||
};
|
||||
|
||||
return value ? (
|
||||
<Panel className="addon-notes-container">
|
||||
<DocumentFormatting>
|
||||
<Markdown options={options}>{value}</Markdown>
|
||||
<DocumentFormatting>
|
||||
<Markdown options={options}>{value}</Markdown>
|
||||
</DocumentFormatting>
|
||||
</Panel>
|
||||
) : (
|
||||
<Placeholder>
|
||||
<React.Fragment>No notes yet</React.Fragment>
|
||||
<React.Fragment>
|
||||
No notes yet
|
||||
</React.Fragment>
|
||||
<React.Fragment>
|
||||
Learn how to <Link href="https://github.com/storybooks/storybook/tree/master/addons/notes" target="_blank" withArrow>document components in Markdown</Link>
|
||||
Learn how to{' '}
|
||||
<Link
|
||||
href="https://github.com/storybooks/storybook/tree/master/addons/notes"
|
||||
target="_blank"
|
||||
withArrow
|
||||
>
|
||||
document components in Markdown
|
||||
</Link>
|
||||
</React.Fragment>
|
||||
</Placeholder>
|
||||
);
|
||||
|
@ -8,26 +8,32 @@ export const withNotes = makeDecorator({
|
||||
skipIfNoParametersOrOptions: true,
|
||||
allowDeprecatedUsage: true,
|
||||
|
||||
wrapper: deprecate((getStory: StoryGetter, context: StoryContext, { options, parameters }: WrapperSettings) => {
|
||||
const storyOptions = parameters || options;
|
||||
wrapper: deprecate(
|
||||
(getStory: StoryGetter, context: StoryContext, { options, parameters }: WrapperSettings) => {
|
||||
const storyOptions = parameters || options;
|
||||
|
||||
const { text, markdown } =
|
||||
typeof storyOptions === 'string'
|
||||
? {
|
||||
text: storyOptions,
|
||||
markdown: undefined,
|
||||
}
|
||||
: storyOptions;
|
||||
const { text, markdown } =
|
||||
typeof storyOptions === 'string'
|
||||
? {
|
||||
text: storyOptions,
|
||||
markdown: undefined,
|
||||
}
|
||||
: storyOptions;
|
||||
|
||||
if (!text && !markdown) {
|
||||
throw new Error(`Parameter 'notes' must must be a string or an object with 'text' or 'markdown' properties`);
|
||||
}
|
||||
if (!text && !markdown) {
|
||||
throw new Error(
|
||||
`Parameter 'notes' must must be a string or an object with 'text' or 'markdown' properties`
|
||||
);
|
||||
}
|
||||
|
||||
return getStory(context);
|
||||
}, 'withNotes is deprecated'),
|
||||
return getStory(context);
|
||||
},
|
||||
'withNotes is deprecated'
|
||||
),
|
||||
});
|
||||
|
||||
export const withMarkdownNotes = deprecate((text: string, options: any) => {}, 'withMarkdownNotes is deprecated');
|
||||
export const withMarkdownNotes = deprecate((text: string, options: any) => {},
|
||||
'withMarkdownNotes is deprecated');
|
||||
|
||||
if (module && module.hot && module.hot.decline) {
|
||||
module.hot.decline();
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-backgrounds",
|
||||
"version": "5.0.0-beta.3",
|
||||
"private": true,
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "A storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,9 +25,9 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"prop-types": "^15.6.2"
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-knobs",
|
||||
"version": "5.0.0-beta.3",
|
||||
"private": true,
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Display storybook story knobs on your deviced.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -21,10 +22,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"deep-equal": "^1.0.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-native-color-picker": "^0.4.0",
|
||||
"react-native-modal-datetime-picker": "^6.0.0",
|
||||
"react-native-modal-selector": "^1.0.2",
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-notes",
|
||||
"version": "5.0.0-beta.3",
|
||||
"private": true,
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Write notes for your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -19,9 +20,9 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-native-simple-markdown": "^1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-options",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Options addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -21,8 +21,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -25,8 +25,8 @@
|
||||
"storybook": "start-storybook -p 6006"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"glob": "^7.1.3",
|
||||
"global": "^4.3.2",
|
||||
"jest-specific-snapshot": "^1.0.0",
|
||||
@ -34,9 +34,9 @@
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"enzyme-to-json": "^3.3.4",
|
||||
"jest-emotion": "^10.0.6",
|
||||
"react": "^16.8.2"
|
||||
"enzyme-to-json": "^3.3.5",
|
||||
"jest-emotion": "^10.0.7",
|
||||
"react": "^16.8.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -43,7 +43,13 @@ export const initModuleData = (storyObj: NgStory): any => {
|
||||
props,
|
||||
};
|
||||
|
||||
const moduleMeta = getModuleMeta([AppComponent, AnnotatedComponent], [AnnotatedComponent], [AppComponent], story, moduleMetadata);
|
||||
const moduleMeta = getModuleMeta(
|
||||
[AppComponent, AnnotatedComponent],
|
||||
[AnnotatedComponent],
|
||||
[AppComponent],
|
||||
story,
|
||||
moduleMetadata
|
||||
);
|
||||
|
||||
return {
|
||||
AppComponent,
|
||||
|
@ -120,10 +120,10 @@ exports[`Storyshots Welcome to Storybook 1`] = `
|
||||
<article
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#fff",
|
||||
"fontFamily": "\\"Helvetica Neue\\", Helvetica, \\"Segoe UI\\", Arial, freesans, sans-serif",
|
||||
"lineHeight": 1.4,
|
||||
"margin": 15,
|
||||
"maxWidth": 600,
|
||||
"padding": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
|
@ -100,10 +100,10 @@ exports[`Storyshots Welcome to Storybook 1`] = `
|
||||
<article
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#fff",
|
||||
"fontFamily": "\\"Helvetica Neue\\", Helvetica, \\"Segoe UI\\", Arial, freesans, sans-serif",
|
||||
"lineHeight": 1.4,
|
||||
"margin": 15,
|
||||
"maxWidth": 600,
|
||||
"padding": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
|
@ -4,10 +4,10 @@ exports[`Storyshots Welcome to Storybook 1`] = `
|
||||
<article
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#fff",
|
||||
"fontFamily": "\\"Helvetica Neue\\", Helvetica, \\"Segoe UI\\", Arial, freesans, sans-serif",
|
||||
"lineHeight": 1.4,
|
||||
"margin": 15,
|
||||
"maxWidth": 600,
|
||||
"padding": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
|
@ -4,10 +4,10 @@ exports[`Storyshots Welcome to Storybook 1`] = `
|
||||
<article
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#fff",
|
||||
"fontFamily": "\\"Helvetica Neue\\", Helvetica, \\"Segoe UI\\", Arial, freesans, sans-serif",
|
||||
"lineHeight": 1.4,
|
||||
"margin": 15,
|
||||
"maxWidth": 600,
|
||||
"padding": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots-puppeteer",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Image snappshots addition to StoryShots base on puppeteer",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,11 +22,11 @@
|
||||
"prepare": "node ../../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/router": "5.0.0-beta.3",
|
||||
"@storybook/node-logger": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"jest-image-snapshot": "^2.6.0",
|
||||
"puppeteer": "^1.12.0",
|
||||
"@storybook/node-logger": "5.1.0-alpha.4",
|
||||
"@storybook/router": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"jest-image-snapshot": "^2.8.1",
|
||||
"puppeteer": "^1.12.2",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -23,14 +23,14 @@ import '@storybook/addon-storysource/register';
|
||||
Use this hook to a custom webpack.config. This will generate a decorator call in every story:
|
||||
|
||||
```js
|
||||
module.exports = function (baseConfig, env, defaultConfig) {
|
||||
defaultConfig.module.rules.push({
|
||||
module.exports = function ({ config }) {
|
||||
config.module.rules.push({
|
||||
test: /\.stories\.jsx?$/,
|
||||
loaders: [require.resolve('@storybook/addon-storysource/loader')],
|
||||
enforce: 'pre',
|
||||
});
|
||||
|
||||
return defaultConfig;
|
||||
return config;
|
||||
};
|
||||
```
|
||||
|
||||
@ -72,7 +72,7 @@ The prettier configuration that will be used to format the story source in the a
|
||||
Defaults:
|
||||
```js
|
||||
{
|
||||
printWidth: 120,
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
bracketSpacing: true,
|
||||
trailingComma: 'es5',
|
||||
@ -91,7 +91,7 @@ module.exports = function (baseConfig, env, defaultConfig) {
|
||||
loader: require.resolve('@storybook/addon-storysource/loader'),
|
||||
options: {
|
||||
prettierConfig: {
|
||||
printWidth: 80,
|
||||
printWidth: 100,
|
||||
singleQuote: false,
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storysource",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Stories addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,15 +22,15 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"@storybook/router": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/router": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"estraverse": "^4.2.0",
|
||||
"loader-utils": "^1.2.1",
|
||||
"loader-utils": "^1.2.3",
|
||||
"prettier": "^1.16.4",
|
||||
"prop-types": "^15.6.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-syntax-highlighter": "^8.0.1",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
const defaultOptions = {
|
||||
prettierConfig: {
|
||||
printWidth: 120,
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
bracketSpacing: true,
|
||||
trailingComma: 'es5',
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Storybook Viewport Addon
|
||||
|
||||
Storybook Viewport Addon allows your stories to be displayed in different sizes and layouts in [Storybook](https://storybook.js.org). This helps build responsive components inside of Storybook.
|
||||
Storybook Viewport Addon allows your stories to be displayed in different sizes and layouts in [Storybook](https://storybook.js.org). This helps build responsive components inside of Storybook.
|
||||
|
||||
[Framework Support](https://github.com/storybooks/storybook/blob/master/ADDONS_SUPPORT.md)
|
||||
|
||||
@ -28,21 +28,30 @@ import '@storybook/addon-viewport/register';
|
||||
|
||||
## Configuration
|
||||
|
||||
Import and use the `configureViewport` function in your `config.js` file.
|
||||
The viewport addon is configured by story parameters with the `viewport` key. To configure globally, import `addParameters` from your app layer in your `config.js` file.
|
||||
|
||||
```js
|
||||
import { configureViewport } from '@storybook/addon-viewport';
|
||||
import { addParameters } from '@storybook/react';
|
||||
|
||||
addParameters({ viewport: options });
|
||||
```
|
||||
|
||||
Options can take a object with the following keys:
|
||||
|
||||
### defaultViewport : String
|
||||
----
|
||||
|
||||
---
|
||||
|
||||
Setting this property to, let say `iphone6`, will make `iPhone 6` the default device/viewport for all stories. Default is `'responsive'` which fills 100% of the preview area.
|
||||
|
||||
### viewports : Object
|
||||
----
|
||||
|
||||
---
|
||||
|
||||
A key-value pair of viewport's key and properties (see `Viewport` definition below) for all viewports to be displayed. Default is [`INITIAL_VIEWPORTS`](src/shared/index.js)
|
||||
|
||||
#### Viewport Model
|
||||
|
||||
```js
|
||||
{
|
||||
/**
|
||||
@ -70,154 +79,81 @@ A key-value pair of viewport's key and properties (see `Viewport` definition bel
|
||||
}
|
||||
```
|
||||
|
||||
## Decorators
|
||||
## Configuring per component or story
|
||||
|
||||
Sometimes you want to show collection of mobile stories, and you know those stories look horible on desktop (`responsive`), so you think you need to change the default viewport only for those?
|
||||
Parameters can be configured for a whole set of stories or a single story via the standard parameter API:
|
||||
|
||||
Here is the answer, with `withViewport` decorator, you can change the default viewport of single, multiple, or all stories.
|
||||
|
||||
`withViewport` accepts either
|
||||
* A `String`, which represents the default viewport, or
|
||||
* An `Object`, which looks like
|
||||
```js
|
||||
{
|
||||
name: 'iphone6', // default viewport
|
||||
onViewportChange({ viewport }) { // called whenever different viewport is selected from the dropdown
|
||||
import addStories from '@storybook/react';
|
||||
|
||||
}
|
||||
}
|
||||
addStories('Stories', module)
|
||||
// To set a default viewport for all the stories for this component
|
||||
.addParameters({ viewport: { defaultViewport: 'iphone6' }})
|
||||
.add('story', () => </>, { viewport: 'iphonex' });
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Simply import the Storybook Viewport Addon in the `addons.js` file in your `.storybook` directory.
|
||||
|
||||
```js
|
||||
import '@storybook/addon-viewport/register'
|
||||
```
|
||||
|
||||
This will register the Viewport Addon to Storybook and will show up in the action area.
|
||||
|
||||
|
||||
### Use Custom Set of Devices
|
||||
|
||||
This will replace all previous devices with `Kindle Fire 2` and `Kindle Fire HD` by simply calling `configureViewport` with the two devices as `viewports` in `config.js` file in your `.storybook` directory.
|
||||
This will replace all previous devices with `Kindle Fire 2` and `Kindle Fire HD` by simply calling `addParameters` with the two devices as `viewports` in `config.js` file in your `.storybook` directory.
|
||||
|
||||
```js
|
||||
import { configureViewport } from '@storybook/addon-viewport';
|
||||
import { addParameters } from '@storybook/react';
|
||||
|
||||
const newViewports = {
|
||||
kindleFire2: {
|
||||
name: 'Kindle Fire 2',
|
||||
styles: {
|
||||
width: '600px',
|
||||
height: '963px'
|
||||
}
|
||||
height: '963px',
|
||||
},
|
||||
},
|
||||
kindleFireHD: {
|
||||
name: 'Kindle Fire HD',
|
||||
styles: {
|
||||
width: '533px',
|
||||
height: '801px'
|
||||
}
|
||||
}
|
||||
height: '801px',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
configureViewport({
|
||||
viewports: newViewports
|
||||
addParameters({
|
||||
viewport: { viewports: newViewports },
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Add New Device
|
||||
|
||||
This will add both `Kindle Fire 2` and `Kindle Fire HD` to the list of devices. This is acheived by making use of the exported [`INITIAL_VIEWPORTS`](src/shared/index.js) property, by merging it with the new viewports and pass the result as `viewports` to `configureViewport` function
|
||||
|
||||
```js
|
||||
import { configureViewport, INITIAL_VIEWPORTS } from '@storybook/addon-viewport';
|
||||
import { addParameters } from '@storybook/react';
|
||||
import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport';
|
||||
|
||||
const newViewports = {
|
||||
kindleFire2: {
|
||||
name: 'Kindle Fire 2',
|
||||
styles: {
|
||||
width: '600px',
|
||||
height: '963px'
|
||||
}
|
||||
height: '963px',
|
||||
},
|
||||
},
|
||||
kindleFireHD: {
|
||||
name: 'Kindle Fire HD',
|
||||
styles: {
|
||||
width: '533px',
|
||||
height: '801px'
|
||||
}
|
||||
}
|
||||
height: '801px',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
configureViewport({
|
||||
viewports: {
|
||||
...INITIAL_VIEWPORTS,
|
||||
...newViewports
|
||||
}
|
||||
addParameters({
|
||||
viewport: {
|
||||
viewports: {
|
||||
...INITIAL_VIEWPORTS,
|
||||
...newViewports,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Change The Default Viewport
|
||||
|
||||
This will make `iPhone 6` the default viewport for all stories.
|
||||
|
||||
```js
|
||||
import { configureViewport } from '@storybook/addon-viewport';
|
||||
|
||||
configureViewport({
|
||||
defaultViewport: 'iphone6'
|
||||
});
|
||||
```
|
||||
|
||||
## withViewport Decorator
|
||||
|
||||
Change the default viewport for single/multiple/global stories, or listen to viewport selection changes
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
import { storiesOf, addDecorator } from '@storybook/react';
|
||||
import { withViewport } from '@storybook/addon-viewport';
|
||||
|
||||
// Globablly
|
||||
addDecorator(withViewport('iphone5'));
|
||||
|
||||
// Collection
|
||||
storiesOf('Decorator with string', module)
|
||||
.addDecorator(withViewport('iphone6'))
|
||||
.add('iPhone 6', () => (
|
||||
<h1>
|
||||
Do I look good on <b>iPhone 6</b>?
|
||||
</h1>
|
||||
));
|
||||
|
||||
// Single
|
||||
storiesOf('Parameterized story', module)
|
||||
.addDecorator(withViewport())
|
||||
.add(
|
||||
'iPad',
|
||||
() => (
|
||||
<h1>
|
||||
Do I look good on <b>iPad</b>?
|
||||
</h1>
|
||||
),
|
||||
{ viewport: 'ipad' }
|
||||
);
|
||||
|
||||
storiesOf('Decorator with object', module)
|
||||
.addDecorator(
|
||||
withViewport({
|
||||
onViewportChange({ viewport }) {
|
||||
console.log(`Viewport changed: ${viewport.name} (${viewport.type})`); // e.g. Viewport changed: iphone6 (mobile)
|
||||
},
|
||||
})
|
||||
)
|
||||
.add('onViewportChange', () => <MobileFirstComponent />);
|
||||
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-viewport",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook addon to change the viewport size to mobile",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -21,15 +21,15 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/client-logger": "5.0.0-beta.3",
|
||||
"@storybook/components": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/theming": "5.0.0-beta.3",
|
||||
"core-js": "^2.6.2",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/client-logger": "5.1.0-alpha.4",
|
||||
"@storybook/components": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/theming": "5.1.0-alpha.4",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"memoizerific": "^1.11.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -4,4 +4,3 @@ exports.configureViewport = preview.configureViewport;
|
||||
exports.DEFAULT_VIEWPORT = preview.DEFAULT_VIEWPORT;
|
||||
exports.INITIAL_VIEWPORTS = preview.INITIAL_VIEWPORTS;
|
||||
exports.withViewport = preview.withViewport;
|
||||
exports.Viewport = preview.Viewport;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import memoize from 'memoizerific';
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
import { Global } from '@storybook/theming';
|
||||
|
||||
@ -8,6 +9,7 @@ import { Icons, IconButton, WithTooltip, TooltipLinkList } from '@storybook/comp
|
||||
import { SET_STORIES } from '@storybook/core-events';
|
||||
|
||||
import { PARAM_KEY } from './constants';
|
||||
import { INITIAL_VIEWPORTS, DEFAULT_VIEWPORT } from './defaults';
|
||||
|
||||
const toList = memoize(50)(items =>
|
||||
items ? Object.entries(items).map(([id, value]) => ({ ...value, id })) : []
|
||||
@ -26,14 +28,35 @@ const createItem = memoize(1000)((id, name, value, change) => ({
|
||||
|
||||
const flip = ({ width, height }) => ({ height: width, width: height });
|
||||
|
||||
const deprecatedViewportString = deprecate(
|
||||
() => 0,
|
||||
'The viewport parameter must be an object with keys `viewports` and `defaultViewport`'
|
||||
);
|
||||
const deprecateOnViewportChange = deprecate(
|
||||
() => 0,
|
||||
'The viewport parameter `onViewportChange` is no longer supported'
|
||||
);
|
||||
|
||||
const getState = memoize(10)((props, state, change) => {
|
||||
const data = props.api.getCurrentStoryData();
|
||||
const list = toList(data && data.parameters && data.parameters[PARAM_KEY]);
|
||||
const parameters = data && data.parameters && data.parameters[PARAM_KEY];
|
||||
|
||||
if (parameters && typeof parameters !== 'object') {
|
||||
deprecatedViewportString();
|
||||
}
|
||||
|
||||
const { disable, viewports, defaultViewport, onViewportChange } = parameters || {};
|
||||
|
||||
if (onViewportChange) {
|
||||
deprecateOnViewportChange();
|
||||
}
|
||||
|
||||
const list = disable ? [] : toList(viewports || INITIAL_VIEWPORTS);
|
||||
|
||||
const selected =
|
||||
state.selected === 'responsive' || list.find(i => i.id === state.selected)
|
||||
? state.selected
|
||||
: list.find(i => i.default) || 'responsive';
|
||||
: list.find(i => i.default) || defaultViewport || DEFAULT_VIEWPORT;
|
||||
|
||||
const resets =
|
||||
selected !== 'responsive'
|
||||
@ -106,9 +129,13 @@ export default class ViewportTool extends Component {
|
||||
<Global
|
||||
styles={{
|
||||
[`#${iframeId}`]: {
|
||||
border: '10px solid black',
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
margin: '10px auto',
|
||||
border: '1px solid #888',
|
||||
borderRadius: 4,
|
||||
margin: 10,
|
||||
boxShadow: '0 4px 8px 0 rgba(0,0,0,0.12), 0 2px 4px 0 rgba(0,0,0,0.08);',
|
||||
boxSizing: 'content-box',
|
||||
|
||||
...(isRotated ? flip(item.value || {}) : item.value || {}),
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
export const ADDON_ID = 'storybook/viewport';
|
||||
export const PARAM_KEY = 'viewports';
|
||||
export const PARAM_KEY = 'viewport';
|
||||
|
||||
export default {
|
||||
UPDATE: `${ADDON_ID}/update`,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
export { INITIAL_VIEWPORTS, DEFAULT_VIEWPORT } from '../defaults';
|
||||
export { default as withViewport, Viewport } from './withViewport';
|
||||
export { default as withViewport } from './withViewport';
|
||||
|
||||
export const configureViewport = deprecate(() => {},
|
||||
'usage is deprecated, use .addParameters({ viewport }) instead');
|
||||
'configureViewport is no longer supported, use .addParameters({ viewport }) instead');
|
||||
|
@ -3,17 +3,11 @@ import deprecate from 'util-deprecate';
|
||||
|
||||
const withViewport = makeDecorator({
|
||||
name: 'withViewport',
|
||||
parameterName: 'viewports',
|
||||
allowDeprecatedUsage: true,
|
||||
parameterName: 'viewport',
|
||||
wrapper: deprecate(
|
||||
(getStory, context) => getStory(context),
|
||||
'usage is deprecated, use .addParameters({ viewport }) instead'
|
||||
'withViewport is no longer supported, use .addParameters({ viewport }) instead'
|
||||
),
|
||||
});
|
||||
|
||||
export default withViewport;
|
||||
|
||||
export const Viewport = deprecate(
|
||||
({ children }) => children,
|
||||
`<Viewport> usage is deprecated, use .addParameters({ viewport }) instead`
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/angular",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Angular: Develop Angular Components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -26,17 +26,17 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/node-logger": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"@storybook/node-logger": "5.1.0-alpha.4",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"fork-ts-checker-webpack-plugin": "^0.5.2",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"sass-loader": "^7.1.0",
|
||||
"ts-loader": "^5.3.2",
|
||||
"ts-loader": "^5.3.3",
|
||||
"tsconfig-paths-webpack-plugin": "^3.2.0",
|
||||
"webpack": "^4.29.3"
|
||||
"webpack": "^4.29.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"zone.js": "^0.8.29"
|
||||
@ -50,7 +50,7 @@
|
||||
"@angular/platform-browser": ">=6.0.0",
|
||||
"@angular/platform-browser-dynamic": ">=6.0.0",
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"zone.js": "^0.8.27"
|
||||
"zone.js": "^0.8.29"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -9,7 +9,10 @@ export const moduleMetadata = (metadata: Partial<NgModuleMetadata>) => (storyFn:
|
||||
...story,
|
||||
moduleMetadata: {
|
||||
declarations: [...(metadata.declarations || []), ...(storyMetadata.declarations || [])],
|
||||
entryComponents: [...(metadata.entryComponents || []), ...(storyMetadata.entryComponents || [])],
|
||||
entryComponents: [
|
||||
...(metadata.entryComponents || []),
|
||||
...(storyMetadata.entryComponents || []),
|
||||
],
|
||||
imports: [...(metadata.imports || []), ...(storyMetadata.imports || [])],
|
||||
schemas: [...(metadata.schemas || []), ...(storyMetadata.schemas || [])],
|
||||
providers: [...(metadata.providers || []), ...(storyMetadata.providers || [])],
|
||||
|
@ -51,7 +51,13 @@ const initModule = (storyFn: IStoryFn) => {
|
||||
props,
|
||||
};
|
||||
|
||||
return getModule([AppComponent, AnnotatedComponent], [AnnotatedComponent], [AppComponent], story, moduleMetadata);
|
||||
return getModule(
|
||||
[AppComponent, AnnotatedComponent],
|
||||
[AnnotatedComponent],
|
||||
[AppComponent],
|
||||
story,
|
||||
moduleMetadata
|
||||
);
|
||||
};
|
||||
|
||||
const staticRoot = document.getElementById('root');
|
||||
|
@ -7,39 +7,49 @@ import { Component, Output, EventEmitter } from '@angular/core';
|
||||
<h1>Welcome to storybook</h1>
|
||||
<p>This is a UI component dev environment for your app.</p>
|
||||
<p>
|
||||
We've added some basic stories inside the <span class="inline-code">src/stories</span> directory. <br />
|
||||
A story is a single state of one or more UI components. You can have as many stories as you want. <br />
|
||||
We've added some basic stories inside the
|
||||
<span class="inline-code">src/stories</span> directory. <br />
|
||||
A story is a single state of one or more UI components. You can have as many stories as you
|
||||
want. <br />
|
||||
(Basically a story is like a visual test case.)
|
||||
</p>
|
||||
<p>
|
||||
See these sample <a (click)="showApp.emit($event)" role="button" tabIndex="0">stories</a> for a component called
|
||||
<span class="inline-code">Button</span> .
|
||||
See these sample
|
||||
<a (click)="showApp.emit($event)" role="button" tabIndex="0">stories</a> for a component
|
||||
called <span class="inline-code">Button</span> .
|
||||
</p>
|
||||
<p>
|
||||
Just like that, you can add your own components as stories. <br />
|
||||
You can also edit those components and see changes right away. <br />
|
||||
(Try editing the <span class="inline-code">Button</span> stories located at <span class="inline-code">src/stories/index.js</span>.)
|
||||
(Try editing the <span class="inline-code">Button</span> stories located at
|
||||
<span class="inline-code">src/stories/index.js</span>.)
|
||||
</p>
|
||||
<p>
|
||||
Usually we create stories with smaller UI components in the app.<br />
|
||||
Have a look at the
|
||||
<a href="https://storybook.js.org/basics/writing-stories" target="_blank" rel="noopener noreferrer"> Writing Stories </a> section in
|
||||
our documentation.
|
||||
<a
|
||||
href="https://storybook.js.org/basics/writing-stories"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Writing Stories
|
||||
</a>
|
||||
section in our documentation.
|
||||
</p>
|
||||
<p class="note">
|
||||
<b>NOTE:</b> <br />
|
||||
Have a look at the <span class="inline-code">.storybook/webpack.config.js</span> to add webpack loaders and plugins you are using in
|
||||
this project.
|
||||
Have a look at the <span class="inline-code">.storybook/webpack.config.js</span> to add
|
||||
webpack loaders and plugins you are using in this project.
|
||||
</p>
|
||||
</main>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
main {
|
||||
margin: 15px;
|
||||
max-width: 600;
|
||||
padding: 15px;
|
||||
line-height: 1.4;
|
||||
fontfamily: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.note {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/ember",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.",
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/ember",
|
||||
"bugs": {
|
||||
@ -23,10 +23,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ember/test-helpers": "^1.3.1",
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@ember/test-helpers": "^1.5.0",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/html",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -25,9 +25,9 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"html-loader": "^0.5.5",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/marko",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Marko: Develop Marko Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -26,17 +26,17 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"marko-loader": "^1.3.3",
|
||||
"marko-loader": "^1.5.0",
|
||||
"raw-loader": "^1.0.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"marko": "^4.10.0",
|
||||
"marko": "^4.15.2",
|
||||
"marko-widgets": "^7.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -8,6 +8,9 @@ export function webpack(config) {
|
||||
{
|
||||
test: /\.marko$/,
|
||||
loader: require.resolve('marko-loader'),
|
||||
options: {
|
||||
compiler: require.resolve('marko/compiler'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/mithril",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Mithril: Develop Mithril Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -27,9 +27,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/polymer",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Polymer: Develop Polymer components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -25,13 +25,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"@webcomponents/webcomponentsjs": "^1.2.0",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"webpack": "^4.29.3"
|
||||
"webpack": "^4.29.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lit-html": "^1.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { document } from 'global';
|
||||
import { stripIndents } from 'common-tags';
|
||||
import { html, render, TemplateResult } from 'lit-html';
|
||||
import { render, TemplateResult } from 'lit-html';
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
|
||||
@ -32,10 +32,12 @@ export default function renderMain({
|
||||
// `render` stores the TemplateInstance in the Node and tries to update based on that.
|
||||
// Since we reuse `rootElement` for all stories, remove the stored instance first.
|
||||
// But forceRender means that it's the same story, so we want too keep the state in that case.
|
||||
if (!forceRender) {
|
||||
render(html``, rootElement);
|
||||
if (!forceRender || !rootElement.querySelector('[id="root-inner"]')) {
|
||||
rootElement.innerHTML = '<div id="root-inner"></div>';
|
||||
}
|
||||
render(element, rootElement);
|
||||
const renderTo = rootElement.querySelector('[id="root-inner"]');
|
||||
|
||||
render(element, renderTo);
|
||||
} else {
|
||||
rootElement.innerHTML = '';
|
||||
rootElement.appendChild(element);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/preact",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Preact: Develop Preact Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -27,9 +27,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
@ -38,7 +38,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"preact": "^8.3.1"
|
||||
"preact": "^8.4.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "@storybook/react-native",
|
||||
"version": "5.0.0-beta.3",
|
||||
"private": true,
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "A better way to develop React Native Components for your app",
|
||||
"keywords": [
|
||||
"react",
|
||||
@ -26,12 +27,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.0.0-beta.3",
|
||||
"@storybook/channel-websocket": "5.0.0-beta.3",
|
||||
"@storybook/channels": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core-events": "5.0.0-beta.3",
|
||||
"@storybook/ui": "5.0.0-beta.3",
|
||||
"@storybook/addons": "5.1.0-alpha.4",
|
||||
"@storybook/channel-websocket": "5.1.0-alpha.4",
|
||||
"@storybook/channels": "5.1.0-alpha.4",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"@storybook/core-events": "5.1.0-alpha.4",
|
||||
"@storybook/ui": "5.1.0-alpha.4",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-plugin-macros": "^2.4.5",
|
||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||
@ -46,25 +47,26 @@
|
||||
"babel-runtime": "^6.26.0",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.2.0",
|
||||
"commander": "^2.19.0",
|
||||
"core-js": "^2.6.5",
|
||||
"dotenv-webpack": "^1.7.0",
|
||||
"ejs": "^2.6.1",
|
||||
"express": "^4.16.3",
|
||||
"express": "^4.16.4",
|
||||
"find-cache-dir": "^2.0.0",
|
||||
"global": "^4.3.2",
|
||||
"html-webpack-plugin": "^4.0.0-beta.2",
|
||||
"json5": "^2.1.0",
|
||||
"lazy-universal-dotenv": "^2.0.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"raw-loader": "^1.0.0",
|
||||
"react-dev-utils": "^7.0.1",
|
||||
"react-dev-utils": "^8.0.0",
|
||||
"react-native-swipe-gestures": "^1.0.2",
|
||||
"shelljs": "^0.8.2",
|
||||
"url-parse": "^1.4.3",
|
||||
"shelljs": "^0.8.3",
|
||||
"url-parse": "^1.4.4",
|
||||
"uuid": "^3.3.2",
|
||||
"webpack": "^4.29.3",
|
||||
"webpack-dev-middleware": "^3.5.2",
|
||||
"webpack": "^4.29.6",
|
||||
"webpack-dev-middleware": "^3.6.0",
|
||||
"webpack-hot-middleware": "^2.24.3",
|
||||
"ws": "^6.1.3"
|
||||
"ws": "^6.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-native": "^0.52.2"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/react",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -29,22 +29,22 @@
|
||||
"@babel/plugin-transform-react-constant-elements": "^7.2.0",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/node-logger": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"@storybook/node-logger": "5.1.0-alpha.4",
|
||||
"@svgr/webpack": "^4.0.3",
|
||||
"babel-plugin-named-asset-import": "^0.3.1",
|
||||
"babel-plugin-react-docgen": "^2.0.2",
|
||||
"babel-preset-react-app": "^7.0.1",
|
||||
"babel-preset-react-app": "^7.0.2",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"lodash": "^4.17.11",
|
||||
"mini-css-extract-plugin": "^0.5.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-dev-utils": "^7.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-dev-utils": "^8.0.0",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"semver": "^5.6.0",
|
||||
"webpack": "^4.29.3"
|
||||
"webpack": "^4.29.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
|
@ -5,10 +5,10 @@ const Main = props => (
|
||||
<article
|
||||
{...props}
|
||||
style={{
|
||||
margin: 15,
|
||||
maxWidth: 600,
|
||||
padding: 15,
|
||||
lineHeight: 1.4,
|
||||
fontFamily: '"Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif',
|
||||
backgroundColor: '#fff',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/riot",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for riot.js: View riot snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -25,16 +25,16 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"raw-loader": "^1.0.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
|
||||
"@babel/preset-env": "^7.3.1",
|
||||
"@babel/preset-env": "^7.3.4",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/svelte",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -26,15 +26,15 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte": "^2.16.1",
|
||||
"svelte-loader": "^2.12.0"
|
||||
"svelte-loader": "^2.13.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/vue",
|
||||
"version": "5.0.0-beta.3",
|
||||
"version": "5.1.0-alpha.4",
|
||||
"description": "Storybook for Vue: Develop Vue Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -26,23 +26,23 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.0.0-beta.3",
|
||||
"@storybook/core": "5.1.0-alpha.4",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"core-js": "^2.6.5",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-preset-vue": "^2.0.2",
|
||||
"vue": "^2.6.3",
|
||||
"vue-loader": "15.6.2",
|
||||
"vue-template-compiler": "^2.6.3"
|
||||
"vue": "^2.6.8",
|
||||
"vue-loader": "^15.7.0",
|
||||
"vue-template-compiler": "^2.6.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"vue": ">=2.5.16",
|
||||
"vue-loader": ">=15.x.x",
|
||||
"vue-template-compiler": ">=2.5.16"
|
||||
"vue": "^2.6.8",
|
||||
"vue-loader": "^15.7.0",
|
||||
"vue-template-compiler": "^2.6.8"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -8,20 +8,22 @@ module.exports = {
|
||||
docSections: {
|
||||
basics: [
|
||||
'/basics/introduction/',
|
||||
'/basics/quick-start-guide/',
|
||||
'/basics/slow-start-guide/',
|
||||
'/basics/guide-react/',
|
||||
'/basics/guide-react-native/',
|
||||
'/basics/guide-vue/',
|
||||
'/basics/guide-angular/',
|
||||
'/basics/guide-mithril/',
|
||||
'/basics/guide-ember/',
|
||||
'/basics/writing-stories/',
|
||||
'/basics/exporting-storybook/',
|
||||
'/basics/faq/',
|
||||
'/basics/community/',
|
||||
'/basics/live-examples/',
|
||||
],
|
||||
guides: [
|
||||
'/guides/quick-start-guide/',
|
||||
'/guides/slow-start-guide/',
|
||||
'/guides/guide-react/',
|
||||
'/guides/guide-react-native/',
|
||||
'/guides/guide-vue/',
|
||||
'/guides/guide-angular/',
|
||||
'/guides/guide-mithril/',
|
||||
'/guides/guide-ember/',
|
||||
'/guides/guide-riot/',
|
||||
],
|
||||
configurations: [
|
||||
'/configurations/options-parameter/',
|
||||
'/configurations/default-config/',
|
||||
@ -45,7 +47,6 @@ module.exports = {
|
||||
addons: [
|
||||
'/addons/introduction/',
|
||||
'/addons/using-addons/',
|
||||
'/addons/addon-gallery/',
|
||||
'/addons/writing-addons/',
|
||||
'/addons/api/',
|
||||
],
|
||||
|
@ -14,6 +14,24 @@ function pagesToSitemap(pages) {
|
||||
}));
|
||||
}
|
||||
|
||||
function getVersionData(distTag) {
|
||||
const versionFile = `${__dirname}/src/versions/${distTag}.json`;
|
||||
if (!fs.existsSync(versionFile)) {
|
||||
return null;
|
||||
}
|
||||
const data = {
|
||||
[distTag]: JSON.parse(fs.readFileSync(versionFile)),
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
function generateVersionsFile() {
|
||||
const latest = getVersionData('latest');
|
||||
const next = getVersionData('next');
|
||||
const data = { ...latest, ...next };
|
||||
fs.writeFileSync(`${__dirname}/public/versions.json`, JSON.stringify(data));
|
||||
}
|
||||
|
||||
function generateSitemap(pages) {
|
||||
const sitemap = sm.createSitemap({
|
||||
hostname: 'https://storybook.js.org',
|
||||
@ -36,6 +54,7 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
`);
|
||||
generateVersionsFile();
|
||||
generateSitemap(result.data.allSitePage.edges.map(({ node }) => node));
|
||||
},
|
||||
onCreateNode({ node, boundActionCreators, getNode }) {
|
||||
|
@ -14,9 +14,7 @@
|
||||
"build-storybook": "build-storybook",
|
||||
"dev": "gatsby develop",
|
||||
"serve": "gatsby serve",
|
||||
"storybook": "start-storybook -p 9009 -s src/pages",
|
||||
"snyk-protect": "snyk protect",
|
||||
"prepare": "npm run snyk-protect"
|
||||
"storybook": "start-storybook -p 9009 -s src/pages"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addon-actions": "5.0.0-rc.1",
|
||||
@ -28,7 +26,7 @@
|
||||
"common-tags": "^1.8.0",
|
||||
"gatsby": "^1.9.279",
|
||||
"gatsby-link": "^1.6.45",
|
||||
"gatsby-plugin-sharp": "^2.0.12",
|
||||
"gatsby-plugin-sharp": "^1.6.48",
|
||||
"gatsby-remark-autolink-headers": "^1.4.19",
|
||||
"gatsby-remark-copy-linked-files": "^1.5.37",
|
||||
"gatsby-remark-images": "^1.5.67",
|
||||
@ -37,17 +35,21 @@
|
||||
"gatsby-transformer-remark": "^1.7.44",
|
||||
"global": "^4.3.2",
|
||||
"highlight.js": "^9.14.2",
|
||||
"is-builtin-module": "^3.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"marked": "^0.5.2",
|
||||
"polished": "^3.0.3",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^15.6.2",
|
||||
"react": "^16.8.3",
|
||||
"react-document-title": "^2.0.3",
|
||||
"react-dom": "^15.6.2",
|
||||
"react-dom": "^16.8.3",
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-popper-tooltip": "^2.8.1",
|
||||
"react-router": "^4.3.1",
|
||||
"react-stack-grid": "^0.7.1",
|
||||
"recompose": "^0.30.0",
|
||||
"sitemap": "^2.1.0",
|
||||
"snyk": "^1.134.2"
|
||||
},
|
||||
"snyk": true
|
||||
"styled-components": "^4.1.3",
|
||||
"validatorjs": "^3.15.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { window } from 'global';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import Nav from '../Nav';
|
||||
import NavDropdown from '../Nav/dropdown';
|
||||
import Content from '../Content';
|
||||
@ -12,9 +13,33 @@ const getEditUrl = (selectedSectionId, selectedItemId) => {
|
||||
return `${gitHubRepoUrl}/blob/master/docs/src/pages/${docPath}/index.md`;
|
||||
};
|
||||
|
||||
class Search extends Component {
|
||||
componentDidMount() {
|
||||
window.docsearch({
|
||||
apiKey: 'a4f7f972f1d8f99a66e237e7fd2e489f',
|
||||
indexName: 'storybook-js',
|
||||
inputSelector: '#search',
|
||||
debug: false,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="search">
|
||||
<input
|
||||
className="form-control form-control-sm"
|
||||
type="search"
|
||||
id="search"
|
||||
placeholder="type to search"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const Container = ({ sections, selectedItem, selectedSectionId, selectedItemId }) => (
|
||||
<div id="docs-container" className="row">
|
||||
<div className="nav col-sm-3 col-md-3 hidden-xs">
|
||||
<div className="nav col-lg-3 col-md-3 d-none d-md-block">
|
||||
<Nav
|
||||
sections={sections}
|
||||
selectedSection={selectedItem.section}
|
||||
@ -23,7 +48,7 @@ const Container = ({ sections, selectedItem, selectedSectionId, selectedItemId }
|
||||
selectedItemId={selectedItemId}
|
||||
/>
|
||||
</div>
|
||||
<div className="content col-xs-12 col-sm-9 col-md-9 col-lg-9">
|
||||
<div className="content col-xs-12 col-sm-12 col-md-9 col-lg-9">
|
||||
<div className="nav-dropdown">
|
||||
<NavDropdown
|
||||
sections={sections}
|
||||
@ -32,6 +57,8 @@ const Container = ({ sections, selectedItem, selectedSectionId, selectedItemId }
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Search />
|
||||
|
||||
<Content
|
||||
title={selectedItem.title}
|
||||
content={selectedItem.content}
|
||||
|
@ -43,10 +43,6 @@
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 998px) {
|
||||
#docs-container .nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#docs-container .content {
|
||||
border-left: none;
|
||||
margin: 15px 0;
|
||||
@ -57,3 +53,12 @@
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
@media only screen and (min-width: 998px) {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 0;
|
||||
width: 400px;
|
||||
}
|
||||
}
|
@ -44,7 +44,7 @@
|
||||
#docs-content .markdown h3 {
|
||||
font-size: 18px;
|
||||
margin: 30px 0 10px 0;
|
||||
font-weight: 800;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#docs-content .markdown a,
|
||||
|
@ -58,13 +58,21 @@ class Nav extends React.Component {
|
||||
) : (
|
||||
<div>
|
||||
<div>
|
||||
<select value={selectedSectionId} onChange={event => this.handleHeadingChange(event)}>
|
||||
<select
|
||||
className="custom-select custom-select-sm"
|
||||
value={selectedSectionId}
|
||||
onChange={event => this.handleHeadingChange(event)}
|
||||
>
|
||||
{sections.map(section => this.renderHeadingOpts(section))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<select value={selectedItemId} onChange={event => this.handleNavChange(event)}>
|
||||
<select
|
||||
className="custom-select custom-select-sm"
|
||||
value={selectedItemId}
|
||||
onChange={event => this.handleNavChange(event)}
|
||||
>
|
||||
{navs.map(nav => this.renderNavOpts(nav))}
|
||||
</select>
|
||||
</div>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user