diff --git a/.babelrc.js b/.babelrc.js index cb85c9eb2b75..7e6d99f229fc 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -48,13 +48,6 @@ module.exports = { test: withTests, }, }, - { - test: './examples/rax-kitchen-sink', - presets: [ - ['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage', corejs: '3' }], - ['babel-preset-rax', { development: process.env.BABEL_ENV === 'development' }], - ], - }, { test: './lib', presets: [ @@ -75,11 +68,6 @@ module.exports = { test: withTests, }, }, - { - test: './app/react-native', - presets: ['module:metro-react-native-babel-preset'], - plugins: ['babel-plugin-macros', ['emotion', { sourceMap: true, autoLabel: true }]], - }, { test: [ './lib/node-logger', diff --git a/.circleci/config.yml b/.circleci/config.yml index 211098ee8415..4b79060d74be 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -79,9 +79,6 @@ jobs: - run: name: Run chromatic on the pre-built mithril-kitchen-sink example command: yarn chromatic --storybook-build-dir="built-storybooks/mithril-kitchen-sink" --app-code="8adgm46jzk8" - - run: - name: Run chromatic on the pre-built polymer-cli example - command: yarn chromatic --storybook-build-dir="built-storybooks/polymer-cli" --app-code="o6jl9kmh0qd" - run: name: Run chromatic on the pre-built preact-kitchen-sink example command: yarn chromatic --storybook-build-dir="built-storybooks/preact-kitchen-sink" --app-code="ls0ikhnwqt" @@ -194,11 +191,6 @@ jobs: command: | cd examples/ember-cli yarn storybook --smoke-test --quiet - - run: - name: Run polymer-cli (smoke test) - command: | - cd examples/polymer-cli - yarn storybook --smoke-test --quiet - run: name: Run marko-cli (smoke test) command: | @@ -229,24 +221,6 @@ jobs: command: | cd examples/cra-react15 yarn storybook --smoke-test --quiet - native-smoke-tests: - <<: *defaults - steps: - - checkout - - attach_workspace: - at: . - - run: - name: Bootstrap - command: yarn bootstrap --core - - run: - name: Run React-Native-App example - command: | - cd examples-native/crna-kitchen-sink - yarn storybook --smoke-test - - run: - name: Publish React-Native-App example - command: | - ./scripts/crna-publish.js frontpage: <<: *defaults steps: @@ -334,9 +308,6 @@ workflows: - packtracker: requires: - build - - native-smoke-tests: - requires: - - build - test: requires: - build diff --git a/.eslintignore b/.eslintignore index ad542e107759..69e43252ce45 100644 --- a/.eslintignore +++ b/.eslintignore @@ -18,7 +18,8 @@ examples/cra-ts-kitchen-sink/*.json examples/cra-ts-kitchen-sink/public/* examples/cra-ts-essentials/*.json examples/cra-ts-essentials/public/* - +examples/rax-kitchen-sink/src/document/* +.yarn !.remarkrc.js !.babelrc.js !.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index 3c53e6faad79..98dff193b3c1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,7 @@ module.exports = { 'react/jsx-fragments': 'off', '@typescript-eslint/ban-ts-ignore': 'off', '@typescript-eslint/no-object-literal-type-assertion': 'off', + '@typescript-eslint/no-empty-function': 'off', 'react/sort-comp': [ 'error', { diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000000..5ea62bf2933c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.yarn/releases/yarn-*.js linguist-generated=true diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c23f1075713c..70a20b7fbe5e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -18,9 +18,7 @@ /addons/viewport/ @saponifi3d /app/angular/ @alterx @igor-dv -/app/polymer/ @ndelangen @naipath @leonrodenburg /app/react/ @xavcz @shilman @thomasbertet -/app/react-native/ @rmevans9 @Gongreg @tmeasday /app/vue/ @thomasbertet @kazupon /app/svelte/ @plumpNation @@ -30,7 +28,6 @@ /examples/cra-kitchen-sink/ @ndelangen @UsulPro /examples/cra-ts-kitchen-sink/ @mucsi96 /examples/official-storybook/ @UsulPro -/examples/polymer-cli/ @naipath @igor-dv /examples/vue-kitchen-sink/ @igor-dv @alexandrebodin /examples/svelte-kitchen-sink/ @plumpNation diff --git a/.github/autolabeler.yml b/.github/autolabeler.yml index 4a4e5cf97216..a418cc267f82 100644 --- a/.github/autolabeler.yml +++ b/.github/autolabeler.yml @@ -13,9 +13,8 @@ 'addon: storyshots': ["addons/storyshots/**"] 'addon: viewport': ["addons/viewport/**"] 'app: angular': ["app/angular/**"] -'app: polymer ': ["app/polymer/**"] 'app: preact': ["app/preact/**"] -'app: react-native': ["app/react-native/**"] +'app: rax': ["app/rax/**"] 'app: react': ["app/react/**"] 'app: vue': ["app/vue/**"] 'app: svelte': ["app/svelte/**"] diff --git a/.github/automention.yml b/.github/automention.yml index 4e3688c40d4e..fd0147cbc3aa 100644 --- a/.github/automention.yml +++ b/.github/automention.yml @@ -2,10 +2,8 @@ 'app: ember': ['gabrielcsapo'] 'app: html': ['Hypnosphi'] 'app: marko': ['nm123github'] -'app: polymer': ['stijnkoopal', 'ndelangen'] 'app: preact': ['BartWaardenburg'] -'app: react-native': ['benoitdion', 'gongreg'] -'app: react-native-server': ['benoitdion', 'gongreg'] +'app: rax': ['SoloJiang'] 'app: svelte': ['rixo', 'cam-stitt', 'plumpNation'] 'app: vue': ['backbone87', 'elevatebart', 'pksunkara', 'Aaron-Pool', 'pocka'] 'app: web-components': ['daKmoR'] diff --git a/.gitignore b/.gitignore index ffe460ac8a41..1594748ce78d 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ storybook-out built-storybooks cypress/videos cypress/screenshots +examples/ember-cli/ember-output diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000000..61c3bc75a05e --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +.yarn diff --git a/.vscode/launch.json b/.vscode/launch.json index 50ef06713aca..daa7997bc064 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -17,6 +17,22 @@ "skipFiles": [ "/**" ] - }, + }, { + "type": "node", + "request": "launch", + "name": "cli html", + "cwd": "${workspaceFolder}/lib/cli/stories", + "runtimeArgs": [ + "--inspect-brk", + "${workspaceFolder}/lib/cli/bin/index.js", + "init", + "--type", + "html" + ], + "port": 9229, + "skipFiles": [ + "/**" + ] + } ] } \ No newline at end of file diff --git a/ADDONS_SUPPORT.md b/ADDONS_SUPPORT.md index a87bcfb68bc5..540732862587 100644 --- a/ADDONS_SUPPORT.md +++ b/ADDONS_SUPPORT.md @@ -1,25 +1,25 @@ ## Addon / Framework Support Table -| | [React](app/react)|[React Native](app/react-native)|[Vue](app/vue)|[Angular](app/angular)| [Polymer](app/polymer)| [Mithril](app/mithril)| [HTML](app/html)| [Marko](app/marko)| [Svelte](app/svelte)| [Riot](app/riot)| [Ember](app/ember)| [Preact](app/preact)| -| ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:| -|[a11y](addons/a11y) |+| |+|+|+|+|+|+|+|+|+|+| -|[actions](addons/actions) |+|+*|+|+|+|+|+|+|+|+|+|+| -|[backgrounds](addons/backgrounds) |+|*|+|+|+|+|+|+|+|+|+|+| -|[centered](addons/centered) |+| |+|+| |+|+| |+| |+|+| -|[contexts](addons/contexts) |+| |+| | | | | | | | |+| -|[events](addons/events) |+| |+|+|+|+|+|+| | |+|+| -|[design assets](addons/design-assets) |+| |+|+|+|+|+|+|+|+|+|+| -|[graphql](addons/graphql) |+| | | | | | | | | | | | -|[google-analytics](addons/google-analytics) |+|+|+|+|+|+|+|+|+|+|+|+| -|[info](addons/info) |+| | | | | | | | | | | | -|[jest](addons/jest) |+|+|+|+|+|+|+|+|+|+|+|+| -|[knobs](addons/knobs) |+|+*|+|+|+|+|+|+|+|+|+|+| -|[links](addons/links) |+|+|+|+|+|+|+| |+|+|+|+| -|[notes](addons/notes) |+|+*|+|+|+|+|+| |+|+|+|+| -|[options](addons/options) |+|+|+|+|+|+|+| |+|+|+|+| -|[cssresources](addons/cssresources) |+| |+|+|+|+|+|+|+|+|+|+| -|[storyshots](addons/storyshots) |+|+|+|+| | |+| |+|+| |+| -|[storysource](addons/storysource) |+| |+|+|+|+|+|+|+|+|+|+| -|[viewport](addons/viewport) |+| |+|+|+|+|+|+|+|+|+|+| +| | [React](app/react) | [React Native](app/react-native) | [Vue](app/vue) | [Angular](app/angular) | [Mithril](app/mithril) | [HTML](app/html) | [Marko](app/marko) | [Svelte](app/svelte) | [Riot](app/riot) | [Ember](app/ember) | [Preact](app/preact) | [Rax](app/rax) | +| ------------------------------------------- | :----------------: | :------------------------------: | :------------: | :--------------------: | :--------------------: | :--------------: | :----------------: | :------------------: | :--------------: | :----------------: | :------------------: | -------------- | +| [a11y](addons/a11y) | + | | + | + | + | + | + | + | + | + | + | + | +| [actions](addons/actions) | + | +\* | + | + | + | + | + | + | + | + | + | + | +| [backgrounds](addons/backgrounds) | + | \* | + | + | + | + | + | + | + | + | + | + | +| [centered](addons/centered) | + | | + | + | + | + | | + | | + | + | + | +| [contexts](addons/contexts) | + | | + | | | | | | | | + | + | +| [events](addons/events) | + | | + | + | + | + | + | | | + | + | + | +| [design assets](addons/design-assets) | + | | + | + | + | + | + | + | + | + | + | + | +| [graphql](addons/graphql) | + | | | | | | | | | | | | +| [google-analytics](addons/google-analytics) | + | + | + | + | + | + | + | + | + | + | + | + | +| [info](addons/info) | + | | | | | | | | | | | | +| [jest](addons/jest) | + | + | + | + | + | + | + | + | + | + | + | + | +| [knobs](addons/knobs) | + | +\* | + | + | + | + | + | + | + | + | + | + | +| [links](addons/links) | + | + | + | + | + | + | | + | + | + | + | + | +| [notes](addons/notes) | + | +\* | + | + | + | + | | + | + | + | + | + | +| [options](addons/options) | + | + | + | + | + | + | | + | + | + | + | + | +| [cssresources](addons/cssresources) | + | | + | + | + | + | + | + | + | + | + | + | +| [storyshots](addons/storyshots) | + | + | + | + | | + | | + | + | | + | + | +| [storysource](addons/storysource) | + | | + | + | + | + | + | + | + | + | + | + | +| [viewport](addons/viewport) | + | | + | + | + | + | + | + | + | + | + | + | -`*` - React Native on device addon (addons/onDevice-\) +`*` - React Native on device addon (addons/onDevice-\) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8166df41aa4e..f2a225f1d9d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,194 @@ +## 6.0.0-alpha.2 (January 30, 2020) + +### Features + +* UI: Configure tabs title, visibility, order and disable ([#9095](https://github.com/storybookjs/storybook/pull/9095)) +* Addon-cssresources: Add hideCode option ([#9627](https://github.com/storybookjs/storybook/pull/9627)) +* UI: Add `viewMode` parameter to control story nav UI ([#9090](https://github.com/storybookjs/storybook/pull/9090)) + +### Bug Fixes + +* Web-components: Fix default value for prop table docs ([#9655](https://github.com/storybookjs/storybook/pull/9655)) +* Web-components: Make TypeScript types play nicely with lit-element ([#9557](https://github.com/storybookjs/storybook/pull/9557)) +* UI: Fix tabs to scroll horizontally ([#9383](https://github.com/storybookjs/storybook/pull/9383)) +* UI: Add support for className prop on Form.Field ([#9665](https://github.com/storybookjs/storybook/pull/9665)) +* Core: Upgrade `min-css-extract-plugin` to fix SASS loading ([#9652](https://github.com/storybookjs/storybook/pull/9652)) +* Adon-docs: Fix ColorPalette styling ([#9643](https://github.com/storybookjs/storybook/pull/9643)) +* Addon-storyshots: Remove excess slashes from jest transform warning ([#9616](https://github.com/storybookjs/storybook/pull/9616)) + +### Maintenance + +* Source-loader: Overhaul to remove decorators, support user-configurable source ([#9547](https://github.com/storybookjs/storybook/pull/9547)) +* Build: Use Netlify for examples again ([#9585](https://github.com/storybookjs/storybook/pull/9585)) +* Ember: Migrate to new "import { hbs } from 'ember-cli-htmlbars'" ([#9633](https://github.com/storybookjs/storybook/pull/9633)) +* Publish: Remove docs to reduce package size ([#9612](https://github.com/storybookjs/storybook/pull/9612)) + +## 5.3.9 (January 24, 2020) + +### Bug Fixes + +* Addon-docs: Revert breaking source indentation fix ([#9609](https://github.com/storybookjs/storybook/pull/9609)) + +## 6.0.0-alpha.1 (January 23, 2020) + +### Features + +* Core: Enable HMR logging in browser console ([#9535](https://github.com/storybookjs/storybook/pull/9535)) + +### Bug Fixes + +* Addon-knobs: Fix broken link to repo in empty panel ([#9530](https://github.com/storybookjs/storybook/pull/9530)) +* Typescript: Export IStory in `@storybook/angular` ([#9097](https://github.com/storybookjs/storybook/pull/9097)) + +### Maintenance + +* React-native: Extract to its own repo ([#9599](https://github.com/storybookjs/storybook/pull/9599)) +* Polymer: Extract to its own repo ([#9596](https://github.com/storybookjs/storybook/pull/9596)) +* Build: Fix some dependencies & ts problems ([#9603](https://github.com/storybookjs/storybook/pull/9603)) + +## 5.3.8 (January 22, 2020) + +### Bug Fixes + +* Addon-docs: Fix TS false default value in prop table ([#9560](https://github.com/storybookjs/storybook/pull/9560)) +* Addon-knobs: Fix broken repo link in empty panel ([#9530](https://github.com/storybookjs/storybook/pull/9530)) +* Typescript: Export IStory in `@storybook/angular` ([#9097](https://github.com/storybookjs/storybook/pull/9097)) +* Fixed Angular button example story ([#9540](https://github.com/storybookjs/storybook/pull/9540)) +* Clean usage of `@types/webpack-env` dep in all packages ([#9536](https://github.com/storybookjs/storybook/pull/9536)) + +## 6.0.0-alpha.0 (January 21, 2020) + +### Features + +* API: Add useSharedState, useStoryState ([#9566](https://github.com/storybookjs/storybook/pull/9566)) +* Addon-docs: Named colors with ColorPalette ([#9453](https://github.com/storybookjs/storybook/pull/9453)) +* Core: Add preview layouts ([#9229](https://github.com/storybookjs/storybook/pull/9229)) +* Marionette: Add marionette support ([#7981](https://github.com/storybookjs/storybook/pull/7981)) +* Addon-a11y: Support manual run ([#8883](https://github.com/storybookjs/storybook/pull/8883)) +* Addon-cssresources: Disable SyntaxHighlighter for long code ([#9360](https://github.com/storybookjs/storybook/pull/9360)) +* Core: Improve monorepo support ([#8822](https://github.com/storybookjs/storybook/pull/8822)) + +### Bug Fixes + +* Addon-docs: Fix TS false default value in prop table ([#9560](https://github.com/storybookjs/storybook/pull/9560)) +* Addon-docs: Remove hard-coded lineHeight in Typeset block ([#9567](https://github.com/storybookjs/storybook/pull/9567)) +* Fixed Angular button example story ([#9540](https://github.com/storybookjs/storybook/pull/9540)) +* Core: Fix generated entry to import at top of file ([#9398](https://github.com/storybookjs/storybook/pull/9398)) +* Preact: Fix story function typescript type ([#9123](https://github.com/storybookjs/storybook/pull/9123)) +* UI: Make canvas link a link ([#9257](https://github.com/storybookjs/storybook/pull/9257)) + +### Maintenance + +* Build: the build-storybooks script ([#9569](https://github.com/storybookjs/storybook/pull/9569)) +* CLI: Improve Rax template ([#9574](https://github.com/storybookjs/storybook/pull/9574)) +* Typescript: Migrate polymer ([#9565](https://github.com/storybookjs/storybook/pull/9565)) +* Typescript: Migrate ember ([#9020](https://github.com/storybookjs/storybook/pull/9020)) +* Next 6.0.0 ([#9212](https://github.com/storybookjs/storybook/pull/9212)) +* REMOVE subscription_store ([#9228](https://github.com/storybookjs/storybook/pull/9228)) + +### Dependency Upgrades + +* Update husky to v4 ([#9509](https://github.com/storybookjs/storybook/pull/9509)) +* Bumped react-dev-utils dependency to v10. ([#9579](https://github.com/storybookjs/storybook/pull/9579)) +* Bump babel-plugin-macros from 2.7.1 to 2.8.0 ([#9236](https://github.com/storybookjs/storybook/pull/9236)) +* Bump babel-plugin-emotion from 10.0.23 to 10.0.27 ([#9239](https://github.com/storybookjs/storybook/pull/9239)) +* Bump @babel/runtime from 7.7.4 to 7.7.7 ([#9277](https://github.com/storybookjs/storybook/pull/9277)) +* Bump corejs-upgrade-webpack-plugin from 2.2.0 to 3.0.1 ([#9427](https://github.com/storybookjs/storybook/pull/9427)) +* Bump terser-webpack-plugin from 2.2.1 to 2.3.2 ([#9386](https://github.com/storybookjs/storybook/pull/9386)) + +## 5.3.7 (January 20, 2020) + +### Bug Fixes + +* Node-logger: Move `@types/npmlog` to dependencies ([#9538](https://github.com/storybookjs/storybook/pull/9538)) +* Core: Fix legacy story URLs ([#9545](https://github.com/storybookjs/storybook/pull/9545)) +* Addon-docs: Convert default prop value to string ([#9525](https://github.com/storybookjs/storybook/pull/9525)) +* Addon-docs: Preserve Source indentation by default ([#9513](https://github.com/storybookjs/storybook/pull/9513)) + +## 5.3.6 (January 17, 2020) + +### Bug Fixes + +* Source-loader: Bypass if file has no exports ([#9505](https://github.com/storybookjs/storybook/pull/9505)) +* Core: Fix default sorting of docs-only stories ([#9504](https://github.com/storybookjs/storybook/pull/9504)) + +## 5.3.5 (January 17, 2020) + +### Bug Fixes + +* Core: Fix typo for loading addon-notes/register-panel ([#9497](https://github.com/storybookjs/storybook/pull/9497)) +* Source-loader: Add imports to top of file ([#9492](https://github.com/storybookjs/storybook/pull/9492)) + +## 5.3.4 (January 16, 2020) + +### Bug Fixes + +* Core: Fix presets register panel ([#9486](https://github.com/storybookjs/storybook/pull/9486)) +* Core: Fix addon/preset detection for local addons ([#9485](https://github.com/storybookjs/storybook/pull/9485)) +* Core: Fix default story sort ([#9482](https://github.com/storybookjs/storybook/pull/9482)) + +## 5.3.3 (January 14, 2020) + +### Bug Fixes + +* UI: Fix edge case where only one legacy separator is defined ([#9425](https://github.com/storybookjs/storybook/pull/9425)) +* Core: Preserve kind load order on HMR when no sortFn is provided ([#9424](https://github.com/storybookjs/storybook/pull/9424)) +* Angular: Fix missing architect properties ([#9390](https://github.com/storybookjs/storybook/pull/9390)) +* Addon-knobs: Fix null knob values in select ([#9416](https://github.com/storybookjs/storybook/pull/9416)) +* Source-loader: Disable linting altogether ([#9417](https://github.com/storybookjs/storybook/pull/9417)) + +## 5.3.2 (January 13, 2020) + +### Bug Fixes + +* Source-loader: Disable eslint entirely for generated code ([#9410](https://github.com/storybookjs/storybook/pull/9410)) + +## 5.3.1 (January 12, 2020) + +### Bug Fixes + +* Core: Fix generated entry to import at top of file ([#9398](https://github.com/storybookjs/storybook/pull/9398)) + +## 5.3.0 (January 11, 2020) + +Storybook 5.3 is here! + +- 📝 [Custom documentation in MDX](https://medium.com/storybookjs/rich-docs-with-storybook-mdx-61bc145ae7bc) +- 🎨 [Multi-framework SB Docs (React, Vue, Angular, WC, Ember)](https://medium.com/storybookjs/storybook-docs-for-new-frameworks-b1f6090ee0ea) +- 📦 [Web-components framework support](https://dev.to/open-wc/storybook-for-web-components-on-steroids-4h29) +- 🔼 [Main.js declarative configuration](https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78) + +5.3 contains hundreds more fixes, features, and tweaks. Browse the changelogs matching `5.3.0-alpha.*`, `5.3.0-beta.*`, and `5.3.0-rc.*` for the full list of changes. See [MIGRATION.md](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md) to upgrade from `5.0` or earlier. + +## 5.3.0-rc.14 (January 11, 2020) + +* Merge `master` into `next` for 5.3.0 release ([#9388](https://github.com/storybookjs/storybook/pull/9388)) + +## 5.3.0-rc.13 (January 11, 2020) + +### Bug Fixes + +* Addon-docs: Fix link CORS errors using channel navigate event ([#9381](https://github.com/storybookjs/storybook/pull/9381)) +* CLI: Fix `sb init` to use spawn.sync if creating package.json ([#9359](https://github.com/storybookjs/storybook/pull/9359)) + +### Maintenance + +* Official-storybook: Prop table example for multiple named exports ([#9364](https://github.com/storybookjs/storybook/pull/9364)) +* Addon-docs / web-components: Rename 'props' to 'properties' in props table ([#9362](https://github.com/storybookjs/storybook/pull/9362)) + +### Dependency Upgrades + +* Upgrade @types/webpack-env and @types/node to fix conflicting types ([#9365](https://github.com/storybookjs/storybook/pull/9365)) + +## 5.3.0-rc.12 (January 8, 2020) + +### Bug Fixes + +* Nav UI: Nodes are components only if they contain ALL leaf nodes ([#9356](https://github.com/storybookjs/storybook/pull/9356)) +* Core: Fix HMR for global decorators in main.js config ([#9354](https://github.com/storybookjs/storybook/pull/9354)) +* Presets: Fix register.js addons entry ([#9347](https://github.com/storybookjs/storybook/pull/9347)) +* React: Check CRA is installed before showing warning ([#9346](https://github.com/storybookjs/storybook/pull/9346)) + ## 5.3.0-rc.11 (January 7, 2020) ### Bug Fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 22a1561cd0a4..9788a94964bf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ Thanks for your interest in improving Storybook! We are a community-driven proje Please review this document to help to streamline the process and save everyone's precious time. -This repo uses yarn workspaces, so you should install `yarn@1.3.2` or higher as a package manager. See [installation guide](https://yarnpkg.com/en/docs/install). +This repo uses yarn workspaces, so you should install `yarn` as the package manager. See [installation guide](https://yarnpkg.com/en/docs/install). ## Issues @@ -283,9 +283,10 @@ Within the `examples` folder of the Storybook repo, you will find kitchen sink e Not only do these show many of the options and add-ons available, they are also automatically linked to all the development packages. We highly encourage you to use these to develop/test contributions on. #### React and Vue + 1. `cd examples/official-storybook` -2. `yarn storybook` -3. Verify that your local version works +2. `yarn storybook` +3. Verify that your local version works ### Working with your own app diff --git a/MIGRATION.md b/MIGRATION.md index 459846d28979..6b573ada5970 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -2,13 +2,14 @@ - [Migration](#migration) - [From version 5.2.x to 5.3.x](#from-version-52x-to-53x) - - [To main.js configuration](#to-main-js-configuration) + - [To main.js configuration](#to-mainjs-configuration) - [Create React App preset](#create-react-app-preset) - [Description doc block](#description-doc-block) - [React Native Async Storage](#react-native-async-storage) - [Deprecate displayName parameter](#deprecate-displayname-parameter) - [Unified docs preset](#unified-docs-preset) - [Simplified hierarchy separators](#simplified-hierarchy-separators) + - [Addon StoryShots Puppeteer uses external puppeteer](#addon-storyshots-puppeteer-uses-external-puppeteer) - [From version 5.1.x to 5.2.x](#from-version-51x-to-52x) - [Source-loader](#source-loader) - [Default viewports](#default-viewports) @@ -83,9 +84,9 @@ In storybook 5.3 3 new files for configuration were introduced, that replaced so These files are now soft-deprecated, (_they still work, but over time we will promote users to migrate_): -- `config.js` has been renamed to `preview.js`. -- `addons.js` has been renamed to `manager.js`. -- `presets.js` has been renamed to `main.js`. +- `presets.js` has been renamed to `main.js`. `main.js` is the main point of configuration for storybook. +- `config.js` has been renamed to `preview.js`. `preview.js` configures the "preview" iframe that renders your components. +- `addons.js` has been renamed to `manager.js`. `manager.js` configures Storybook's "manager" UI that wraps the preview, and also configures addons panel. #### Using main.js @@ -143,7 +144,6 @@ const theme = create({ }); addons.setConfig({ - showRoots: true, panelPosition: 'bottom', theme, }); @@ -152,6 +152,8 @@ addons.setConfig({ This makes storybook load and use the theme in the manager directly. This allows for richer theming in the future, and has a much better performance! +> If you're using addon-docs, you should probably not do this. Docs uses the theme as well, but this change makes the theme inaccessible to addon-docs. We'll address this in 6.0.0. + ### Create React App preset You can now move to the new preset for [Create React App](https://create-react-app.dev/). The in-built preset for Create React App will be disabled in Storybook 6.0. @@ -187,6 +189,8 @@ getStorybookUI({ }); ``` +The benefit of using Async Storage is so that when users refresh the app, Storybook can open their last visited story. + ### Deprecate displayName parameter In 5.2, the story parameter `displayName` was introduced as a publicly visible (but internal) API. Storybook's Component Story Format (CSF) loader used it to modify a story's display name independent of the story's `name`/`id` (which were coupled). @@ -210,11 +214,26 @@ yarn sb migrate upgrade-hierarchy-separators --glob="*.stories.js" If you were using `|` and wish to keep the "root" behavior, use the `showRoots: true` option to re-enable roots: ```js -addParameters({ options: { showRoots: true } }); +addParameters({ + options: { + showRoots: true, + }, +}); ``` NOTE: it is no longer possible to have some stories with roots and others without. If you want to keep the old behavior, simply add a root called "Others" to all your previously unrooted stories. +### Addon StoryShots Puppeteer uses external puppeteer + +To give you more control on the Chrome version used when running StoryShots Puppeteer, `puppeteer` is no more included in the addon dependencies. So you can now pick the version of `puppeteer` you want and set it in your project. + +If you want the latest version available just run: +```sh +yarn add puppeteer --dev +OR +npm install puppeteer --save-dev +``` + ## From version 5.1.x to 5.2.x ### Source-loader diff --git a/README.md b/README.md index 036c350cd464..6e431acf9e3c 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ For additional help, join us [in our Discord](https://discord.gg/sMFvFsG) or [Sl | [React Native](app/react-native) | - | [![React Native](https://img.shields.io/npm/dm/@storybook/react-native.svg)](app/react-native) | | [Vue](app/vue) | [v5.1.0](https://storybooks-vue.netlify.com/) | [![Vue](https://img.shields.io/npm/dm/@storybook/vue.svg)](app/vue) | | [Angular](app/angular) | [v5.1.0](https://storybooks-angular.netlify.com/) | [![Angular](https://img.shields.io/npm/dm/@storybook/angular.svg)](app/angular) | -| [Polymer](app/polymer) | [v5.1.0](https://storybooks-polymer.netlify.com/) | [![Polymer](https://img.shields.io/npm/dm/@storybook/polymer.svg)](app/polymer) | +| [Marionette.js](app/marionette) | - | [![Marionette.js](https://img.shields.io/npm/dm/@storybook/marionette.svg)](app/marionette) | | [Mithril](app/mithril) | [v5.1.0](https://storybooks-mithril.netlify.com/) | [![Mithril](https://img.shields.io/npm/dm/@storybook/mithril.svg)](app/mithril) | | [Marko](app/marko) | [v5.1.0](https://storybooks-marko.netlify.com/) | [![Marko](https://img.shields.io/npm/dm/@storybook/marko.svg)](app/marko) | | [HTML](app/html) | [v5.1.0](https://storybooks-html.netlify.com/) | [![HTML](https://img.shields.io/npm/dm/@storybook/html.svg)](app/html) | @@ -123,6 +123,7 @@ For additional help, join us [in our Discord](https://discord.gg/sMFvFsG) or [Sl | [Riot](app/riot) | [v5.1.0](https://storybooks-riot.netlify.com/) | [![Riot](https://img.shields.io/npm/dm/@storybook/riot.svg)](app/riot) | | [Ember](app/ember) | [v5.1.0](https://storybooks-ember.netlify.com/) | [![Ember](https://img.shields.io/npm/dm/@storybook/ember.svg)](app/ember) | | [Preact](app/preact) | [v5.1.0](https://storybooks-preact.netlify.com/) | [![Preact](https://img.shields.io/npm/dm/@storybook/preact.svg)](app/preact) | +| [Rax](app/rax) | [v5.1.0](https://storybooks-rax.netlify.com/) | [![Rax](https://img.shields.io/npm/dm/@storybook/rax.svg)](app/rax) | ### Sub Projects diff --git a/ROADMAP.md b/ROADMAP.md index 6a406bc2ccd7..506d84c86d2d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -9,7 +9,6 @@ + [Add a playground addon](#add-a-playground-addon) + [See multiple (or all) stories in 1 preview.](#see-multiple--or-all--stories-in-1-preview) * [Supporting other frameworks and libraries](#supporting-other-frameworks-and-libraries) - + [Polymer & Webcomponents](#polymer---webcomponents) + [Aurelia](#aurelia) * [Breaking changes](#breaking-changes) + [Addon API](#addon-api) @@ -60,10 +59,6 @@ Unfortunately, if you choose anything not from the list of [supported frameworks We want you to be able to use storybook with the framework / library of your choice. -### Polymer & Webcomponents - -Storybook for Polymer is currently in development and will support custom elements and plain HTML. - ### Aurelia We're reaching out to the Aurelia maintainers to cooperate on this. diff --git a/addons/a11y/README.md b/addons/a11y/README.md index aa141c5c94c1..f4d086fb9f1d 100755 --- a/addons/a11y/README.md +++ b/addons/a11y/README.md @@ -69,6 +69,8 @@ export default { config: {}, // axe-core optionsParameter (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter) options: {}, + // optional flag to prevent the automatic check + manual: true, }, }, }; diff --git a/addons/a11y/package.json b/addons/a11y/package.json index 73448aa60263..9dd357621f18 100644 --- a/addons/a11y/package.json +++ b/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "a11y addon for storybook", "keywords": [ "a11y", @@ -22,7 +22,6 @@ "license": "MIT", "files": [ "dist/**/*", - "docs/**/*", "README.md", "*.js", "*.d.ts" @@ -33,12 +32,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-rc.11", - "@storybook/api": "5.3.0-rc.11", - "@storybook/client-logger": "5.3.0-rc.11", - "@storybook/components": "5.3.0-rc.11", - "@storybook/core-events": "5.3.0-rc.11", - "@storybook/theming": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", + "@storybook/api": "6.0.0-alpha.2", + "@storybook/client-logger": "6.0.0-alpha.2", + "@storybook/components": "6.0.0-alpha.2", + "@storybook/core-events": "6.0.0-alpha.2", + "@storybook/theming": "6.0.0-alpha.2", "axe-core": "^3.3.2", "core-js": "^3.0.1", "global": "^4.3.2", @@ -51,7 +50,8 @@ "util-deprecate": "^1.0.2" }, "devDependencies": { - "@types/react-redux": "^7.0.6" + "@types/react-redux": "^7.0.6", + "@types/webpack-env": "^1.15.0" }, "publishConfig": { "access": "public" diff --git a/addons/a11y/src/components/A11YPanel.test.js b/addons/a11y/src/components/A11YPanel.test.js index 2f84b31afd39..9bc88673ab01 100644 --- a/addons/a11y/src/components/A11YPanel.test.js +++ b/addons/a11y/src/components/A11YPanel.test.js @@ -1,19 +1,18 @@ import React from 'react'; import { mount } from 'enzyme'; +import { EventEmitter } from 'events'; import { ThemeProvider, themes, convert } from '@storybook/theming'; -import { STORY_RENDERED } from '@storybook/core-events'; -import { ScrollArea } from '@storybook/components'; import { A11YPanel } from './A11YPanel'; import { EVENTS } from '../constants'; function createApi() { - return { - emit: jest.fn(), - on: jest.fn(), - off: jest.fn(), - }; + const emitter = new EventEmitter(); + jest.spyOn(emitter, 'emit'); + jest.spyOn(emitter, 'on'); + jest.spyOn(emitter, 'off'); + return emitter; } const axeResult = { @@ -63,7 +62,7 @@ function ThemedA11YPanel(props) { } describe('A11YPanel', () => { - it('should register STORY_RENDERED, RESULT and ERROR updater on mount', () => { + it('should register event listener on mount', () => { // given const api = createApi(); expect(api.on).not.toHaveBeenCalled(); @@ -73,144 +72,91 @@ describe('A11YPanel', () => { // then expect(api.on.mock.calls.length).toBe(3); - expect(api.on.mock.calls[0][0]).toBe(STORY_RENDERED); - expect(api.on.mock.calls[1][0]).toBe(EVENTS.RESULT); - expect(api.on.mock.calls[2][0]).toBe(EVENTS.ERROR); + expect(api.on.mock.calls[0][0]).toBe(EVENTS.RESULT); + expect(api.on.mock.calls[1][0]).toBe(EVENTS.ERROR); + expect(api.on.mock.calls[2][0]).toBe(EVENTS.MANUAL); }); - it('should request a run on tab activation', () => { + it('should deregister event listener on unmount', () => { // given const api = createApi(); - - const wrapper = mount(); - expect(api.emit).not.toHaveBeenCalled(); - - // when - wrapper.setProps({ active: true }); - wrapper.update(); - - // then - expect(api.emit).toHaveBeenCalledWith(EVENTS.REQUEST); - expect(wrapper.find(ScrollArea).length).toBe(0); - }); - - it('should deregister STORY_RENDERED, RESULT and ERROR updater on unmount', () => { - // given - const api = createApi(); - const wrapper = mount(); expect(api.off).not.toHaveBeenCalled(); // when + const wrapper = mount(); wrapper.unmount(); // then expect(api.off.mock.calls.length).toBe(3); - expect(api.off.mock.calls[0][0]).toBe(STORY_RENDERED); - expect(api.off.mock.calls[1][0]).toBe(EVENTS.RESULT); - expect(api.off.mock.calls[2][0]).toBe(EVENTS.ERROR); + expect(api.off.mock.calls[0][0]).toBe(EVENTS.RESULT); + expect(api.off.mock.calls[1][0]).toBe(EVENTS.ERROR); + expect(api.off.mock.calls[2][0]).toBe(EVENTS.MANUAL); }); - it('should update run result', () => { + it('should handle "initial" status', () => { // given const api = createApi(); - const wrapper = mount(); - const onUpdate = api.on.mock.calls.find(([event]) => event === EVENTS.RESULT)[1]; - - expect( - wrapper - .find('button') - .last() - .text() - .trim() - ).toBe('Rerun tests'); // when - onUpdate(axeResult); - - // then - expect( - wrapper - .find('button') - .last() - .text() - .trim() - ).toBe('Tests completed'); - }); - - it('should request run', () => { - // given - const api = createApi(); const wrapper = mount(); - const request = api.on.mock.calls.find(([event]) => event === STORY_RENDERED)[1]; - - expect( - wrapper - .find('button') - .last() - .text() - .trim() - ).toBe('Rerun tests'); - expect(api.emit).not.toHaveBeenCalled(); - - // when - request(); // then - expect( - wrapper - .find('button') - .last() - .text() - .trim() - ).toBe('Running test'); - expect(api.emit).toHaveBeenCalledWith(EVENTS.REQUEST); + expect(api.emit).not.toHaveBeenCalled(); + expect(wrapper.text()).toMatch(/Initializing/); }); - it('should NOT request run on inactive tab', () => { + it('should handle "manual" status', () => { // given const api = createApi(); - mount(); - const request = api.on.mock.calls.find(([event]) => event === STORY_RENDERED)[1]; - expect(api.emit).not.toHaveBeenCalled(); + const wrapper = mount(); // when - request(); + api.emit(EVENTS.MANUAL, true); + wrapper.update(); // then - expect(api.emit).not.toHaveBeenCalled(); + expect(wrapper.text()).toMatch(/Manually run the accessibility scan/); + expect(api.emit).not.toHaveBeenCalledWith(EVENTS.REQUEST); }); - it('should render report', () => { + it('should handle "running" status', () => { // given const api = createApi(); const wrapper = mount(); - const onUpdate = api.on.mock.calls.find(([event]) => event === EVENTS.RESULT)[1]; // when - onUpdate(axeResult); + api.emit(EVENTS.MANUAL, false); + wrapper.update(); // then - expect(wrapper.find(A11YPanel)).toMatchSnapshot(); + expect(wrapper.text()).toMatch(/Please wait while the accessibility scan is running/); + expect(api.emit).toHaveBeenCalledWith(EVENTS.REQUEST); }); - it("should render loader when it's running", () => { + it('should handle "ran" status', () => { // given const api = createApi(); const wrapper = mount(); - const request = api.on.mock.calls.find(([event]) => event === STORY_RENDERED)[1]; // when - request(); + api.emit(EVENTS.RESULT, axeResult); wrapper.update(); // then - expect(wrapper.find('ScrollArea').length).toBe(0); - expect(wrapper.find('Loader').length).toBe(1); - expect(wrapper.find('ActionBar').length).toBe(1); - expect(wrapper.find('Loader')).toMatchSnapshot(); + expect( + wrapper + .find('button') + .last() + .text() + .trim() + ).toBe('Tests completed'); + expect(wrapper.find('Tabs').prop('tabs').length).toBe(3); + expect(wrapper.find('Tabs').prop('tabs')[0].label.props.children).toEqual([1, ' Violations']); + expect(wrapper.find('Tabs').prop('tabs')[1].label.props.children).toEqual([1, ' Passes']); + expect(wrapper.find('Tabs').prop('tabs')[2].label.props.children).toEqual([1, ' Incomplete']); }); - it('should NOT anything when tab is not active', () => { + it('should handle inactive state', () => { // given const api = createApi(); @@ -218,7 +164,7 @@ describe('A11YPanel', () => { const wrapper = mount(); // then - expect(wrapper.find('ScrollArea').length).toBe(0); - expect(wrapper.find('ActionBar').length).toBe(0); + expect(wrapper.text()).toBe(''); + expect(api.emit).not.toHaveBeenCalled(); }); }); diff --git a/addons/a11y/src/components/A11YPanel.tsx b/addons/a11y/src/components/A11YPanel.tsx index a2d7a7fc73d8..de8215a1b6ab 100644 --- a/addons/a11y/src/components/A11YPanel.tsx +++ b/addons/a11y/src/components/A11YPanel.tsx @@ -1,8 +1,8 @@ +/* eslint-disable react/destructuring-assignment,default-case,consistent-return,no-case-declarations */ import React, { Component, Fragment } from 'react'; import { styled } from '@storybook/theming'; -import { STORY_RENDERED } from '@storybook/core-events'; import { ActionBar, Icons, ScrollArea } from '@storybook/components'; import { AxeResults, Result } from 'axe-core'; @@ -20,19 +20,15 @@ export enum RuleType { INCOMPLETION, } -const Icon = styled(Icons)( - { - height: 12, - width: 12, - marginRight: 4, - }, - ({ status, theme }: any) => - status === 'running' - ? { - animation: `${theme.animation.rotate360} 1s linear infinite;`, - } - : {} -); +const Icon = styled(Icons)({ + height: 12, + width: 12, + marginRight: 4, +}); + +const RotatingIcon = styled(Icon)(({ theme }) => ({ + animation: `${theme.animation.rotate360} 1s linear infinite;`, +})); const Passes = styled.span<{}>(({ theme }) => ({ color: theme.color.positive, @@ -46,34 +42,51 @@ const Incomplete = styled.span<{}>(({ theme }) => ({ color: theme.color.warning, })); -const centeredStyle = { +const Centered = styled.span<{}>({ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', -}; - -const Loader = styled(({ className }) => ( -
- Please wait while the accessibility scan is running - ... -
-))(centeredStyle); -Loader.displayName = 'Loader'; - -interface A11YPanelNormalState { - status: 'ready' | 'ran' | 'running'; +}); + +interface InitialState { + status: 'initial'; +} + +interface ManualState { + status: 'manual'; +} + +interface RunningState { + status: 'running'; +} + +interface RanState { + status: 'ran'; passes: Result[]; violations: Result[]; incomplete: Result[]; } -interface A11YPanelErrorState { +interface ReadyState { + status: 'ready'; + passes: Result[]; + violations: Result[]; + incomplete: Result[]; +} + +interface ErrorState { status: 'error'; error: unknown; } -type A11YPanelState = A11YPanelNormalState | A11YPanelErrorState; +type A11YPanelState = + | InitialState + | ManualState + | RunningState + | RanState + | ReadyState + | ErrorState; interface A11YPanelProps { active: boolean; @@ -82,18 +95,15 @@ interface A11YPanelProps { export class A11YPanel extends Component { state: A11YPanelState = { - status: 'ready', - passes: [], - violations: [], - incomplete: [], + status: 'initial', }; componentDidMount() { const { api } = this.props; - api.on(STORY_RENDERED, this.request); - api.on(EVENTS.RESULT, this.onUpdate); + api.on(EVENTS.RESULT, this.onResult); api.on(EVENTS.ERROR, this.onError); + api.on(EVENTS.MANUAL, this.onManual); } componentDidUpdate(prevProps: A11YPanelProps) { @@ -103,18 +113,18 @@ export class A11YPanel extends Component { if (!prevProps.active && active) { // removes all elements from the redux map in store from the previous panel store.dispatch(clearElements()); - this.request(); } } componentWillUnmount() { const { api } = this.props; - api.off(STORY_RENDERED, this.request); - api.off(EVENTS.RESULT, this.onUpdate); + + api.off(EVENTS.RESULT, this.onResult); api.off(EVENTS.ERROR, this.onError); + api.off(EVENTS.MANUAL, this.onManual); } - onUpdate = ({ passes, violations, incomplete }: AxeResults) => { + onResult = ({ passes, violations, incomplete }: AxeResults) => { this.setState( { status: 'ran', @@ -142,64 +152,67 @@ export class A11YPanel extends Component { }); }; - request = () => { - const { api, active } = this.props; - - if (active) { - this.setState( - { - status: 'running', - }, - () => { - api.emit(EVENTS.REQUEST); - // removes all elements from the redux map in store from the previous panel - store.dispatch(clearElements()); - } - ); + onManual = (manual: boolean) => { + if (manual) { + this.setState({ + status: 'manual', + }); + } else { + this.request(); } }; + request = () => { + const { api } = this.props; + this.setState( + { + status: 'running', + }, + () => { + api.emit(EVENTS.REQUEST); + // removes all elements from the redux map in store from the previous panel + store.dispatch(clearElements()); + } + ); + }; + render() { const { active } = this.props; if (!active) return null; - // eslint-disable-next-line react/destructuring-assignment - if (this.state.status === 'error') { - const { error } = this.state; - return ( -
- The accessibility scan encountered an error. -
- {error} -
- ); - } - - const { passes, violations, incomplete, status } = this.state; - - let actionTitle; - if (status === 'ready') { - actionTitle = 'Rerun tests'; - } else if (status === 'running') { - actionTitle = ( - - Running test - - ); - } else if (status === 'ran') { - actionTitle = ( - - Tests completed - - ); - } - - return ( - - - {status === 'running' ? ( - + switch (this.state.status) { + case 'initial': + return Initializing...; + case 'manual': + return ( + + Manually run the accessibility scan. + + + ); + case 'running': + return ( + + Please wait while the accessibility scan is running + ... + + ); + case 'ready': + case 'ran': + const { passes, violations, incomplete, status } = this.state; + const actionTitle = + status === 'ready' ? ( + 'Rerun tests' ) : ( + + Tests completed + + ); + return ( + { ]} /> - )} - - - - ); + + + ); + case 'error': + const { error } = this.state; + return ( + + The accessibility scan encountered an error. +
+ {error} +
+ ); + } } } diff --git a/addons/a11y/src/components/ColorBlindness.tsx b/addons/a11y/src/components/ColorBlindness.tsx index 35edc2bd15c4..87e98989513d 100644 --- a/addons/a11y/src/components/ColorBlindness.tsx +++ b/addons/a11y/src/components/ColorBlindness.tsx @@ -18,7 +18,7 @@ const getFilter = (filter: string | null) => { return `url('#${filter}')`; }; -const ColorIcon = styled.span( +const ColorIcon = styled.span<{ filter: string | null }>( { background: 'linear-gradient(to right, #F44336, #FF9800, #FFEB3B, #8BC34A, #2196F3, #9C27B0)', borderRadius: '1rem', @@ -26,7 +26,7 @@ const ColorIcon = styled.span( height: '1rem', width: '1rem', }, - ({ filter }: { filter: string | null }) => ({ + ({ filter }) => ({ filter: getFilter(filter), }), ({ theme }) => ({ @@ -80,7 +80,7 @@ const getColorList = (active: string | null, set: (i: string | null) => void): L ]; export const ColorBlindness: FunctionComponent = () => { - const [active, setActiveState] = useState(null); + const [active, setActiveState] = useState(null); const setActive = (activeState: string | null): void => { const iframe = getIframe(); diff --git a/addons/a11y/src/components/Report/HighlightToggle.tsx b/addons/a11y/src/components/Report/HighlightToggle.tsx index 2aa554641e39..64c4d0cb7123 100644 --- a/addons/a11y/src/components/Report/HighlightToggle.tsx +++ b/addons/a11y/src/components/Report/HighlightToggle.tsx @@ -5,24 +5,24 @@ import { styled, themes, convert } from '@storybook/theming'; import memoize from 'memoizerific'; import { NodeResult } from 'axe-core'; +import { Dispatch } from 'redux'; import { RuleType } from '../A11YPanel'; import { addElement } from '../../redux-config'; import { IFRAME } from '../../constants'; -export class HighlightedElementData { +export interface HighlightedElementData { originalOutline: string; - isHighlighted: boolean; } interface ToggleProps { elementsToHighlight: NodeResult[]; type: RuleType; - addElement?: (data: any) => void; - highlightedElementsMap?: Map; + addElement: (data: any) => void; + highlightedElementsMap: Map; isToggledOn?: boolean; toggleId?: string; - indeterminate?: boolean; + indeterminate: boolean; } enum CheckBoxStates { @@ -48,7 +48,7 @@ function getElementBySelectorPath(elementPath: string): HTMLElement { if (iframe && iframe.contentDocument && elementPath) { return iframe.contentDocument.querySelector(elementPath); } - return null; + return (null as unknown) as HTMLElement; } function setElementOutlineStyle(targetElement: HTMLElement, outlineStyle: string): void { @@ -64,7 +64,7 @@ function areAllRequiredElementsHighlighted( const targetElement = getElementBySelectorPath(item.target[0]); return ( highlightedElementsMap.has(targetElement) && - highlightedElementsMap.get(targetElement).isHighlighted + (highlightedElementsMap.get(targetElement) as HighlightedElementData).isHighlighted ); }).length; @@ -76,7 +76,7 @@ function areAllRequiredElementsHighlighted( : CheckBoxStates.INDETERMINATE; } -function mapDispatchToProps(dispatch: any) { +function mapDispatchToProps(dispatch: Dispatch) { return { addElement: (data: { element: HTMLElement; data: HighlightedElementData }) => dispatch(addElement(data)), @@ -112,7 +112,7 @@ class HighlightToggle extends Component { }); } - componentDidUpdate(prevProps: Readonly): void { + componentDidUpdate(): void { const { indeterminate } = this.props; if (this.checkBoxRef.current) { this.checkBoxRef.current.indeterminate = indeterminate; @@ -126,8 +126,9 @@ class HighlightToggle extends Component { if (!highlightedElementsMap.has(targetElement)) { return; } - const { originalOutline } = highlightedElementsMap.get(targetElement); - const { isHighlighted } = highlightedElementsMap.get(targetElement); + const { originalOutline, isHighlighted } = highlightedElementsMap.get( + targetElement + ) as HighlightedElementData; const { isToggledOn } = this.props; if ((isToggledOn && isHighlighted) || (!isToggledOn && !isHighlighted)) { const addHighlight = !isToggledOn && !isHighlighted; @@ -151,7 +152,7 @@ class HighlightToggle extends Component { if (highlightedElementsMap.has(targetElement)) { setElementOutlineStyle( targetElement, - highlightedElementsMap.get(targetElement).originalOutline + highlightedElementsMap.get(targetElement)!.originalOutline ); } } @@ -162,9 +163,7 @@ class HighlightToggle extends Component { originalOutline: string ): void { const { addElement: localAddElement } = this.props; - const data: HighlightedElementData = new HighlightedElementData(); - data.isHighlighted = isHighlighted; - data.originalOutline = originalOutline; + const data: HighlightedElementData = { isHighlighted, originalOutline }; const payload = { element: targetElement, highlightedElementData: data }; localAddElement(payload); } diff --git a/addons/a11y/src/components/Report/Rules.tsx b/addons/a11y/src/components/Report/Rules.tsx index 48fe2dd924aa..b1485ef4fa60 100644 --- a/addons/a11y/src/components/Report/Rules.tsx +++ b/addons/a11y/src/components/Report/Rules.tsx @@ -1,17 +1,8 @@ import React, { FunctionComponent } from 'react'; import { styled } from '@storybook/theming'; -import { Badge, Icons } from '@storybook/components'; +import { Badge } from '@storybook/components'; import { CheckResult } from 'axe-core'; import { SizeMe } from 'react-sizeme'; -import { RuleType } from '../A11YPanel'; - -const impactColors = { - minor: '#f1c40f', - moderate: '#e67e22', - serious: '#e74c3c', - critical: '#c0392b', - success: '#2ecc71', -}; const List = styled.div({ display: 'flex', @@ -22,7 +13,7 @@ const List = styled.div({ fontWeight: '400', } as any); -const Item = styled.div(({ elementWidth }: { elementWidth: number }) => { +const Item = styled.div<{ elementWidth: number }>(({ elementWidth }) => { const maxWidthBeforeBreak = 407; return { flexDirection: elementWidth > maxWidthBeforeBreak ? 'row' : 'inherit', @@ -31,31 +22,20 @@ const Item = styled.div(({ elementWidth }: { elementWidth: number }) => { }; }); -const StyledBadge = styled(Badge)(({ status }: { status: string }) => ({ +const StyledBadge = styled(Badge)({ padding: '2px 8px', marginBottom: 3, minWidth: 65, maxWidth: 'fit-content', width: '100%', textAlign: 'center', -})); +}); const Message = styled.div({ paddingLeft: 6, paddingRight: 23, }); -const Status = styled.div(({ passes, impact }: { passes: boolean; impact: string }) => ({ - display: 'inline-flex', - justifyContent: 'center', - alignItems: 'center', - color: passes ? impactColors.success : (impactColors as any)[impact], - '& > svg': { - height: 16, - width: 16, - }, -})); - export enum ImpactValue { MINOR = 'minor', MODERATE = 'moderate', @@ -94,7 +74,7 @@ const Rule: FunctionComponent = ({ rule }) => { } return ( - {({ size }: { size: any }) => ( + {({ size }: { size: { width: number; height: number } }) => ( {formatSeverityText(rule.impact)} {rule.message} diff --git a/addons/a11y/src/components/Tabs.tsx b/addons/a11y/src/components/Tabs.tsx index 26b6febaa040..b16bd1745991 100644 --- a/addons/a11y/src/components/Tabs.tsx +++ b/addons/a11y/src/components/Tabs.tsx @@ -1,6 +1,6 @@ import React, { Component, SyntheticEvent } from 'react'; -import { styled, themes } from '@storybook/theming'; +import { styled } from '@storybook/theming'; import { NodeResult, Result } from 'axe-core'; import { SizeMe } from 'react-sizeme'; import store, { clearElements } from '../redux-config'; @@ -23,7 +23,7 @@ const HighlightToggleLabel = styled.label<{}>(({ theme }) => ({ color: theme.color.dark, })); -const GlobalToggle = styled.div(({ elementWidth }: { elementWidth: number }) => { +const GlobalToggle = styled.div<{ elementWidth: number }>(({ elementWidth }) => { const maxWidthBeforeBreak = 450; return { cursor: 'pointer', @@ -47,7 +47,7 @@ const GlobalToggle = styled.div(({ elementWidth }: { elementWidth: number }) => }; }); -const Item = styled.button( +const Item = styled.button<{ active?: boolean }>( ({ theme }) => ({ textDecoration: 'none', padding: '10px 15px', @@ -66,7 +66,7 @@ const Item = styled.button( borderBottom: `3px solid ${theme.color.secondary}`, }, }), - ({ active, theme }: any) => + ({ active, theme }) => active ? { opacity: 1, @@ -99,7 +99,7 @@ interface TabsState { } function retrieveAllNodesFromResults(items: Result[]): NodeResult[] { - return items.reduce((acc, item) => acc.concat(item.nodes), []); + return items.reduce((acc, item) => acc.concat(item.nodes), [] as NodeResult[]); } export class Tabs extends Component { @@ -109,7 +109,7 @@ export class Tabs extends Component { onToggle = (event: SyntheticEvent) => { this.setState({ - active: parseInt(event.currentTarget.getAttribute('data-index'), 10), + active: parseInt(event.currentTarget.getAttribute('data-index') || '', 10), }); // removes all elements from the redux map in store from the previous panel store.dispatch(clearElements()); diff --git a/addons/a11y/src/components/__snapshots__/A11YPanel.test.js.snap b/addons/a11y/src/components/__snapshots__/A11YPanel.test.js.snap deleted file mode 100644 index db6f667c93a6..000000000000 --- a/addons/a11y/src/components/__snapshots__/A11YPanel.test.js.snap +++ /dev/null @@ -1,1126 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`A11YPanel should render loader when it's running 1`] = ` -@keyframes animation-0 { - from { - -webkit-transform: rotate(0deg); - -ms-transform: rotate(0deg); - transform: rotate(0deg); - } - - to { - -webkit-transform: rotate(360deg); - -ms-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -.emotion-4 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - height: 100%; -} - -.emotion-2 { - height: 12px; - width: 12px; - margin-right: 4px; - -webkit-animation: animation-0 1s linear infinite; - animation: animation-0 1s linear infinite; -} - -.emotion-1 { - shape-rendering: inherit; - -webkit-transform: translate3d(0,0,0); - -ms-transform: translate3d(0,0,0); - transform: translate3d(0,0,0); - display: inline-block; - height: 12px; - width: 12px; - margin-right: 4px; - -webkit-animation: animation-0 1s linear infinite; - animation: animation-0 1s linear infinite; -} - -.emotion-0 { - fill: currentColor; -} - - - -
- - - - - - - - - - - - Please wait while the accessibility scan is running ... -
-
-
-`; - -exports[`A11YPanel should render report 1`] = ` -.emotion-0 { - overflow-y: auto; - height: 100%; - overflow-x: auto; - width: 100%; -} - -.emotion-4 { - position: absolute; - bottom: 0; - right: 0; - max-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - background: #FFFFFF; - z-index: 1; -} - -.emotion-3 { - border: 0 none; - padding: 4px 10px; - cursor: pointer; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - color: #333333; - background: #FFFFFF; - font-size: 12px; - line-height: 16px; - font-family: "Nunito Sans",-apple-system,".SFNSText-Regular","San Francisco",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Helvetica,Arial,sans-serif; - font-weight: 700; - border-top: 1px solid rgba(0,0,0,.1); - border-left: 1px solid rgba(0,0,0,.1); - margin-left: -1px; - border-radius: 4px 0 0 0; -} - -.emotion-3:not(:last-child) { - border-right: 1px solid rgba(0,0,0,.1); -} - -.emotion-3 + * { - border-left: 1px solid rgba(0,0,0,.1); - border-radius: 0; -} - -.emotion-3:focus { - box-shadow: #1EA7FD 0 -3px 0 0 inset; - outline: 0 none; -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - , - "ctr": 35, - "isSpeedy": false, - "key": "css", - "nonce": undefined, - "tags": Array [ - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ], - }, - } - } - serialized={ - Object { - "map": undefined, - "name": "nh5djz", - "next": undefined, - "styles": "[data-simplebar]{position:relative;flex-direction:column;flex-wrap:wrap;justify-content:flex-start;align-content:flex-start;align-items:flex-start;}.simplebar-wrapper{overflow:hidden;width:inherit;height:inherit;max-width:inherit;max-height:inherit;}.simplebar-mask{direction:inherit;position:absolute;overflow:hidden;padding:0;margin:0;left:0;top:0;bottom:0;right:0;width:auto !important;height:auto !important;z-index:0;}.simplebar-offset{direction:inherit !important;resize:none !important;position:absolute;top:0;left:0;bottom:0;right:0;padding:0;margin:0;-webkit-overflow-scrolling:touch;}.simplebar-content-wrapper{direction:inherit;position:relative;display:block;visibility:visible;}.simplebar-placeholder{max-height:100%;max-width:100%;width:100%;pointer-events:none;}.simplebar-height-auto-observer-wrapper{height:100%;width:inherit;max-width:1px;position:relative;float:left;max-height:1px;overflow:hidden;z-index:-1;padding:0;margin:0;pointer-events:none;flex-grow:inherit;flex-shrink:0;flex-basis:0;}.simplebar-height-auto-observer{display:block;opacity:0;position:absolute;top:0;left:0;height:1000%;width:1000%;min-height:1px;min-width:1px;overflow:hidden;pointer-events:none;z-index:-1;}.simplebar-track{z-index:1;position:absolute;right:0;bottom:0;pointer-events:none;overflow:hidden;}[data-simplebar].simplebar-dragging .simplebar-track{pointer-events:all;}.simplebar-scrollbar{position:absolute;right:2px;width:7px;min-height:10px;}.simplebar-scrollbar:before{position:absolute;content:\\"\\";border-radius:7px;left:0;right:0;opacity:0;transition:opacity 0.2s linear;background:#333333;}.simplebar-track .simplebar-scrollbar.simplebar-visible:before{opacity:0.5;transition:opacity 0s linear;}.simplebar-track.simplebar-vertical{top:0;width:11px;}.simplebar-track.simplebar-vertical .simplebar-scrollbar:before{top:2px;bottom:2px;}.simplebar-track.simplebar-horizontal{left:0;height:11px;}.simplebar-track.simplebar-horizontal .simplebar-scrollbar:before{height:100%;left:2px;right:2px;}.simplebar-track.simplebar-horizontal .simplebar-scrollbar{right:auto;left:0;top:2px;height:7px;min-height:0;min-width:10px;width:auto;}[data-simplebar-direction=\\"rtl\\"] .simplebar-track.simplebar-vertical{right:auto;left:0;}", - "toString": [Function], - } - } - /> - - - - -
-
-
-
-
-
-
-
-
- - 0 - Violations - , - "panel": , - "type": 0, - }, - Object { - "items": Array [], - "label": - 0 - Passes - , - "panel": , - "type": 1, - }, - Object { - "items": Array [], - "label": - 0 - Incomplete - , - "panel": , - "type": 2, - }, - ] - } - > - - - - - -
- - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
- - - - - - -
- - - -
-
-
- - -`; diff --git a/addons/a11y/src/constants.ts b/addons/a11y/src/constants.ts index efabac7a268b..79ef7446a159 100755 --- a/addons/a11y/src/constants.ts +++ b/addons/a11y/src/constants.ts @@ -7,5 +7,6 @@ export const CLEAR_ELEMENTS = 'CLEAR_ELEMENTS'; const RESULT = `${ADDON_ID}/result`; const REQUEST = `${ADDON_ID}/request`; const ERROR = `${ADDON_ID}/error`; +const MANUAL = `${ADDON_ID}/manual`; -export const EVENTS = { RESULT, REQUEST, ERROR }; +export const EVENTS = { RESULT, REQUEST, ERROR, MANUAL }; diff --git a/addons/a11y/src/index.ts b/addons/a11y/src/index.ts index a7f53ec29a73..f96d86cb0d07 100644 --- a/addons/a11y/src/index.ts +++ b/addons/a11y/src/index.ts @@ -11,8 +11,10 @@ interface Setup { element?: ElementContext; config: Spec; options: RunOptions; + manual: boolean; } -let setup: Setup = { element: null, config: {}, options: {} }; + +let setup: Setup = { element: undefined, config: {}, options: {}, manual: false }; const getElement = () => { const storyRoot = document.getElementById('story-root'); @@ -58,12 +60,16 @@ export const withA11y = makeDecorator({ if (storedDefaultSetup === null) { storedDefaultSetup = { ...setup }; } - Object.assign(setup, parameters as Setup); + Object.assign(setup, parameters as Partial); } else if (storedDefaultSetup !== null) { Object.assign(setup, storedDefaultSetup); storedDefaultSetup = null; } - addons.getChannel().on(EVENTS.REQUEST, () => run(setup.element, setup.config, setup.options)); + + addons + .getChannel() + .on(EVENTS.REQUEST, () => run(setup.element as ElementContext, setup.config, setup.options)); + addons.getChannel().emit(EVENTS.MANUAL, setup.manual); return getStory(context); }, diff --git a/addons/a11y/tsconfig.json b/addons/a11y/tsconfig.json index 8876bb6737a1..99a91ffc487b 100644 --- a/addons/a11y/tsconfig.json +++ b/addons/a11y/tsconfig.json @@ -2,7 +2,13 @@ "extends": "../../tsconfig.json", "compilerOptions": { "rootDir": "./src", - "types": ["webpack-env"] + "types": ["webpack-env"], + "forceConsistentCasingInFileNames": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true }, "include": [ "src/**/*" diff --git a/addons/actions/package.json b/addons/actions/package.json index f0ef79eb118b..c1e60dd0c374 100644 --- a/addons/actions/package.json +++ b/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "Action Logger addon for storybook", "keywords": [ "storybook" @@ -17,7 +17,6 @@ "license": "MIT", "files": [ "dist/**/*", - "docs/**/*", "README.md", "*.js", "*.d.ts" @@ -28,12 +27,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-rc.11", - "@storybook/api": "5.3.0-rc.11", - "@storybook/client-api": "5.3.0-rc.11", - "@storybook/components": "5.3.0-rc.11", - "@storybook/core-events": "5.3.0-rc.11", - "@storybook/theming": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", + "@storybook/api": "6.0.0-alpha.2", + "@storybook/client-api": "6.0.0-alpha.2", + "@storybook/components": "6.0.0-alpha.2", + "@storybook/core-events": "6.0.0-alpha.2", + "@storybook/theming": "6.0.0-alpha.2", "core-js": "^3.0.1", "fast-deep-equal": "^2.0.1", "global": "^4.3.2", @@ -45,7 +44,8 @@ }, "devDependencies": { "@types/lodash": "^4.14.149", - "@types/uuid": "^3.4.4" + "@types/uuid": "^3.4.4", + "@types/webpack-env": "^1.15.0" }, "publishConfig": { "access": "public" diff --git a/addons/backgrounds/package.json b/addons/backgrounds/package.json index b30d5c07d32f..16ac69bb7c7d 100644 --- a/addons/backgrounds/package.json +++ b/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "A storybook addon to show different backgrounds for your preview", "keywords": [ "addon", @@ -21,7 +21,6 @@ "author": "jbaxleyiii", "files": [ "dist/**/*", - "docs/**/*", "README.md", "*.js", "*.d.ts" @@ -32,19 +31,20 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-rc.11", - "@storybook/api": "5.3.0-rc.11", - "@storybook/client-logger": "5.3.0-rc.11", - "@storybook/components": "5.3.0-rc.11", - "@storybook/core-events": "5.3.0-rc.11", - "@storybook/theming": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", + "@storybook/api": "6.0.0-alpha.2", + "@storybook/client-logger": "6.0.0-alpha.2", + "@storybook/components": "6.0.0-alpha.2", + "@storybook/core-events": "6.0.0-alpha.2", + "@storybook/theming": "6.0.0-alpha.2", "core-js": "^3.0.1", "memoizerific": "^1.11.3", "react": "^16.8.3", "util-deprecate": "^1.0.2" }, "devDependencies": { - "@types/util-deprecate": "^1.0.0" + "@types/util-deprecate": "^1.0.0", + "@types/webpack-env": "^1.15.0" }, "publishConfig": { "access": "public" diff --git a/addons/centered/package.json b/addons/centered/package.json index a1c0adc53065..ca536816cc3f 100644 --- a/addons/centered/package.json +++ b/addons/centered/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-centered", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "Storybook decorator to center components", "keywords": [ "addon", @@ -29,13 +29,14 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", "core-js": "^3.0.1", "global": "^4.3.2", "util-deprecate": "^1.0.2" }, "devDependencies": { "@types/mithril": "^1.1.16", + "@types/webpack-env": "^1.15.0", "mithril": "*", "preact": "*", "react": "*" diff --git a/addons/contexts/package.json b/addons/contexts/package.json index 4c06346ed25e..840ceb726697 100644 --- a/addons/contexts/package.json +++ b/addons/contexts/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-contexts", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "Storybook Addon Contexts", "keywords": [ "preact", @@ -27,10 +27,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-rc.11", - "@storybook/api": "5.3.0-rc.11", - "@storybook/components": "5.3.0-rc.11", - "@storybook/core-events": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", + "@storybook/api": "6.0.0-alpha.2", + "@storybook/components": "6.0.0-alpha.2", + "@storybook/core-events": "6.0.0-alpha.2", "core-js": "^3.0.1", "global": "^4.3.2", "qs": "^6.6.0" @@ -39,6 +39,7 @@ "global": "*", "preact": "*", "qs": "*", + "rax": "*", "react": "*", "vue": "*" }, diff --git a/addons/contexts/rax.js b/addons/contexts/rax.js new file mode 100644 index 000000000000..06abd7467f83 --- /dev/null +++ b/addons/contexts/rax.js @@ -0,0 +1,4 @@ +import { withContexts } from './dist/preview/frameworks/rax'; + +export { withContexts }; +export default withContexts; diff --git a/addons/contexts/src/preview/frameworks/rax.ts b/addons/contexts/src/preview/frameworks/rax.ts new file mode 100644 index 000000000000..0748a7d7f7cf --- /dev/null +++ b/addons/contexts/src/preview/frameworks/rax.ts @@ -0,0 +1,14 @@ +import { createElement, RaxElement } from 'rax'; +import { createAddonDecorator, Render } from '../../index'; +import { ContextsPreviewAPI } from '../ContextsPreviewAPI'; + +/** + * This is the framework specific bindings for Rax. + * '@storybook/rax' expects the returning object from a decorator to be a 'Rax Element' (vNode). + */ +export const renderRax: Render> = (contextNodes, propsMap, getStoryVNode) => { + const { getRendererFrom } = ContextsPreviewAPI(); + return getRendererFrom(createElement)(contextNodes, propsMap, getStoryVNode); +}; + +export const withContexts = createAddonDecorator(renderRax); diff --git a/addons/cssresources/README.md b/addons/cssresources/README.md index c3b91348eef0..bf15532f593e 100644 --- a/addons/cssresources/README.md +++ b/addons/cssresources/README.md @@ -20,8 +20,8 @@ Add following content to it: ```js module.exports = { - addons: ['@storybook/addon-cssresources/register'] -} + addons: ['@storybook/addon-cssresources/register'], +}; ``` ## Usage @@ -34,17 +34,17 @@ import { withCssResources } from '@storybook/addon-cssresources'; export default { title: 'CssResources', parameters: { - cssresources: [{ + cssresources: [ + { id: `bluetheme`, code: ``, picked: false, + hideCode: false, // Defaults to false, this enables you to hide the code snippet and only displays the style selector }, ], }, decorators: [withCssResources], }; -export const defaultView = () => ( -
-); +export const defaultView = () =>
; ``` diff --git a/addons/cssresources/package.json b/addons/cssresources/package.json index 05057a21f661..b1f21d225e10 100644 --- a/addons/cssresources/package.json +++ b/addons/cssresources/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-cssresources", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "A storybook addon to switch between css resources at runtime for your story", "keywords": [ "addon", @@ -21,7 +21,6 @@ "author": "nm123github", "files": [ "dist/**/*", - "docs/**/*", "README.md", "*.js", "*.d.ts" @@ -32,14 +31,18 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-rc.11", - "@storybook/api": "5.3.0-rc.11", - "@storybook/components": "5.3.0-rc.11", - "@storybook/core-events": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", + "@storybook/api": "6.0.0-alpha.2", + "@storybook/components": "6.0.0-alpha.2", + "@storybook/core-events": "6.0.0-alpha.2", + "@storybook/theming": "6.0.0-alpha.2", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3" }, + "devDependencies": { + "@types/webpack-env": "^1.15.0" + }, "peerDependencies": { "react": "*" }, diff --git a/addons/cssresources/src/CssResource.ts b/addons/cssresources/src/CssResource.ts index 0067ca677488..ee67b93e2a7c 100644 --- a/addons/cssresources/src/CssResource.ts +++ b/addons/cssresources/src/CssResource.ts @@ -2,4 +2,5 @@ export interface CssResource { id: string; code: string; picked: boolean; + hideCode: boolean; } diff --git a/addons/cssresources/src/css-resource-panel.test.js b/addons/cssresources/src/css-resource-panel.test.js index cd0f47303045..ef75ae2ba376 100644 --- a/addons/cssresources/src/css-resource-panel.test.js +++ b/addons/cssresources/src/css-resource-panel.test.js @@ -300,5 +300,32 @@ describe('CSSResourcePanel', () => { node.instance().onStoryChange('fake-story-id'); expect(node.find(SyntaxHighlighter).length).toEqual(1); }); + + it('should not render code for items /w the `hideCode` flag', () => { + const apiGetParameters = jest.fn(() => [ + { + id: 'local-fake-id-1', + code: 'local-fake-code-1', + picked: true, + hideCode: true, + }, + { + id: 'local-fake-id-2', + code: 'local-fake-code-2', + picked: false, + }, + ]); + + const node = shallowNode({ + ...defaultProps, + api: { + ...defaultProps.api, + getParameters: apiGetParameters, + }, + }); + + node.instance().onStoryChange('fake-story-id'); + expect(node.find(SyntaxHighlighter).length).toEqual(1); + }); }); }); diff --git a/addons/cssresources/src/css-resource-panel.tsx b/addons/cssresources/src/css-resource-panel.tsx index ef0be6e19bb2..5155edb71c31 100644 --- a/addons/cssresources/src/css-resource-panel.tsx +++ b/addons/cssresources/src/css-resource-panel.tsx @@ -1,7 +1,8 @@ import React, { Component, Fragment } from 'react'; -import { SyntaxHighlighter } from '@storybook/components'; +import { SyntaxHighlighter, Placeholder, Spaced, Icons } from '@storybook/components'; import { STORY_RENDERED } from '@storybook/core-events'; import { API } from '@storybook/api'; +import { styled } from '@storybook/theming'; import { EVENTS, PARAM_KEY } from './constants'; import { CssResource } from './CssResource'; @@ -20,6 +21,27 @@ interface CssResourceLookup { [key: string]: CssResource; } +const maxLimitToUseSyntaxHighlighter = 100000; + +const PlainCode = styled.pre({ + textAlign: 'left', + fontWeight: 'normal', +}); + +const Warning = styled.div({ + display: 'flex', + padding: '10px', + justifyContent: 'center', + alignItems: 'center', + background: '#fff3cd', + fontSize: 12, + '& svg': { + marginRight: 10, + width: 24, + height: 24, + }, +}); + export class CssResourcePanel extends Component { constructor(props: Props) { super(props); @@ -90,13 +112,26 @@ export class CssResourcePanel extends Component { return (
{list && - list.map(({ id, code, picked }) => ( + list.map(({ id, code, picked, hideCode = false }) => (
- {code ? {code} : null} + {code && !hideCode && code.length < maxLimitToUseSyntaxHighlighter && ( + {code} + )} + {code && !hideCode && code.length >= maxLimitToUseSyntaxHighlighter && ( + + + {code.substring(0, maxLimitToUseSyntaxHighlighter)} ... + + + Rest of the content cannot be displayed + + + + )}
))}
diff --git a/addons/design-assets/package.json b/addons/design-assets/package.json index 6d44f27abf15..cc084cbbb76c 100644 --- a/addons/design-assets/package.json +++ b/addons/design-assets/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-design-assets", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "Design asset preview for storybook", "keywords": [ "addon", @@ -23,7 +23,6 @@ "license": "MIT", "files": [ "dist/**/*", - "docs/**/*", "README.md", "*.js", "*.d.ts" @@ -34,12 +33,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.3.0-rc.11", - "@storybook/api": "5.3.0-rc.11", - "@storybook/client-logger": "5.3.0-rc.11", - "@storybook/components": "5.3.0-rc.11", - "@storybook/core-events": "5.3.0-rc.11", - "@storybook/theming": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", + "@storybook/api": "6.0.0-alpha.2", + "@storybook/client-logger": "6.0.0-alpha.2", + "@storybook/components": "6.0.0-alpha.2", + "@storybook/core-events": "6.0.0-alpha.2", + "@storybook/theming": "6.0.0-alpha.2", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3", diff --git a/addons/docs/README.md b/addons/docs/README.md index 2e69a8b3e17d..1276d5f2c299 100644 --- a/addons/docs/README.md +++ b/addons/docs/README.md @@ -4,6 +4,8 @@ # Storybook Docs +> migration guide: This page documents the method to configure storybook introduced recently in 5.3.0, consult the [migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md) if you want to migrate to this format of configuring storybook. + Storybook Docs transforms your Storybook stories into world-class component documentation. **DocsPage.** Out of the box, all your stories get a `DocsPage`. `DocsPage` is a zero-config aggregation of your component stories, text descriptions, docgen comments, props tables, and code examples into clean, readable pages. @@ -77,16 +79,16 @@ For more information on `MDX`, see the [`MDX` reference](./docs/mdx.md). Storybook Docs supports all view layers that Storybook supports except for React Native (currently). There are some framework-specific features as well, such as props tables and inline story rendering. This chart captures the current state of support: -| | React | Vue | Angular | Ember | Web Components | HTML | Svelte | Preact | Polymer | Riot | Mithril | Marko | -| ----------------- | :---: | :-: | :-----: | :---: | :------------: | :--: | :----: | :----: | :-----: | :--: | :-----: | :---: | -| MDX stories | + | + | + | + | + | + | + | + | + | + | + | + | -| CSF stories | + | + | + | + | + | + | + | + | + | + | + | + | -| StoriesOf stories | + | + | + | + | + | + | + | + | + | + | + | + | -| Source | + | + | + | + | + | + | + | + | + | + | + | + | -| Notes / Info | + | + | + | + | + | + | + | + | + | + | + | + | -| Props table | + | + | + | + | + | | | | | | | | -| Description | + | + | + | + | + | | | | | | | | -| Inline stories | + | + | | | + | | | | | | | | +| | React | Vue | Angular | Ember | Web Components | HTML | Svelte | Preact | Riot | Mithril | Marko | +| ----------------- | :---: | :-: | :-----: | :---: | :------------: | :--: | :----: | :----: | :--: | :-----: | :---: | +| MDX stories | + | + | + | + | + | + | + | + | + | + | + | +| CSF stories | + | + | + | + | + | + | + | + | + | + | + | +| StoriesOf stories | + | + | + | + | + | + | + | + | + | + | + | +| Source | + | + | + | + | + | + | + | + | + | + | + | +| Notes / Info | + | + | + | + | + | + | + | + | + | + | + | +| Props table | + | + | + | + | + | | | | | | | +| Description | + | + | + | + | + | | | | | | | +| Inline stories | + | + | | | + | | | | | | | **Note:** `#` = WIP support @@ -162,22 +164,20 @@ The `configureJSX` option is useful when you're writing your docs in MDX and you ## Manual configuration -If you don't want to use the preset, and prefer to configure "the long way", first register the addon in `.storybook/main.js`: - -```js -module.exports = { - addons: ['@storybook/addon-docs/register'], -}; -``` - -Then configure Storybook's webpack loader in `.storybook/main.js` to understand MDX story files and annotate TS/JS story files with source code using `source-loader`: +If you don't want to use the preset, and prefer to configure "the long way" add the following configuration to `.storybook/main.js` (see comments inline for explanation): ```js const createCompiler = require('@storybook/addon-docs/mdx-compiler-plugin'); module.exports = { - webpack: async config => { + // 1. register the docs panel (as opposed to '@storybook/addon-docs' which + // will configure everything with a preset) + addons: ['@storybook/addon-docs/register'], + // 2. manually configure webpack, since you're not using the preset + webpackFinal: async config => { config.module.rules.push({ + // 2a. Load `.stories.mdx` / `.story.mdx` files as CSF and generate + // the docs page from the markdown test: /\.(stories|story)\.mdx$/, use: [ { @@ -195,6 +195,8 @@ module.exports = { }, ], }); + // 2b. Run `source-loader` on story files to show their source code + // automatically in `DocsPage` or the `Source` doc block. config.module.rules.push({ test: /\.(stories|story)\.[tj]sx?$/, loader: require.resolve('@storybook/source-loader'), diff --git a/addons/docs/angular/README.md b/addons/docs/angular/README.md index 0d9f819c6d2a..5783d26dfcaa 100644 --- a/addons/docs/angular/README.md +++ b/addons/docs/angular/README.md @@ -4,6 +4,8 @@ # Storybook Docs for Angular +> migration guide: This page documents the method to configure storybook introduced recently in 5.3.0, consult the [migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md) if you want to migrate to this format of configuring storybook. + Storybook Docs transforms your Storybook stories into world-class component documentation. Storybook Docs for Angular supports [DocsPage](../docs/docspage.md) for auto-generated docs, and [MDX](../docs/mdx.md) for rich long-form docs. To learn more about Storybook Docs, read the [general documentation](../README.md). To learn the Angular specifics, read on! diff --git a/addons/docs/docs/faq.md b/addons/docs/docs/faq.md index 82fc188d4f50..e7592c3e2aa0 100644 --- a/addons/docs/docs/faq.md +++ b/addons/docs/docs/faq.md @@ -10,7 +10,7 @@ You've read the [Storybook Docs README](../README.md). You're already familiar w ## Does Docs support framework X? -Docs does not currently support [React Native](https://github.com/storybooks/storybook/tree/next/app/react-native). Otherwise, [it supports all frameworks that Storybook supports](../README.md#framework-support), including React, Vue, Angular, Ember, Svelte, Polymer, and others. +Docs does not currently support [React Native](https://github.com/storybooks/storybook/tree/next/app/react-native). Otherwise, [it supports all frameworks that Storybook supports](../README.md#framework-support), including React, Vue, Angular, Ember, Svelte, and others. ## How does Docs interact with existing addons? diff --git a/addons/docs/docs/mdx.md b/addons/docs/docs/mdx.md index fb6e1ee1909a..0d65a34044c3 100644 --- a/addons/docs/docs/mdx.md +++ b/addons/docs/docs/mdx.md @@ -4,8 +4,6 @@ # Storybook Docs MDX -> ⚠️ MDX support is an experimental feature in Storybook 5.2. The API may change in 5.3 outside of the normal semver rules. Be forewarned! - `MDX` is the syntax [Storybook Docs](../README.md) uses to capture long-form markdown documentation and stories in one file. You can also write pure documentation pages in `MDX` and add them to Storybook alongside your stories. - [Storybook Docs MDX](#storybook-docs-mdx) diff --git a/addons/docs/docs/recipes.md b/addons/docs/docs/recipes.md index 427b11a5eb91..2b1d4841194e 100644 --- a/addons/docs/docs/recipes.md +++ b/addons/docs/docs/recipes.md @@ -76,9 +76,7 @@ And I can also embed arbitrary markdown & JSX in this file. What's happening here: - Your stories are defined in CSF, but because of `includeStories: []`, they are not actually added to Storybook. -- The MDX file is adding the stories to Storybook, and using the story function defined in CSF. -- The MDX loader is using story metadata from CSF, such as name, decorators, parameters, but will give giving preference to anything defined in the MDX file. -- The MDX file is using the Meta `default` defined in the CSF. +- The MDX file is simply importing stories as functions in the MDX, and other aspects of the CSF file, such as decorators, parameters, and any other metadata should be applied as needed in the MDX from the import. ## CSF Stories with arbitrary MDX @@ -211,6 +209,31 @@ User writes documentation & stories side-by-side in a single MDX file, and wants ``` +## Controlling a story's view mode + +Storybook's default story navigation behavior is to preserve the existing view mode. In other words, if a user is viewing a story in "docs" mode, and clicks on another story, they will navigate to the other story in "docs" mode. If they are viewing a story in "story" mode (i.e. "canvas" in the UI) they will navigate to another story in "story" mode (with the exception of "docs-only" pages, which are always shown in "docs" mode). + +Based on user feedback, it's also possible to control the view mode for an individual story using the `viewMode` story parameter. In the following example, the nav link will always set the view mode to story: + +```js +export const Foo = () => ; +Foo.story = { + parameters: { + // reset the view mode to "story" whenever the user navigates to this story + viewMode: 'story', + }, +}; +``` + +This can also be applied globally in `preview.js`: + +```js +// always reset the view mode to "docs" whenever the user navigates +addParameters({ + viewMode: 'docs', +}); +``` + ## More resources Want to learn more? Here are some more articles on Storybook Docs: diff --git a/addons/docs/docs/theming.md b/addons/docs/docs/theming.md index 23c12ce159bd..73ee65dced5f 100644 --- a/addons/docs/docs/theming.md +++ b/addons/docs/docs/theming.md @@ -10,7 +10,11 @@ Storybook theming is the **recommended way** to theme your docs. If you update your storybook theme according to [the documentation](https://storybook.js.org/docs/configurations/theming/), Storybook Docs should adapt in reasonable ways. -For example, here's how to change your docs (and Storybook) to the dark theme, by modifying `.storybook/preview.js`: +> In the documentation it will say you can theme storybook in `manager.js`, That's a newer more optimal way to theme storybook, but it's currently incompatible with docs. +> +> We're working on making it compatible in 6.0.0, so for now use the method described below. + +Here's how to change your docs (and Storybook) to the dark theme, by modifying `.storybook/preview.js`: ```js import { addParameters } from '@storybook/react'; diff --git a/addons/docs/ember/README.md b/addons/docs/ember/README.md index eed0df6bbd2e..375b8b0de3e6 100644 --- a/addons/docs/ember/README.md +++ b/addons/docs/ember/README.md @@ -1,5 +1,7 @@ # Storybook Docs for Ember +> migration guide: This page documents the method to configure storybook introduced recently in 5.3.0, consult the [migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md) if you want to migrate to this format of configuring storybook. + Storybook Docs transforms your Storybook stories into world-class component documentation. Storybook Docs for Ember supports [DocsPage](../docs/docspage.md) for auto-generated docs, and [MDX](../docs/mdx.md) for rich long-form docs. To learn more about Storybook Docs, read the [general documentation](../README.md). To learn the Ember specifics, read on! @@ -91,7 +93,7 @@ Finally, you can create MDX files like this: ```md import { Meta, Story, Props } from '@storybook/addon-docs/blocks'; -import hbs from 'htmlbars-inline-precompile' +import { hbs } from 'ember-cli-htmlbars'; diff --git a/addons/docs/package.json b/addons/docs/package.json index d7d4c0fc3098..cb735d29f20a 100644 --- a/addons/docs/package.json +++ b/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "5.3.0-rc.11", + "version": "6.0.0-alpha.2", "description": "Superior documentation for your components", "keywords": [ "addon", @@ -19,7 +19,6 @@ "license": "MIT", "files": [ "dist/**/*", - "docs/**/*", "angular/**/*", "common/**/*", "ember/**/*", @@ -46,13 +45,14 @@ "@mdx-js/loader": "^1.5.1", "@mdx-js/mdx": "^1.5.1", "@mdx-js/react": "^1.5.1", - "@storybook/addons": "5.3.0-rc.11", - "@storybook/api": "5.3.0-rc.11", - "@storybook/components": "5.3.0-rc.11", + "@storybook/addons": "6.0.0-alpha.2", + "@storybook/api": "6.0.0-alpha.2", + "@storybook/components": "6.0.0-alpha.2", + "@storybook/core-events": "6.0.0-alpha.2", "@storybook/csf": "0.0.1", - "@storybook/postinstall": "5.3.0-rc.11", - "@storybook/source-loader": "5.3.0-rc.11", - "@storybook/theming": "5.3.0-rc.11", + "@storybook/postinstall": "6.0.0-alpha.2", + "@storybook/source-loader": "6.0.0-alpha.2", + "@storybook/theming": "6.0.0-alpha.2", "acorn": "^7.1.0", "acorn-jsx": "^5.1.0", "acorn-walk": "^7.0.0", @@ -78,7 +78,6 @@ "@types/jest": "^24.0.11", "@types/prop-types": "^15.5.9", "@types/util-deprecate": "^1.0.0", - "@types/webpack-env": "^1.14.0", "jest-specific-snapshot": "^2.0.0" }, "peerDependencies": { diff --git a/addons/docs/react/README.md b/addons/docs/react/README.md index 7b476cb0d090..55d74e526abf 100644 --- a/addons/docs/react/README.md +++ b/addons/docs/react/README.md @@ -4,6 +4,8 @@ # Storybook Docs for React +> migration guide: This page documents the method to configure storybook introduced recently in 5.3.0, consult the [migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md) if you want to migrate to this format of configuring storybook. + Storybook Docs transforms your Storybook stories into world-class component documentation. Storybook Docs for React supports [DocsPage](../docs/docspage.md) for auto-generated docs, and [MDX](../docs/mdx.md) for rich long-form docs. To learn more about Storybook Docs, read the [general documentation](../README.md). To learn the React specifics, read on! diff --git a/addons/docs/src/blocks/DocsContainer.tsx b/addons/docs/src/blocks/DocsContainer.tsx index cedf8e18f4de..bc536a2361c2 100644 --- a/addons/docs/src/blocks/DocsContainer.tsx +++ b/addons/docs/src/blocks/DocsContainer.tsx @@ -29,7 +29,12 @@ export const DocsContainer: FunctionComponent = ({ context, const allComponents = { ...defaultComponents, ...userComponents }; useEffect(() => { - const url = new URL(window.parent.location); + let url; + try { + url = new URL(window.parent.location); + } catch (err) { + return; + } if (url.hash) { const element = document.getElementById(url.hash.substring(1)); if (element) { diff --git a/addons/docs/src/blocks/Source.tsx b/addons/docs/src/blocks/Source.tsx index 4464c02a6293..fcd13ceac9cd 100644 --- a/addons/docs/src/blocks/Source.tsx +++ b/addons/docs/src/blocks/Source.tsx @@ -35,17 +35,23 @@ interface StorySource { } const extract = (targetId: string, { source, locationsMap }: StorySource) => { + if (!locationsMap) { + return source; + } const location = locationsMap[targetId]; // FIXME: bad locationsMap generated for module export functions whose titles are overridden if (!location) return null; const { startBody: start, endBody: end } = location; const lines = source.split('\n'); - if (start.line === end.line) { + if (start.line === end.line && lines[start.line - 1] !== undefined) { return lines[start.line - 1].substring(start.col, end.col); } // NOTE: storysource locations are 1-based not 0-based! const startLine = lines[start.line - 1]; const endLine = lines[end.line - 1]; + if (startLine === undefined || endLine === undefined) { + return source; + } return [ startLine.substring(start.col), ...lines.slice(start.line, end.line - 1), diff --git a/addons/docs/src/blocks/mdx.tsx b/addons/docs/src/blocks/mdx.tsx index ca5225602199..473ee8a57ee8 100644 --- a/addons/docs/src/blocks/mdx.tsx +++ b/addons/docs/src/blocks/mdx.tsx @@ -1,11 +1,11 @@ import React, { FC, SyntheticEvent } from 'react'; +import addons from '@storybook/addons'; import { Source } from '@storybook/components'; +import { NAVIGATE_URL } from '@storybook/core-events'; import { Code, components } from '@storybook/components/html'; -import { document, window } from 'global'; -import { isNil } from 'lodash'; +import { document } from 'global'; import { styled } from '@storybook/theming'; import { DocsContext, DocsContextProps } from './DocsContext'; -import { scrollToElement } from './utils'; // Hacky utility for asserting identifiers in MDX Story elements export const assertIsFn = (val: any) => { @@ -48,11 +48,8 @@ export const CodeOrSourceMdx: FC = ({ className, children, ); }; -function generateHrefWithHash(hash: string): string { - const url = new URL(window.parent.location); - const href = `${url.origin}/${url.search}#${hash}`; - - return href; +function navigate(url: string) { + addons.getChannel().emit(NAVIGATE_URL, url); } // @ts-ignore @@ -65,14 +62,12 @@ interface AnchorInPageProps { const AnchorInPage: FC = ({ hash, children }) => ( { - event.preventDefault(); - - const hashValue = hash.substring(1); - const element = document.getElementById(hashValue); - if (!isNil(element)) { - window.parent.history.replaceState(null, '', generateHrefWithHash(hashValue)); - scrollToElement(element); + const id = hash.substring(1); + const element = document.getElementById(id); + if (element) { + navigate(hash); } }} > @@ -88,7 +83,7 @@ interface AnchorMdxProps { export const AnchorMdx: FC = props => { const { href, target, children, ...rest } = props; - if (!isNil(href)) { + if (href) { // Enable scrolling for in-page anchors. if (href.startsWith('#')) { return {children}; @@ -96,11 +91,16 @@ export const AnchorMdx: FC = props => { // Links to other pages of SB should use the base URL of the top level iframe instead of the base URL of the preview iframe. if (target !== '_blank') { - const parentUrl = new URL(window.parent.location.href); - const newHref = `${parentUrl.origin}${href}`; - return ( - + { + event.preventDefault(); + navigate(href); + }} + target={target} + {...rest} + > {children} ); @@ -149,17 +149,19 @@ const HeaderWithOcticonAnchor: FC = ({ }) => { // @ts-ignore const OcticonHeader = OcticonHeaders[as]; + const hash = `#${id}`; return (