Merge branch 'next' into feature/knobs-performance-debouncing

This commit is contained in:
Alex Wilson 2019-03-11 12:02:41 -04:00 committed by GitHub
commit 636a02dc91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
328 changed files with 10116 additions and 11575 deletions

View File

@ -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

View File

@ -18,3 +18,8 @@ lib/cli/test
!.eslintrc-markdown.js
!.jest.config.js
!.storybook
REACT_NATIVE
examples-native
react-native
ondevice-*

View File

@ -39,6 +39,7 @@ object OpenSourceProjects_Storybook_Build_2 : BuildType({
}
retryBuild {
delaySeconds = 60
enabled = false
}
finishBuildTrigger {
enabled = false

View File

@ -43,7 +43,9 @@ object OpenSourceProjects_Storybook_CliTestLatestCra : BuildType({
+:next
""".trimIndent()
}
retryBuild {}
retryBuild {
enabled = false
}
}
features {

View File

@ -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

View File

@ -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

View File

@ -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) | [![React](https://img.shields.io/npm/dm/@storybook/react.svg)](app/react) |
| [React](app/react) | [v5.0.0](https://storybooks-official.netlify.com) | [![React](https://img.shields.io/npm/dm/@storybook/react.svg)](app/react) |
| [React Native](app/react-native) | - | [![React Native](https://img.shields.io/npm/dm/@storybook/react-native.svg)](app/react-native) |
| [Vue](app/vue) | [v4.0.0](https://storybooks-vue.netlify.com/) | [![Vue](https://img.shields.io/npm/dm/@storybook/vue.svg)](app/vue) |
| [Angular](app/angular) | [v4.0.0](https://storybooks-angular.netlify.com/) | [![Angular](https://img.shields.io/npm/dm/@storybook/angular.svg)](app/angular) |
| [Polymer](app/polymer) | [v4.0.0](https://storybooks-polymer.netlify.com/) | [![Polymer](https://img.shields.io/npm/dm/@storybook/polymer.svg)](app/polymer) |
| [Mithril](app/mithril) | [v4.0.0](https://storybooks-mithril.netlify.com/) | [![Mithril](https://img.shields.io/npm/dm/@storybook/mithril.svg)](app/mithril) |
| [Marko](app/marko) | [v4.0.0](https://storybooks-marko.netlify.com/) | [![Marko](https://img.shields.io/npm/dm/@storybook/marko.svg)](app/marko) |
| [HTML](app/html) | [v4.0.0](https://storybooks-html.netlify.com/) | [![HTML](https://img.shields.io/npm/dm/@storybook/html.svg)](app/html) |
| [Svelte](app/svelte) | [v4.0.0](https://storybooks-svelte.netlify.com/) | [![Svelte](https://img.shields.io/npm/dm/@storybook/svelte.svg)](app/svelte) |
| [Riot](app/riot) | [v4.0.0](https://storybooks-riot.netlify.com/) | [![Riot](https://img.shields.io/npm/dm/@storybook/riot.svg)](app/riot) |
| [Ember](app/ember) | [v4.0.0](https://storybooks-ember.netlify.com/) | [![Ember](https://img.shields.io/npm/dm/@storybook/ember.svg)](app/ember) |
| [Preact](app/preact) | [v4.0.0](https://storybooks-preact.netlify.com/) | [![Preact](https://img.shields.io/npm/dm/@storybook/preact.svg)](app/preact) |
| [Vue](app/vue) | [v5.0.0](https://storybooks-vue.netlify.com/) | [![Vue](https://img.shields.io/npm/dm/@storybook/vue.svg)](app/vue) |
| [Angular](app/angular) | [v5.0.0](https://storybooks-angular.netlify.com/) | [![Angular](https://img.shields.io/npm/dm/@storybook/angular.svg)](app/angular) |
| [Polymer](app/polymer) | [v5.0.0](https://storybooks-polymer.netlify.com/) | [![Polymer](https://img.shields.io/npm/dm/@storybook/polymer.svg)](app/polymer) |
| [Mithril](app/mithril) | [v5.0.0](https://storybooks-mithril.netlify.com/) | [![Mithril](https://img.shields.io/npm/dm/@storybook/mithril.svg)](app/mithril) |
| [Marko](app/marko) | [v5.0.0](https://storybooks-marko.netlify.com/) | [![Marko](https://img.shields.io/npm/dm/@storybook/marko.svg)](app/marko) |
| [HTML](app/html) | [v5.0.0](https://storybooks-html.netlify.com/) | [![HTML](https://img.shields.io/npm/dm/@storybook/html.svg)](app/html) |
| [Svelte](app/svelte) | [v5.0.0](https://storybooks-svelte.netlify.com/) | [![Svelte](https://img.shields.io/npm/dm/@storybook/svelte.svg)](app/svelte) |
| [Riot](app/riot) | [v5.0.0](https://storybooks-riot.netlify.com/) | [![Riot](https://img.shields.io/npm/dm/@storybook/riot.svg)](app/riot) |
| [Ember](app/ember) | [v5.0.0](https://storybooks-ember.netlify.com/) | [![Ember](https://img.shields.io/npm/dm/@storybook/ember.svg)](app/ember) |
| [Preact](app/preact) | [v5.0.0](https://storybooks-preact.netlify.com/) | [![Preact](https://img.shields.io/npm/dm/@storybook/preact.svg)](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.
![Storybook](https://github.com/storybooks/brand/blob/master/badge/badge-storybook.svg)
![Storybook](https://cdn.jsdelivr.net/gh/storybooks/brand@master/badge/badge-storybook.svg)
```md
[![Storybook](https://github.com/storybooks/brand/blob/master/badge/badge-storybook.svg)](link to site)
[![Storybook](https://cdn.jsdelivr.net/gh/storybooks/brand@master/badge/badge-storybook.svg)](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 [![Good First Issue](https://img.shields.io/github/issues/storybooks/storybook/good%20first%20issue.svg)](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.

View File

@ -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

View File

@ -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"
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View 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>
);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View 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>
);

View File

@ -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;

View File

@ -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 };

View File

@ -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
View 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
},
});
`
);

View File

@ -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
View 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
View File

@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"types": ["webpack-env"]
},
"include": [
"src/**/*"
],
"exclude": [
"src/__tests__/**/*"
]
}

View File

@ -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": {

View File

@ -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>
))}

View File

@ -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',

View File

@ -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);

View File

@ -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;

View File

@ -1 +0,0 @@
module.exports = require('./dist/deprecated');

View File

@ -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": {

View File

@ -10,5 +10,5 @@ export const ColorIcon = styled.span(
}),
({ theme }) => ({
boxShadow: `${theme.appBorderColor} 0 0 0 1px inset`,
}),
})
);

View File

@ -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`,
};

View File

@ -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>

View File

@ -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`"
);

View File

@ -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) {

View File

@ -1 +0,0 @@
module.exports = require('./dist/deprecated');

View File

@ -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"
},

View File

@ -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": "*"

View File

@ -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"

View File

@ -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"

View File

@ -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": "*"

View File

@ -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": "*"

View File

@ -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"
},

View File

@ -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": "*"

View File

@ -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>
);

View File

@ -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';

View File

@ -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": "*"

View File

@ -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"
},

View 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');
});
});
});

View File

@ -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>
);

View File

@ -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();

View File

@ -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": "*",

View File

@ -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",

View File

@ -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": {

View File

@ -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": {

View File

@ -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"

View File

@ -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,

View File

@ -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,
}
}
>

View File

@ -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,
}
}
>

View File

@ -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,
}
}
>

View File

@ -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,
}
}
>

View File

@ -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": {

View File

@ -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,
}
}

View File

@ -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"
},

View File

@ -1,6 +1,6 @@
const defaultOptions = {
prettierConfig: {
printWidth: 120,
printWidth: 100,
tabWidth: 2,
bracketSpacing: true,
trailingComma: 'es5',

View File

@ -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 />);
```

View File

@ -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": {

View File

@ -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;

View File

@ -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 || {}),
},

View File

@ -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`,

View File

@ -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');

View File

@ -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`
);

View File

@ -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"

View File

@ -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 || [])],

View File

@ -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');

View File

@ -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 {

View File

@ -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"
},

View File

@ -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"

View File

@ -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": {

View File

@ -8,6 +8,9 @@ export function webpack(config) {
{
test: /\.marko$/,
loader: require.resolve('marko-loader'),
options: {
compiler: require.resolve('marko/compiler'),
},
},
],
},

View File

@ -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"
},

View File

@ -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",

View File

@ -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);

View File

@ -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"

View File

@ -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"

View File

@ -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",

View File

@ -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',
}}
/>
);

View File

@ -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"
},

View File

@ -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",

View File

@ -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"

View File

@ -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/',
],

View File

@ -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 }) {

View File

@ -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"
}
}

View File

@ -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}

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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