diff --git a/.babelrc.js b/.babelrc.js index 9533d25af29..b60cfbe892d 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -13,6 +13,7 @@ const withTests = { }; module.exports = { + ignore: ['./lib/codemod/src/transforms/__testfixtures__'], presets: [ ['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage', corejs: '3' }], '@babel/preset-typescript', @@ -53,6 +54,7 @@ module.exports = { }, { test: './lib', + exclude: './addons/storysource/src/loader', presets: [ ['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage', corejs: '3' }], '@babel/preset-react', @@ -76,6 +78,7 @@ module.exports = { './lib/core/src/server', './lib/node-logger', './lib/codemod', + './lib/source-loader/src', './addons/storyshots', './addons/storysource/src/loader', './app/**/src/server/**', diff --git a/.eslintignore b/.eslintignore index 73cb24becbf..af5321f2b3b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -10,6 +10,7 @@ lib/cli/test scripts/storage *.bundle.js *.js.map +*.d.ts !.remarkrc.js !.babelrc.js @@ -18,7 +19,3 @@ scripts/storage !.jest.config.js !.storybook -REACT_NATIVE -examples-native -react-native -ondevice-* \ No newline at end of file diff --git a/.github/automention.yml b/.github/automention.yml index 59c65111e0f..b137b453dbc 100644 --- a/.github/automention.yml +++ b/.github/automention.yml @@ -7,7 +7,7 @@ 'app: react-native': ['benoitdion', 'gongreg'] 'app: react-native-server': ['benoitdion', 'igor-dv'] 'app: svelte': ['cam-stitt', 'plumpNation'] -'app: vue': ['backbone87', 'elevatebart'] +'app: vue': ['backbone87', 'elevatebart', 'pksunkara'] 'api: addons': ['ndelangen'] 'addon: a11y': ['CodeByAlex', 'Armanio', 'jsomsanith'] 'addon: contexts': ['leoyli'] diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d8126d9c7a..33f5529becb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,188 @@ +## 5.2.0-alpha.32 (June 29, 2019) + +### Features + +* Addon-docs: Add .story.mdx support to preset ([#7229](https://github.com/storybookjs/storybook/pull/7229)) + +### Bug Fixes + +* React-native: Fix react native server ([#7187](https://github.com/storybookjs/storybook/pull/7187)) +* Addon-docs: Fix source-loader in monorepo examples ([#7214](https://github.com/storybookjs/storybook/pull/7214)) + +### Maintenance + +* Addon-docs: Convert repo stories to new module format ([#7175](https://github.com/storybookjs/storybook/pull/7175)) + +## 5.2.0-alpha.31 (June 27, 2019) + +### Breaking Changes + +* Module format: story field for name/parameters annotation ([#7202](https://github.com/storybookjs/storybook/pull/7202)) + +### Features + +* Core: Story sorting ([#6472](https://github.com/storybookjs/storybook/pull/6472)) + +### Maintenance + +* Addon-docs: Fix source-loader CI errors ([#7203](https://github.com/storybookjs/storybook/pull/7203)) + +## 5.2.0-alpha.30 (June 25, 2019) + +This release merges `release/docs-technical-preview` branch back into `next` through a series of PRs. It also contains other changes that came in on `next` since the last alpha. + +### Features + +* CLI: Add info command to print environment information ([#6937](https://github.com/storybookjs/storybook/pull/6937)) +* CLI: Use process.env.CI if available ([#7118](https://github.com/storybookjs/storybook/pull/7118)) +* Addon-docs: Source loader library ([#7117](https://github.com/storybookjs/storybook/pull/7117)) +* Addon-docs: Support non-story exports in MDX ([#7188](https://github.com/storybookjs/storybook/pull/7188)) +* Addon-docs: Support non-story exports in module format ([#7185](https://github.com/storybookjs/storybook/pull/7185)) +* Addon-docs: Docs mode with `--docs` flag ([#7154](https://github.com/storybookjs/storybook/pull/7154)) +* Addon-docs: Convert to module format codemod ([#7174](https://github.com/storybookjs/storybook/pull/7174)) +* Addon-docs: MDX support ([#7145](https://github.com/storybookjs/storybook/pull/7145)) +* Addon-docs: Component parameter codemod ([#7155](https://github.com/storybookjs/storybook/pull/7155)) +* Addon-docs: DocsPage and doc blocks ([#7119](https://github.com/storybookjs/storybook/pull/7119)) +* Addon-docs: Module story format & framework param ([#7110](https://github.com/storybookjs/storybook/pull/7110)) +* Addon-docs: Basic skeleton, UI viewMode handling ([#7107](https://github.com/storybookjs/storybook/pull/7107)) + +### Bug Fixes + +* Addon-backgrounds: Fix unstretched preview background wrapper ([#7173](https://github.com/storybookjs/storybook/pull/7173)) +* Addon-notes/info: Fix indenting on markdown code blocks ([#7158](https://github.com/storybookjs/storybook/pull/7158)) +* Core: Improve HMR error reporting, no refreshes needed for error recovery ([#6972](https://github.com/storybookjs/storybook/pull/6972)) +* Addon-info: change stylesheetBase info height from 110vh to 100vh ([#7141](https://github.com/storybookjs/storybook/pull/7141)) + +### Maintenance + +* Typescript: Migrate addon viewport ([#7177](https://github.com/storybookjs/storybook/pull/7177)) + +### Dependency Upgrades + +* Bump css-loader from 2.1.1 to 3.0.0 ([#7122](https://github.com/storybookjs/storybook/pull/7122)) +* Upgrade core-js to 3.x in devkits ([#7171](https://github.com/storybookjs/storybook/pull/7171)) +* UPGRADE lazy-universal-dotenv ([#7151](https://github.com/storybookjs/storybook/pull/7151)) + +## 5.1.9 (June 20, 2019) + +### Bug Fixes + +* Core: Fix JSON babel config error reporting ([#7104](https://github.com/storybookjs/storybook/pull/7104)) +* UI: Fix about page version check message ([#7105](https://github.com/storybookjs/storybook/pull/7105)) + +### Dependency Upgrades + +* Add missing dependencies to ui/react ([#7081](https://github.com/storybookjs/storybook/pull/7081)) +* UPGRADE lazy-universal-dotenv ([#7151](https://github.com/storybookjs/storybook/pull/7151)) +* Make compatible with yarn Pnp ([#6922](https://github.com/storybookjs/storybook/pull/6922)) + +## 5.2.0-alpha.29 (June 17, 2019) + +### Features + +* Addon-notes: enable multiple sections in notes panel ([#6861](https://github.com/storybookjs/storybook/pull/6861)) +* Addon-context: title fallback ([#7078](https://github.com/storybookjs/storybook/pull/7078)) +* Addon-info: Fix rendering of code block ([#6016](https://github.com/storybookjs/storybook/pull/6016)) + +### Bug Fixes + +* Core: Fix JSON babel config error reporting ([#7104](https://github.com/storybookjs/storybook/pull/7104)) +* UI: Fix about page version check message ([#7105](https://github.com/storybookjs/storybook/pull/7105)) + +### Maintenance + +* Core: Refactor story_store ([#6382](https://github.com/storybookjs/storybook/pull/6382)) +* Core: Make compatible with yarn Pnp ([#6922](https://github.com/storybookjs/storybook/pull/6922)) + +### Dependency Upgrades + +* Bump jest-expo from 32.0.1 to 33.0.2 ([#6996](https://github.com/storybookjs/storybook/pull/6996)) + +## 5.2.0-alpha.28 (June 17, 2019) + +Publish failed + +## 5.2.0-alpha.27 (June 17, 2019) + +* CLI: improve bootstrap list ([#6993](https://github.com/storybookjs/storybook/pull/6993)) +* CLI: replaced merge-dirs dependency by fs-extra ([#7100](https://github.com/storybookjs/storybook/pull/7100)) + +## 5.1.8 (June 14, 2019) + +### Bug Fixes + +* CLI: Fix RN template to not import addons ([#7096](https://github.com/storybookjs/storybook/pull/7096)) + +## 5.1.7 (June 14, 2019) + +### Bug Fixes + +* UI: Fix warning of loading prop not being a string ([#7080](https://github.com/storybookjs/storybook/pull/7080)) + +## 5.1.6 (June 14, 2019) + +Publish failed + +## 5.1.5 (June 14, 2019) + +### Bug Fixes + +* Core: Upgrade plugin core-js fix ([#7086](https://github.com/storybookjs/storybook/pull/7086)) +* UI: Fix sidebar loading visibility ([#7073](https://github.com/storybookjs/storybook/pull/7073)) +* UI: Fix unnecessary large bundlesize ([#7091](https://github.com/storybookjs/storybook/pull/7091)) +* Addon-contexts, RN-server: Add core-js dep ([#7094](https://github.com/storybookjs/storybook/pull/7094)) + +## 5.2.0-alpha.26 (June 14, 2019) + +- Merge in changes from 5.1.7/next branch. +- Fix earlier merge problems relating to addon-docs: + - Restore `--docs` command-line functionality + - Fix refreshing docs page bug + +## 5.2.0-alpha.25 (June 14, 2019) + +Publish failed + +## 5.1.4 (June 13, 2019) + +### Bug Fixes + +* Core: Fix core-js 3 errors ([#7051](https://github.com/storybookjs/storybook/pull/7051)) +* UI: Fix syntax highlighter plain text not visible ([#7057](https://github.com/storybookjs/storybook/pull/7057)) +* Addon-actions: Add default options to action(s) ([#6438](https://github.com/storybookjs/storybook/pull/6438)) + +### Dependency Upgrades + +* fix: add missing core-js dependency ([#7016](https://github.com/storybookjs/storybook/pull/7016)) +* chore: set react version to 16.8.3 to match react native ([#7008](https://github.com/storybookjs/storybook/pull/7008)) + +## 5.2.0-alpha.24 (June 13, 2019) + +Merge in changes from 5.1.3/next branch. + +## 5.2.0-alpha.23 (June 10, 2019) + +Merge in changes from 5.1.3/next branch. Releasing from the addon-docs branch to keep things moving until we can merge addon-docs into next. + +## 5.2.0-alpha.22 (June 7, 2019) + +- Merge in changes from 5.1.1 +- Addon-docs: + - Inline stories respect height prop + - Export Description block + +## 5.1.3 (June 6, 2019) + +### Bug Fixes + +* UI: Fix links that are not working with plain left click ([#6970](https://github.com/storybookjs/storybook/pull/6970)) +* Core: Don't redefine `process` variable ([#6991](https://github.com/storybookjs/storybook/pull/6991)) +* Core: Don't mutate user's babel config ([#6987](https://github.com/storybookjs/storybook/pull/6987)) + +## 5.1.2 (June 6, 2019) + +Publish failed + ## 5.1.1 (June 5, 2019) Storybook 5.1 is a juicy upgrade including: @@ -42,6 +227,16 @@ Publish failed * Core: Fix webpack `process.*` variable definitions ([#6946](https://github.com/storybookjs/storybook/pull/6946)) * Angular: Fix tsconfig.app.json detection for Angular 8 ([#6940](https://github.com/storybookjs/storybook/pull/6940)) +## 5.2.0-alpha.21 (June 2, 2019) + +- Core: Convert module format to use default export for metadata +- Addon-docs: Compile MDX to default export modules format +- Source-loader: Support parameter injection for default export metadata + +## 5.2.0-alpha.20 (May 31, 2019) + +- Addon-docs: Use Meta doc block instead of exporting componentMeta + ## 5.1.0-rc.3 (May 29, 2019) ### Features @@ -62,12 +257,46 @@ Publish failed * Bump ts-node from 8.1.0 to 8.2.0 ([#6890](https://github.com/storybookjs/storybook/pull/6890)) * Bump svelte from 3.4.2 to 3.4.4 ([#6892](https://github.com/storybookjs/storybook/pull/6892)) +## 5.2.0-alpha.19 (May 28, 2019) + +- Source-loader: Fix bad package dependencies + ## 5.1.0-rc.2 (May 27, 2019) ### Bug Fixes * Core: Fix JS/JSON loading babel config ([#6878](https://github.com/storybookjs/storybook/pull/6878)) +## 5.2.0-alpha.18 (May 26, 2019) + +- Addon-docs: Codemod for adding component parameters +- Core: Babel config loading bugfix ([#6878](https://github.com/storybookjs/storybook/pull/6878)) + +## 5.2.0-alpha.17 (May 26, 2019) + +- Addon-docs: Refer to selected story/component with `id="."` / `of="."` + +## 5.2.0-alpha.16 (May 25, 2019) + +- Addon-docs: Auto-configure `inlineStories` & `getPropDefs` based on framework + +## 5.2.0-alpha.15 (May 25, 2019) + +- Addon-docs: Expanded Vue support + - Props table support + - iframeHeight configuration parameter + +## 5.2.0-alpha.14 (May 25, 2019) + +- Addon-docs: Expanded source formats via `@storybook/source-loader` + - Legacy `storiesOf` format x (JS / TSX) + - Component modules format x (JS / TSX) + - Component MDX format + +## 5.2.0-alpha.13 (May 24, 2019) + +- Addon-docs: Add documentation-only `--docs` option to build storybook + ## 5.1.0-rc.1 (May 24, 2019) ### Features @@ -122,6 +351,29 @@ Publish failed * Bump svelte from 3.4.1 to 3.4.2 ([#6838](https://github.com/storybookjs/storybook/pull/6838)) * Misc upgrades ([#6820](https://github.com/storybookjs/storybook/pull/6820)) +## 5.2.0-alpha.12 (May 21, 2019) + +- Addon-docs: Fix regression in preview source for legacy stories + +## 5.2.0-alpha.11 (May 21, 2019) + +- Addon-docs: + - Source refer to stories by name + - Source support for multi-story previews + - Fix loader bug for plaintext stories + +## 5.2.0-alpha.10 (May 19, 2019) + +- Addon-docs: Display source dropdown in preview component + +## 5.2.0-alpha.9 (May 17, 2019) + +- Addon-docs bugfixes: + - Fix broken components stories + - Fix regression in iframe preview + - Fix docgen props block + - Fix margin styling on docs page + ## 5.1.0-beta.1 (May 16, 2019) ### Bug Fixes @@ -139,6 +391,49 @@ Publish failed * Bump fs-extra from 7.0.1 to 8.0.1 ([#6776](https://github.com/storybookjs/storybook/pull/6776)) +## 5.2.0-alpha.8 (May 15, 2019) + +- Addon-docs: Optimize docs pane rerendering + +## 5.2.0-alpha.7 (May 15, 2019) + +- Addon-docs: Docs page bugfix +- Addon-docs: Fix source block for legacy stories + +NOTE: use `@storybook/addon-storysource/loader` with option `injectParameters: true` for legacy source + +## 5.2.0-alpha.6 (May 14, 2019) + +- Addon-docs: Docs page content update +- Addon-docs: Preview component redefinition + +#### Breaking changes + +Preview behavior has been updated. Docs page content has been updated. + +Before: + +- `` defines a story, `` references it + +After: + +- `` defines a story, `` references it +- `` shows one or more stories in a grid + +## 5.2.0-alpha.5 (May 12, 2019) + +- Addon-docs: Description block refactor and bugfixes + +## 5.2.0-alpha.4 (May 11, 2019) + +- Addon-docs: Source, Props, DocsPage doc blocks + +#### Breaking changes + +- Doc blocks & presets have moved. Update your MDX stories and `presets.js` file accordingly: + - `import { Preview, Story } from '@storybook/addon-docs/blocks'; + - `module.exports = ['@storybook/addon-docs/common/preset'];` + ## 5.1.0-beta.0 (May 10, 2019) Welcome to the 5.1 beta! Feature development's done; `beta.0` kicks off the stabilization process for the 5.1 final release. ๐Ÿš€ @@ -204,6 +499,25 @@ Failed publish - CLI: Refactor how we install dev dependencies in cli ([#6695](https://github.com/storybookjs/storybook/pull/6695)) +## 5.2.0-alpha.3 (May 1, 2019) + +- Addon-docs: Add Story decorator and parameter support +- Addon-docs: Remove need for extra project babelrc + +## 5.2.0-alpha.2 (April 30, 2019) + +- Addon-docs: Streamline setup, fix MDX dependencies, improve MDX import, and update guide + +## 5.2.0-alpha.0 (April 29, 2019) + +Storybook Docs technical preview: + +- Docs addon +- MDX story format +- Module story format +- Load API +- [Guide](https://docs.google.com/document/d/1un6YX7xDKEKl5-MVb-egnOYN8dynb5Hf7mq0hipk8JE/edit?usp=sharing) + ## 5.0.11 (April 28, 2019) ### Bug Fixes diff --git a/MIGRATION.md b/MIGRATION.md index e768f1ba27e..593bc601f8e 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,5 +1,7 @@ # Migration +- [From version 5.1.x to 5.2.x](#from-version-51x-to-52x) + - [Docs mode docgen](#docs-mode-docgen) - [From version 5.0.x to 5.1.x](#from-version-50x-to-51x) - [React native server](#react-native-server) - [Angular 7](#angular-7) @@ -56,6 +58,15 @@ - [Packages renaming](#packages-renaming) - [Deprecated embedded addons](#deprecated-embedded-addons) +## From version 5.1.x to 5.2.x + +### Docs mode docgen + +This isn't a breaking change per se, because `addon-docs` is a new feature. However it's intended to replace `addon-info`, so if you're migrating from `addon-info` there are a few things you should know: + +1. Support for only one prop table +2. Prop table docgen info should be stored on the component and not in the global variable `STORYBOOK_REACT_CLASSES` as before. + ## From version 5.0.x to 5.1.x ### React native server diff --git a/addons/a11y/package.json b/addons/a11y/package.json index 6462f86c1a8..b7e59233771 100644 --- a/addons/a11y/package.json +++ b/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "a11y addon for storybook", "keywords": [ "a11y", @@ -26,12 +26,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/client-logger": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/client-logger": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "axe-core": "^3.2.2", "common-tags": "^1.8.0", "core-js": "^3.0.1", diff --git a/addons/actions/package.json b/addons/actions/package.json index b13d06ce7f8..eb73971c4b6 100644 --- a/addons/actions/package.json +++ b/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Action Logger addon for storybook", "keywords": [ "storybook" @@ -21,12 +21,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/client-api": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/client-api": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "core-js": "^3.0.1", "fast-deep-equal": "^2.0.1", "global": "^4.3.2", diff --git a/addons/backgrounds/package.json b/addons/backgrounds/package.json index 273d598a0d1..b8ffa4dbaee 100644 --- a/addons/backgrounds/package.json +++ b/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "A storybook addon to show different backgrounds for your preview", "keywords": [ "addon", @@ -25,12 +25,12 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/client-logger": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/client-logger": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "core-js": "^3.0.1", "memoizerific": "^1.11.3", "react": "^16.8.3", diff --git a/addons/centered/package.json b/addons/centered/package.json index da975b3c42a..2201adb31f4 100644 --- a/addons/centered/package.json +++ b/addons/centered/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-centered", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Storybook decorator to center components", "keywords": [ "addon", diff --git a/addons/contexts/package.json b/addons/contexts/package.json index 440d6de19e6..674e665bbc5 100644 --- a/addons/contexts/package.json +++ b/addons/contexts/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-contexts", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Storybook Addon Contexts", "keywords": [ "storybook", @@ -28,10 +28,10 @@ "dev:check-types": "tsc --noEmit" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", "core-js": "^3.0.1" }, "peerDependencies": { diff --git a/addons/cssresources/package.json b/addons/cssresources/package.json index 2acdafdd173..3f427876f14 100644 --- a/addons/cssresources/package.json +++ b/addons/cssresources/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-cssresources", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "A storybook addon to switch between css resources at runtime for your story", "keywords": [ "addon", @@ -25,10 +25,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3" diff --git a/addons/design-assets/package.json b/addons/design-assets/package.json index 659b71f4053..fe792527836 100644 --- a/addons/design-assets/package.json +++ b/addons/design-assets/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-design-assets", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Design asset preview for storybook", "keywords": [ "addon", @@ -11,13 +11,13 @@ "files", "viewer" ], - "homepage": "https://github.com/storybooks/storybook#readme", + "homepage": "https://github.com/storybookjs/storybook#readme", "bugs": { - "url": "https://github.com/storybooks/storybook/issues" + "url": "https://github.com/storybookjs/storybook/issues" }, "repository": { "type": "git", - "url": "git+https://github.com/storybooks/storybook.git", + "url": "git+https://github.com/storybookjs/storybook.git", "directory": "addons/design-assets" }, "license": "MIT", @@ -27,14 +27,14 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/client-logger": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/client-logger": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "common-tags": "^1.8.0", - "core-js": "^2.6.5", + "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3", "use-image": "^1.0.3" diff --git a/addons/docs/README.md b/addons/docs/README.md index 5946e6cc71d..57252453dc0 100644 --- a/addons/docs/README.md +++ b/addons/docs/README.md @@ -1,3 +1,88 @@ # Storybook Docs Living documentation for your components. + +- [Sneak peak article](https://medium.com/storybookjs/storybook-docs-sneak-peak-5be78445094a) +- [Technical preview guide](https://docs.google.com/document/d/1un6YX7xDKEKl5-MVb-egnOYN8dynb5Hf7mq0hipk8JE/edit?usp=sharing) + +## View layer support + +Docs supports all view layers that Storybook supports except for React Native (currently). There are some view-layer specific +features as well. This chart captures the current state of support + +| | React | Vue | Angular | Polymer | Mithril | HTML | Marko | Svelte | Riot | Ember | Preact | +| -------------- | :---: | :-: | :-----: | :-----: | :-----: | :--: | :---: | :----: | :--: | :---: | :----: | +| MDX stories | + | + | + | + | + | + | + | + | + | + | + | +| Module stories | + | + | + | + | + | + | + | + | + | + | + | +| Legacy stories | + | + | + | + | + | + | + | + | + | + | + | +| Source \* | + | + | + | + | + | + | + | + | + | + | + | +| Notes / Info | + | + | + | + | + | + | + | + | + | + | + | +| Props table | + | # | # | | | | | | | | | +| Docgen | + | # | # | | | | | | | | | +| Inline stories | + | # | | | | | | | | | | + +**Notes:** + +- `#` denotes planned/WIP support +- \* Source supports legacy `JS storiesOf` and `MDX` stories. `Typescript` and new `module format` support is WIP + +## Installation + +First add the package. Make sure that the versions for your `@storybook/*` packages match: + +```sh +yarn add -D @storybook/addon-docs +``` + +The add the following line to your `.storybook/presets.js` file: + +```js +module.exports = ['@storybook/addon-docs/react/preset']; +``` + +Finally, import your stories and MDX files in `.storybook/config.js`: + +```js +import { load } from '@storybook/react'; + +// standard configuration here +// ... + +// wherever your story files are located +load(require.context('../src', true, /\.stories\.js$/), module); +load(require.context('../src', true, /\.stories\.mdx$/), module); +``` + +## Manual configuration + +Docs uses Storybook presets as a configuration shortcut. To configure "the long way", first register the addon in `.storybook/addons.js`: + +```js +import '@storybook/addon-docs/register'; +``` + +Then configure Storybook's webpack loader to understand MDX files in `.storybook/webpack.config.js`: + +```js +const createCompiler = require('@storybook/addon-docs/mdx-compiler-plugin'); + +module.exports = async ({ config }) => { + config.module.rules.push({ + test: /\.mdx$/, + use: [ + { + loader: 'babel-loader', + // may or may not need this line depending on your app's setup + plugins: ['@babel/plugin-transform-react-jsx'], + }, + { + loader: '@mdx-js/loader', + options: { + compilers: [createCompiler({})], + }, + }, + ], + }); + return config; +}; +``` diff --git a/addons/docs/__snapshots__/mdx-compiler-plugin.test.js.snap b/addons/docs/__snapshots__/mdx-compiler-plugin.test.js.snap new file mode 100644 index 00000000000..34e98971afb --- /dev/null +++ b/addons/docs/__snapshots__/mdx-compiler-plugin.test.js.snap @@ -0,0 +1,612 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`docs-mdx-compiler-plugin supports "smart" current story 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Story } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + +

{\`Current story\`}

+ +
+ ); +} + +MDXContent.isMDXComponent = true; + +const componentMeta = { includeStories: [] }; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports decorators 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + + ( +
+ {storyFn()} +
+ ), + ]} + mdxType=\\"Meta\\" + /> +

{\`Decorated story\`}

+ + + +
+ ); +} + +MDXContent.isMDXComponent = true; + +export const one = () => ; +one.story = {}; +one.story.parameters = { mdxSource: \`\` }; + +const componentMeta = { + title: 'Button', + decorators: [ + storyFn => ( +
+ {storyFn()} +
+ ), + ], + includeStories: ['one'], +}; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports non-story exports 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; +export const two = 2; +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = { + two, +}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + + +

{\`Story definition\`}

+ + + + + + + +
+ ); +} + +MDXContent.isMDXComponent = true; + +export const one = () => ; +one.story = {}; +one.story.parameters = { mdxSource: \`\` }; + +export const helloStory = () => ; +helloStory.story = {}; +helloStory.story.name = 'hello story'; +helloStory.story.parameters = { mdxSource: \`\` }; + +const componentMeta = { title: 'Button', includeStories: ['one', 'helloStory'] }; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports object-style story definitions 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Story, Meta } from '@storybook/addon-docs/blocks'; +import { Welcome, Button } from '@storybook/angular/demo'; +import { linkTo } from '@storybook/addon-links'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + + +

{\`Story object\`}

+ + {{ + template: \`\`, + props: { + showApp: linkTo('Button'), + }, + moduleMetadata: { + declarations: [Welcome], + }, + }} + +
+ ); +} + +MDXContent.isMDXComponent = true; + +export const toStorybook = () => ({ + template: \`\`, + props: { + showApp: linkTo('Button'), + }, + moduleMetadata: { + declarations: [Welcome], + }, +}); +toStorybook.story = {}; +toStorybook.story.name = 'to storybook'; +toStorybook.story.parameters = { + mdxSource: \`{ + template: \\\\\`\\\\\`, + props: { + showApp: linkTo('Button') + }, + moduleMetadata: { + declarations: [Welcome] + } +}\`, +}; + +const componentMeta = { title: 'MDX|Welcome', includeStories: ['toStorybook'] }; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports parameters 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + + + + + + + + + + ); +} + +MDXContent.isMDXComponent = true; + +export const componentNotes = () => ; +componentNotes.story = {}; +componentNotes.story.name = 'component notes'; +componentNotes.story.parameters = { mdxSource: \`\` }; + +export const storyNotes = () => ; +storyNotes.story = {}; +storyNotes.story.name = 'story notes'; +storyNotes.story.parameters = { + mdxSource: \`\`, + ...{ + notes: 'story notes', + }, +}; + +const componentMeta = { + title: 'Button', + parameters: { + component: Button, + notes: 'component notes', + }, + includeStories: ['componentNotes', 'storyNotes'], +}; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports previews 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Preview, Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + + +

{\`Preview\`}

+

{\`Previews can contain normal components, stories, and story references\`}

+ + + + + + + + + + +
+ ); +} + +MDXContent.isMDXComponent = true; + +export const helloButton = () => ; +helloButton.story = {}; +helloButton.story.name = 'hello button'; +helloButton.story.parameters = { mdxSource: \`\` }; + +export const two = () => ; +two.story = {}; +two.story.parameters = { mdxSource: \`\` }; + +const componentMeta = { + title: 'Button', + parameters: { + component: Button, + notes: 'component notes', + }, + includeStories: ['helloButton', 'two'], +}; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports story definitions 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + + +

{\`Story definition\`}

+ + + + + + +
+ ); +} + +MDXContent.isMDXComponent = true; + +export const one = () => ; +one.story = {}; +one.story.parameters = { mdxSource: \`\` }; + +export const helloStory = () => ; +helloStory.story = {}; +helloStory.story.name = 'hello story'; +helloStory.story.parameters = { mdxSource: \`\` }; + +const componentMeta = { title: 'Button', includeStories: ['one', 'helloStory'] }; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports story references 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Story } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + +

{\`Story reference\`}

+ +
+ ); +} + +MDXContent.isMDXComponent = true; + +const componentMeta = { includeStories: [] }; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports text-only story definitions 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + + +

{\`Story definition\`}

+ + Plain text + +
+ ); +} + +MDXContent.isMDXComponent = true; + +export const text = () => 'Plain text'; +text.story = {}; +text.story.parameters = { mdxSource: \`'Plain text'\` }; + +const componentMeta = { title: 'Text', includeStories: ['text'] }; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; + +exports[`docs-mdx-compiler-plugin supports vanilla mdx 1`] = ` +"/* @jsx mdx */ +import { DocsContainer } from '@storybook/addon-docs/blocks'; + +import { Button } from '@storybook/react/demo'; + +const makeShortcode = name => + function MDXDefaultShortcode(props) { + console.warn( + 'Component ' + + name + + ' was not imported, exported, or provided by MDXProvider as global scope' + ); + return
; + }; + +const layoutProps = {}; +const MDXLayout = 'wrapper'; +function MDXContent({ components, ...props }) { + return ( + +

{\`Hello MDX\`}

+

{\`This is some random content.\`}

+ +
+ ); +} + +MDXContent.isMDXComponent = true; + +const componentMeta = { includeStories: [] }; + +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ( + +); +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; + +export default componentMeta; +" +`; diff --git a/addons/docs/blocks.js b/addons/docs/blocks.js new file mode 100644 index 00000000000..6f65c051a90 --- /dev/null +++ b/addons/docs/blocks.js @@ -0,0 +1 @@ +module.exports = require('./dist/blocks'); diff --git a/addons/docs/common/index.js b/addons/docs/common/index.js new file mode 100644 index 00000000000..ab2313695b6 --- /dev/null +++ b/addons/docs/common/index.js @@ -0,0 +1,2 @@ +// FIXME: move this to typescript and src/react folder +module.exports = require('../dist/lib/getPropDefs'); diff --git a/addons/docs/common/preset.js b/addons/docs/common/preset.js new file mode 100644 index 00000000000..3831a573b20 --- /dev/null +++ b/addons/docs/common/preset.js @@ -0,0 +1,66 @@ +const createCompiler = require('../mdx-compiler-plugin'); + +function createBabelOptions({ babelOptions, configureJSX }) { + if (!configureJSX) { + return babelOptions; + } + + return { + ...babelOptions, + // for frameworks that are not working with react, we need to configure + // the jsx to transpile mdx, for now there will be a flag for that + // for more complex solutions we can find alone that we need to add '@babel/plugin-transform-react-jsx' + plugins: [...babelOptions.plugins, '@babel/plugin-transform-react-jsx'], + }; +} + +function webpack(webpackConfig = {}, options = {}) { + const { module = {} } = webpackConfig; + // it will reuse babel options that are already in use in storybook + // also, these babel options are chained with other presets. + const { babelOptions, configureJSX } = options; + + return { + ...webpackConfig, + module: { + ...module, + rules: [ + ...(module.rules || []), + { + test: /\.(stories|story).mdx$/, + use: [ + { + loader: 'babel-loader', + options: createBabelOptions({ babelOptions, configureJSX }), + }, + { + loader: '@mdx-js/loader', + options: { + compilers: [createCompiler(options)], + }, + }, + ], + }, + { + test: /\.mdx$/, + exclude: /\.(stories|story).mdx$/, + use: [ + { + loader: 'babel-loader', + options: createBabelOptions({ babelOptions, configureJSX }), + }, + { + loader: '@mdx-js/loader', + }, + ], + }, + ], + }, + }; +} + +function addons(entry = []) { + return [...entry, require.resolve('../register')]; +} + +module.exports = { webpack, addons }; diff --git a/addons/docs/fixtures/decorators.mdx b/addons/docs/fixtures/decorators.mdx new file mode 100644 index 00000000000..2f4e84e6ded --- /dev/null +++ b/addons/docs/fixtures/decorators.mdx @@ -0,0 +1,13 @@ +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + +
{storyFn()}
]} +/> + +# Decorated story + + + + diff --git a/addons/docs/fixtures/non-story-exports.mdx b/addons/docs/fixtures/non-story-exports.mdx new file mode 100644 index 00000000000..833dd03c138 --- /dev/null +++ b/addons/docs/fixtures/non-story-exports.mdx @@ -0,0 +1,16 @@ +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + + + +# Story definition + + + + + +export const two = 2; + + + + diff --git a/addons/docs/fixtures/parameters.mdx b/addons/docs/fixtures/parameters.mdx new file mode 100644 index 00000000000..0805466b38c --- /dev/null +++ b/addons/docs/fixtures/parameters.mdx @@ -0,0 +1,12 @@ +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + + + + + + + + + + diff --git a/addons/docs/fixtures/previews.mdx b/addons/docs/fixtures/previews.mdx new file mode 100644 index 00000000000..80601eed2ed --- /dev/null +++ b/addons/docs/fixtures/previews.mdx @@ -0,0 +1,19 @@ +import { Button } from '@storybook/react/demo'; +import { Preview, Story, Meta } from '@storybook/addon-docs/blocks'; + + + +# Preview + +Previews can contain normal components, stories, and story references + + + + + + + + + + + diff --git a/addons/docs/fixtures/story-current.mdx b/addons/docs/fixtures/story-current.mdx new file mode 100644 index 00000000000..d5b62cc6eda --- /dev/null +++ b/addons/docs/fixtures/story-current.mdx @@ -0,0 +1,5 @@ +import { Story } from '@storybook/addon-docs/blocks'; + +# Current story + + diff --git a/addons/docs/fixtures/story-def-text-only.mdx b/addons/docs/fixtures/story-def-text-only.mdx new file mode 100644 index 00000000000..78ebd50215e --- /dev/null +++ b/addons/docs/fixtures/story-def-text-only.mdx @@ -0,0 +1,7 @@ +import { Story, Meta } from '@storybook/addon-docs/blocks'; + + + +# Story definition + +Plain text diff --git a/addons/docs/fixtures/story-definitions.mdx b/addons/docs/fixtures/story-definitions.mdx new file mode 100644 index 00000000000..ee5c355b989 --- /dev/null +++ b/addons/docs/fixtures/story-definitions.mdx @@ -0,0 +1,14 @@ +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + + + +# Story definition + + + + + + + + diff --git a/addons/docs/fixtures/story-missing-props.mdx b/addons/docs/fixtures/story-missing-props.mdx new file mode 100644 index 00000000000..0eb3137a975 --- /dev/null +++ b/addons/docs/fixtures/story-missing-props.mdx @@ -0,0 +1,10 @@ +import { Button } from '@storybook/react/demo'; +import { Story, Meta } from '@storybook/addon-docs/blocks'; + + + +# Bad story + + + + diff --git a/addons/docs/fixtures/story-object.mdx b/addons/docs/fixtures/story-object.mdx new file mode 100644 index 00000000000..e63d4892384 --- /dev/null +++ b/addons/docs/fixtures/story-object.mdx @@ -0,0 +1,19 @@ +import { Story, Meta } from '@storybook/addon-docs/blocks'; +import { Welcome, Button } from '@storybook/angular/demo'; +import { linkTo } from '@storybook/addon-links'; + + + +# Story object + + + {{ + template: ``, + props: { + showApp: linkTo('Button'), + }, + moduleMetadata: { + declarations: [Welcome], + }, + }} + diff --git a/addons/docs/fixtures/story-references.mdx b/addons/docs/fixtures/story-references.mdx new file mode 100644 index 00000000000..865bd5dea49 --- /dev/null +++ b/addons/docs/fixtures/story-references.mdx @@ -0,0 +1,5 @@ +import { Story } from '@storybook/addon-docs/blocks'; + +# Story reference + + diff --git a/addons/docs/fixtures/vanilla.mdx b/addons/docs/fixtures/vanilla.mdx new file mode 100644 index 00000000000..93ccac3d6bc --- /dev/null +++ b/addons/docs/fixtures/vanilla.mdx @@ -0,0 +1,7 @@ +import { Button } from '@storybook/react/demo'; + +# Hello MDX + +This is some random content. + + diff --git a/addons/docs/mdx-compiler-plugin.js b/addons/docs/mdx-compiler-plugin.js new file mode 100644 index 00000000000..c5586977381 --- /dev/null +++ b/addons/docs/mdx-compiler-plugin.js @@ -0,0 +1,222 @@ +const mdxToJsx = require('@mdx-js/mdx/mdx-hast-to-jsx'); +const parser = require('@babel/parser'); +const generate = require('@babel/generator').default; +const camelCase = require('lodash/camelCase'); + +// Generate the MDX as is, but append named exports for every +// story in the contents + +const STORY_REGEX = /^]/; +const PREVIEW_REGEX = /^]/; +const META_REGEX = /^]/; +const RESERVED = /^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|await|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$/; + +function getAttr(elt, what) { + const attr = elt.attributes.find(n => n.name.name === what); + return attr && attr.value; +} + +function getStoryFn(name, counter) { + if (name) { + const storyFn = camelCase(name.replace(/[^a-z0-9-]/g, '-')); + if (storyFn.length > 1 && !RESERVED.exec(storyFn)) { + return storyFn; + } + } + return `story${counter}`; +} + +function genStoryExport(ast, counter) { + let storyName = getAttr(ast.openingElement, 'name'); + let storyId = getAttr(ast.openingElement, 'id'); + storyName = storyName && storyName.value; + storyId = storyId && storyId.value; + + if (!storyId && !storyName) { + throw new Error('Expected a story name or ID attribute'); + } + + // We don't generate exports for story references or the smart "current story" + if (storyId || !storyName) { + return null; + } + + // console.log('genStoryExport', JSON.stringify(ast, null, 2)); + + const statements = []; + const storyKey = getStoryFn(storyName, counter); + + let body = ast.children.find(n => n.type !== 'JSXText'); + let storyCode = null; + if (!body) { + // plain text node + const { code } = generate(ast.children[0], {}); + storyCode = `'${code}'`; + } else { + if (body.type === 'JSXExpressionContainer') { + // FIXME: handle fragments + body = body.expression; + } + const { code } = generate(body, {}); + storyCode = code; + } + statements.push( + `export const ${storyKey} = () => ( + ${storyCode} + );` + ); + statements.push(`${storyKey}.story = {};`); + + if (storyName !== storyKey) { + statements.push(`${storyKey}.story.name = '${storyName}';`); + } + + let parameters = getAttr(ast.openingElement, 'parameters'); + parameters = parameters && parameters.expression; + const source = `\`${storyCode.replace(/`/g, '\\`')}\``; + if (parameters) { + const { code: params } = generate(parameters, {}); + // FIXME: hack in the story's source as a parameter + statements.push(`${storyKey}.story.parameters = { mdxSource: ${source}, ...${params} };`); + } else { + statements.push(`${storyKey}.story.parameters = { mdxSource: ${source} };`); + } + + // console.log(statements); + + return { + [storyKey]: statements.join('\n'), + }; +} + +function genPreviewExports(ast, counter) { + // console.log('genPreviewExports', JSON.stringify(ast, null, 2)); + + let localCounter = counter; + const previewExports = {}; + for (let i = 0; i < ast.children.length; i += 1) { + const child = ast.children[i]; + if (child.type === 'JSXElement' && child.openingElement.name.name === 'Story') { + const storyExport = genStoryExport(child, localCounter); + if (storyExport) { + Object.assign(previewExports, storyExport); + localCounter += 1; + } + } + } + return previewExports; +} + +function genMeta(ast) { + let title = getAttr(ast.openingElement, 'title'); + let parameters = getAttr(ast.openingElement, 'parameters'); + let decorators = getAttr(ast.openingElement, 'decorators'); + title = title && `'${title.value}'`; + if (parameters && parameters.expression) { + const { code: params } = generate(parameters.expression, {}); + parameters = params; + } + if (decorators && decorators.expression) { + const { code: decos } = generate(decorators.expression, {}); + decorators = decos; + } + return { + title, + parameters, + decorators, + }; +} + +function getExports(node, counter) { + const { value, type } = node; + if (type === 'jsx') { + if (STORY_REGEX.exec(value)) { + // Single story + const ast = parser.parseExpression(value, { plugins: ['jsx'] }); + const storyExport = genStoryExport(ast, counter); + return storyExport && { stories: storyExport }; + } + if (PREVIEW_REGEX.exec(value)) { + // Preview, possibly containing multiple stories + const ast = parser.parseExpression(value, { plugins: ['jsx'] }); + return { stories: genPreviewExports(ast, counter) }; + } + if (META_REGEX.exec(value)) { + // Preview, possibly containing multiple stories + const ast = parser.parseExpression(value, { plugins: ['jsx'] }); + return { meta: genMeta(ast) }; + } + } + return null; +} + +// insert `mdxKind` into the context so that we can know what "kind" we're rendering into +// when we render ..., since this MDX can be attached to any `selectedKind`! +const wrapperJs = ` +const mdxKind = componentMeta.title || componentMeta.displayName; +const WrappedMDXContent = ({ context }) => ; +componentMeta.parameters = componentMeta.parameters || {}; +componentMeta.parameters.docs = WrappedMDXContent; +`.trim(); + +function stringifyMeta(meta) { + let result = '{ '; + Object.entries(meta).forEach(([key, val]) => { + if (val) { + result += `${key}: ${val}, `; + } + }); + result += ' }'; + return result; +} + +function extractExports(node, options) { + // we're overriding default export + const defaultJsx = mdxToJsx.toJSX(node, {}, { ...options, skipExport: true }); + const storyExports = []; + const includeStories = []; + let metaExport = null; + let counter = 0; + node.children.forEach(n => { + const exports = getExports(n, counter); + if (exports) { + const { stories, meta } = exports; + if (stories) { + Object.entries(stories).forEach(([key, story]) => { + includeStories.push(key); + storyExports.push(story); + counter += 1; + }); + } + if (meta) { + if (metaExport) { + throw new Error('Meta can only be declared once'); + } + metaExport = meta; + } + } + }); + if (!metaExport) { + metaExport = {}; + } + metaExport.includeStories = JSON.stringify(includeStories); + + const fullJsx = [ + 'import { DocsContainer } from "@storybook/addon-docs/blocks";', + defaultJsx, + ...storyExports, + `const componentMeta = ${stringifyMeta(metaExport)};`, + wrapperJs, + 'export default componentMeta;', + ].join('\n\n'); + + return fullJsx; +} + +function createCompiler(mdxOptions) { + return function compiler(options = {}) { + this.Compiler = tree => extractExports(tree, options, mdxOptions); + }; +} + +module.exports = createCompiler; diff --git a/addons/docs/mdx-compiler-plugin.test.js b/addons/docs/mdx-compiler-plugin.test.js new file mode 100644 index 00000000000..75e8cc03dba --- /dev/null +++ b/addons/docs/mdx-compiler-plugin.test.js @@ -0,0 +1,75 @@ +const path = require('path'); +const fs = require('fs-extra'); +const mdx = require('@mdx-js/mdx'); +const prettier = require('prettier'); +const plugin = require('./mdx-compiler-plugin'); + +function format(code) { + return prettier.format(code, { + parser: 'babel', + printWidth: 100, + tabWidth: 2, + bracketSpacing: true, + trailingComma: 'es5', + singleQuote: true, + }); +} + +async function generate(filePath) { + const content = await fs.readFile(filePath, 'utf8'); + + const result = mdx.sync(content, { + filepath: filePath, + compilers: [plugin({})], + }); + + return format(result); +} + +describe('docs-mdx-compiler-plugin', () => { + it('supports vanilla mdx', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/vanilla.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports story definitions', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/story-definitions.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports text-only story definitions', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/story-def-text-only.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports object-style story definitions', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/story-object.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports story references', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/story-references.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports "smart" current story', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/story-current.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports previews', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/previews.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports decorators', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/decorators.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports parameters', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/parameters.mdx')); + expect(code).toMatchSnapshot(); + }); + it('supports non-story exports', async () => { + const code = await generate(path.resolve(__dirname, './fixtures/non-story-exports.mdx')); + expect(code).toMatchSnapshot(); + }); + it('errors on missing story props', async () => { + await expect( + generate(path.resolve(__dirname, './fixtures/story-missing-props.mdx')) + ).rejects.toThrow('Expected a story name or ID attribute'); + }); +}); diff --git a/addons/docs/package.json b/addons/docs/package.json index 9ad9a19606b..0632f85aa66 100644 --- a/addons/docs/package.json +++ b/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Superior documentation for your components", "keywords": [ "addon", @@ -23,10 +23,23 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23" + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.2", + "@mdx-js/loader": "^1.0.0", + "@mdx-js/mdx": "^1.0.0", + "@mdx-js/react": "^1.0.16", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/router": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", + "core-js": "^3.0.1", + "global": "^4.3.2", + "lodash": "^4.17.11", + "prop-types": "^15.7.2" }, "devDependencies": { + "@types/prop-types": "^15.5.9", "@types/util-deprecate": "^1.0.0", "@types/webpack-env": "^1.13.7" }, diff --git a/addons/docs/react/index.js b/addons/docs/react/index.js new file mode 100644 index 00000000000..38c1756201b --- /dev/null +++ b/addons/docs/react/index.js @@ -0,0 +1 @@ +module.exports = require('../common/index'); diff --git a/addons/docs/react/preset.js b/addons/docs/react/preset.js new file mode 100644 index 00000000000..a9b8af2cce0 --- /dev/null +++ b/addons/docs/react/preset.js @@ -0,0 +1 @@ +module.exports = require('../common/preset'); diff --git a/addons/docs/src/blocks/Description.tsx b/addons/docs/src/blocks/Description.tsx new file mode 100644 index 00000000000..e12a1ea5f9f --- /dev/null +++ b/addons/docs/src/blocks/Description.tsx @@ -0,0 +1,68 @@ +/* eslint-disable no-underscore-dangle */ +import React from 'react'; +import { Description, DescriptionProps as PureDescriptionProps } from '@storybook/components'; +import { DocsContext, DocsContextProps } from './DocsContext'; +import { Component, CURRENT_SELECTION } from './shared'; + +export enum DescriptionType { + INFO = 'info', + NOTES = 'notes', + DOCGEN = 'docgen', + AUTO = 'auto', +} + +type Notes = string | any; +type Info = string | any; + +interface DescriptionProps { + of?: '.' | Component; + type?: DescriptionType; + markdown?: string; +} + +const getNotes = (notes?: Notes) => + notes && (typeof notes === 'string' ? notes : notes.markdown || notes.text); + +const getInfo = (info?: Info) => info && (typeof info === 'string' ? info : info.text); + +const getDocgen = (component?: Component) => + (component && component.__docgenInfo && component.__docgenInfo.description) || ''; + +export const getDescriptionProps = ( + { of, type, markdown }: DescriptionProps, + { parameters }: DocsContextProps +): PureDescriptionProps => { + if (markdown) { + return { markdown }; + } + const { component, notes, info } = parameters; + const target = of === CURRENT_SELECTION ? component : of; + switch (type) { + case DescriptionType.INFO: + return { markdown: getInfo(info) }; + case DescriptionType.NOTES: + return { markdown: getNotes(notes) }; + case DescriptionType.DOCGEN: + return { markdown: getDocgen(target) }; + case DescriptionType.AUTO: + default: + return { + markdown: ` +${getNotes(notes) || getInfo(info) || ''} + +${getDocgen(target)} +`.trim(), + }; + } +}; + +const DescriptionContainer: React.FunctionComponent = props => ( + + {context => { + const { markdown } = getDescriptionProps(props, context); + return markdown && ; + }} + +); + +export { DescriptionContainer as Description }; diff --git a/addons/docs/src/blocks/DocsContainer.tsx b/addons/docs/src/blocks/DocsContainer.tsx new file mode 100644 index 00000000000..1e829cbbfbd --- /dev/null +++ b/addons/docs/src/blocks/DocsContainer.tsx @@ -0,0 +1,52 @@ +/* eslint-disable react/destructuring-assignment */ + +import React from 'react'; +import { MDXProvider } from '@mdx-js/react'; +import { Global, createGlobal, ThemeProvider, ensure as ensureTheme } from '@storybook/theming'; +import { DocumentFormatting, DocsWrapper, DocsContent } from '@storybook/components'; +import { DocsContextProps, DocsContext } from './DocsContext'; + +interface DocsContainerProps { + context: DocsContextProps; + content: React.ElementType; +} + +const defaultComponents = { + // p: ({ children }) => {children}, + wrapper: DocumentFormatting, +}; + +const globalWithOverflow = (args: any) => { + const global = createGlobal(args); + const { body, ...rest } = global; + const { overflow, ...bodyRest } = body; + return { + body: bodyRest, + ...rest, + }; +}; + +export const DocsContainer: React.FunctionComponent = ({ + context, + content: MDXContent, +}) => { + const parameters = (context && context.parameters) || {}; + const options = parameters.options || {}; + const theme = ensureTheme(options.theme); + const { components: userComponents = null } = options.docs || {}; + const components = { ...defaultComponents, ...userComponents }; + return ( + + + + + + + + + + + + + ); +}; diff --git a/addons/docs/src/blocks/DocsContext.ts b/addons/docs/src/blocks/DocsContext.ts new file mode 100644 index 00000000000..26efed04813 --- /dev/null +++ b/addons/docs/src/blocks/DocsContext.ts @@ -0,0 +1,23 @@ +import React from 'react'; + +export interface DocsContextProps { + id?: string; + selectedKind?: string; + selectedStory?: string; + + /** + * mdxKind is a statically-generated "kind" that corresponds to the + * component that's being documented in the MDX file, It's combined + * with the MDX story name `...` to + * generate a storyId. In the case that the user is viewing a non-MDX + * story, the value of `mdxKind` will be the currently-selected kind. + * (I can't remember the corner case in which using the currentl-selected + * kind breaks down in MDX-defined stories, but there is one!) + */ + mdxKind?: string; + parameters?: any; + storyStore?: any; + forceRender?: () => void; +} + +export const DocsContext: React.Context = React.createContext({}); diff --git a/addons/docs/src/blocks/DocsPage.tsx b/addons/docs/src/blocks/DocsPage.tsx new file mode 100644 index 00000000000..8d3c3944784 --- /dev/null +++ b/addons/docs/src/blocks/DocsPage.tsx @@ -0,0 +1,140 @@ +import React from 'react'; + +import { parseKind } from '@storybook/router'; +import { styled } from '@storybook/theming'; +import { DocsPage as PureDocsPage, DocsPageProps } from '@storybook/components'; +import { DocsContext, DocsContextProps } from './DocsContext'; +import { DocsContainer } from './DocsContainer'; +import { Description } from './Description'; +import { Story } from './Story'; +import { Preview } from './Preview'; +import { Props } from './Props'; + +enum DocsStoriesType { + ALL = 'all', + PRIMARY = 'primary', + REST = 'rest', +} + +interface DocsStoriesProps { + type?: DocsStoriesType; +} + +interface DocsStoryProps { + id: string; + name: string; + description?: string; + expanded?: boolean; +} + +interface StoryData { + id: string; + kind: string; + name: string; + parameters?: any; +} + +const getDocsStories = (type: DocsStoriesType, componentStories: StoryData[]): DocsStoryProps[] => { + let stories = componentStories; + if (type !== DocsStoriesType.ALL) { + const primary = stories.find(s => s.parameters && s.parameters.primary); + const [first, ...rest] = stories; + if (type === DocsStoriesType.PRIMARY) { + stories = [primary || first]; + } else { + stories = primary ? stories.filter(s => !s.parameters || !s.parameters.primary) : rest; + } + } + return stories.map(({ id, name, parameters: { notes, info } }) => ({ + id, + name, + description: notes || info || null, + })); +}; + +const StoriesHeading = styled.h2(); +const StoryHeading = styled.h3(); + +const DocsStory: React.FunctionComponent = ({ + id, + name, + description, + expanded = true, +}) => ( + <> + {expanded && {name}} + {expanded && description && } + + + + +); + +const DocsStories: React.FunctionComponent = ({ type = DocsStoriesType.ALL }) => ( + + {({ selectedKind, storyStore }) => { + const componentStories = (storyStore.raw() as StoryData[]).filter( + s => s.kind === selectedKind + ); + const stories = getDocsStories(type, componentStories); + if (stories.length === 0) { + return null; + } + const expanded = type !== DocsStoriesType.PRIMARY; + return ( + <> + {expanded && Stories} + {stories.map(s => ( + + ))} + + ); + }} + +); + +const getDocsPageProps = (context: DocsContextProps): DocsPageProps => { + const { selectedKind, selectedStory, parameters } = context; + const { + hierarchyRootSeparator: rootSeparator, + hierarchySeparator: groupSeparator, + } = (parameters && parameters.options) || { + hierarchyRootSeparator: '|', + hierarchySeparator: '/', + }; + + const { groups } = parseKind(selectedKind, { rootSeparator, groupSeparator }); + const title = (groups && groups[groups.length - 1]) || selectedKind; + + return { + title, + subtitle: parameters && parameters.componentDescription, + }; +}; + +const DocsPage: React.FunctionComponent = () => ( + + {context => { + const docsPageProps = getDocsPageProps(context); + return ( + + + + + + + ); + }} + +); + +interface DocsPageWrapperProps { + context: DocsContextProps; +} + +const DocsPageWrapper: React.FunctionComponent = ({ context }) => ( + /* eslint-disable react/destructuring-assignment */ + +); + +export { DocsPageWrapper as DocsPage }; diff --git a/addons/docs/src/blocks/Meta.tsx b/addons/docs/src/blocks/Meta.tsx new file mode 100644 index 00000000000..5308f9f0ea9 --- /dev/null +++ b/addons/docs/src/blocks/Meta.tsx @@ -0,0 +1,16 @@ +import React from 'react'; + +type Decorator = (...args: any) => any; + +interface MetaProps { + title: string; + decorators?: [Decorator]; + parameters?: any; +} + +/** + * This component is used to declare component metadata in docs + * and gets transformed into a default export underneath the hood. + * It doesn't actually render anything. + */ +export const Meta: React.FunctionComponent = props => null; diff --git a/addons/docs/src/blocks/Preview.tsx b/addons/docs/src/blocks/Preview.tsx new file mode 100644 index 00000000000..bc18d47405c --- /dev/null +++ b/addons/docs/src/blocks/Preview.tsx @@ -0,0 +1,48 @@ +import React, { ReactNodeArray } from 'react'; +import { Preview as PurePreview, PreviewProps as PurePreviewProps } from '@storybook/components'; +import { toId } from '@storybook/router'; +import { getSourceProps } from './Source'; +import { DocsContext, DocsContextProps } from './DocsContext'; + +export enum SourceState { + OPEN = 'open', + CLOSED = 'closed', + NONE = 'none', +} + +type PreviewProps = PurePreviewProps & { + withSource?: SourceState; +}; + +const getPreviewProps = ( + { + withSource = SourceState.CLOSED, + children, + ...props + }: PreviewProps & { children?: React.ReactNode }, + { mdxKind, storyStore }: DocsContextProps +): PurePreviewProps => { + if (withSource === SourceState.NONE && !children) { + return props; + } + const childArray: ReactNodeArray = Array.isArray(children) ? children : [children]; + const stories = childArray.filter( + (c: React.ReactElement) => c.props && (c.props.id || c.props.name) + ) as React.ReactElement[]; + const targetIds = stories.map(s => s.props.id || toId(mdxKind, s.props.name)); + const sourceProps = getSourceProps({ ids: targetIds }, { storyStore }); + return { + ...props, // pass through columns etc. + withSource: sourceProps, + isExpanded: withSource === SourceState.OPEN, + }; +}; + +export const Preview: React.FunctionComponent = props => ( + + {context => { + const previewProps = getPreviewProps(props, context); + return {props.children}; + }} + +); diff --git a/addons/docs/src/blocks/Props.tsx b/addons/docs/src/blocks/Props.tsx new file mode 100644 index 00000000000..53b396cdbc1 --- /dev/null +++ b/addons/docs/src/blocks/Props.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { PropsTable, PropsTableError, PropsTableProps, PropDef } from '@storybook/components'; +import { DocsContext, DocsContextProps } from './DocsContext'; +import { Component, CURRENT_SELECTION } from './shared'; +import { getPropDefs as autoPropDefs, PropDefGetter } from '../lib/getPropDefs'; + +interface PropsProps { + exclude?: string[]; + of: '.' | Component; +} + +const inferPropDefs = (framework: string): PropDefGetter | null => { + switch (framework) { + case 'react': + case 'vue': + return autoPropDefs; + default: + return null; + } +}; + +export const getPropsTableProps = ( + { exclude, of }: PropsProps, + { parameters }: DocsContextProps +): PropsTableProps => { + const { component } = parameters; + try { + const target = of === CURRENT_SELECTION ? component : of; + if (!target) { + throw new Error(PropsTableError.NO_COMPONENT); + } + + const { framework = null } = parameters || {}; + const { getPropDefs = inferPropDefs(framework) } = + (parameters && parameters.options && parameters.options.docs) || {}; + + if (!getPropDefs) { + throw new Error(PropsTableError.PROPS_UNSUPPORTED); + } + const allRows = getPropDefs(target); + const rows = !exclude ? allRows : allRows.filter((row: PropDef) => !exclude.includes(row.name)); + return { rows }; + } catch (err) { + return { error: err.message }; + } +}; + +const PropsContainer: React.FunctionComponent = props => ( + + {context => { + const propsTableProps = getPropsTableProps(props, context); + return ; + }} + +); + +export { PropsContainer as Props }; diff --git a/addons/docs/src/blocks/Source.tsx b/addons/docs/src/blocks/Source.tsx new file mode 100644 index 00000000000..8ba904787f7 --- /dev/null +++ b/addons/docs/src/blocks/Source.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { Source, SourceProps as PureSourceProps, SourceError } from '@storybook/components'; +import { DocsContext, DocsContextProps } from './DocsContext'; +import { CURRENT_SELECTION } from './shared'; + +interface CommonProps { + language?: string; +} + +type SingleSourceProps = { + id: string; +} & CommonProps; + +type MultiSourceProps = { + ids: string[]; +} & CommonProps; + +type CodeProps = { + code: string; +} & CommonProps; + +type NoneProps = CommonProps; + +type SourceProps = SingleSourceProps | MultiSourceProps | CodeProps | NoneProps; + +interface Location { + line: number; + col: number; +} + +interface StorySource { + source: string; + locationsMap: { [id: string]: { startBody: Location; endBody: Location } }; +} + +const extract = (targetId: string, { source, locationsMap }: StorySource) => { + 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) { + 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]; + return [ + startLine.substring(start.col), + ...lines.slice(start.line, end.line - 1), + endLine.substring(0, end.col), + ].join('\n'); +}; + +export const getSourceProps = ( + props: SourceProps, + { id: currentId, storyStore }: DocsContextProps +): PureSourceProps => { + const codeProps = props as CodeProps; + const singleProps = props as SingleSourceProps; + const multiProps = props as MultiSourceProps; + + let source = codeProps.code; // prefer user-specified code + if (!source) { + const targetId = singleProps.id === CURRENT_SELECTION ? currentId : singleProps.id; + const targetIds = multiProps.ids || [targetId]; + source = targetIds + .map(sourceId => { + const data = storyStore.fromId(sourceId); + if (data && data.parameters) { + const { mdxSource, storySource } = data.parameters; + return mdxSource || (storySource && extract(sourceId, storySource)); + } + return ''; + }) + .join('\n\n'); + } + return source + ? { code: source, language: props.language || 'jsx' } + : { error: SourceError.SOURCE_UNAVAILABLE }; +}; + +/** + * Story source doc block renders source code if provided, + * or the source for a story if `storyId` is provided, or + * the source for the current story if nothing is provided. + */ +const SourceContainer: React.FunctionComponent = props => ( + + {context => { + const sourceProps = getSourceProps(props, context); + return ; + }} + +); + +export { SourceContainer as Source }; diff --git a/addons/docs/src/blocks/Story.tsx b/addons/docs/src/blocks/Story.tsx new file mode 100644 index 00000000000..7fde8e353b3 --- /dev/null +++ b/addons/docs/src/blocks/Story.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { toId } from '@storybook/router'; +import { Story, StoryProps as PureStoryProps } from '@storybook/components'; +import { CURRENT_SELECTION } from './shared'; + +import { DocsContext, DocsContextProps } from './DocsContext'; + +interface CommonProps { + height?: string; +} + +type StoryDefProps = { + name: string; + children: React.ReactNode; +} & CommonProps; + +type StoryRefProps = { + id?: string; +} & CommonProps; + +export type StoryProps = StoryDefProps | StoryRefProps; + +const inferInlineStories = (framework: string): boolean => { + switch (framework) { + case 'react': + return true; + default: + return false; + } +}; + +export const getStoryProps = ( + props: StoryProps, + { id: currentId, storyStore, parameters, mdxKind }: DocsContextProps +): PureStoryProps => { + const { id } = props as StoryRefProps; + const { name } = props as StoryDefProps; + const inputId = id === CURRENT_SELECTION ? currentId : id; + const previewId = inputId || toId(mdxKind, name); + + const { height } = props; + const data = storyStore.fromId(previewId); + const { framework = null } = parameters || {}; + const { inlineStories = inferInlineStories(framework), iframeHeight = undefined } = + (parameters && parameters.options && parameters.options.docs) || {}; + return { + inline: inlineStories, + id: previewId, + storyFn: data && data.getDecorated(), + height: height || iframeHeight, + title: data && data.name, + }; +}; + +const StoryContainer: React.FunctionComponent = props => ( + + {context => { + const storyProps = getStoryProps(props, context); + return ; + }} + +); + +StoryContainer.defaultProps = { + children: null, + name: null, +}; + +export { StoryContainer as Story }; diff --git a/addons/docs/src/blocks/Wrapper.tsx b/addons/docs/src/blocks/Wrapper.tsx new file mode 100644 index 00000000000..a73402f89a5 --- /dev/null +++ b/addons/docs/src/blocks/Wrapper.tsx @@ -0,0 +1,9 @@ +import React from 'react'; + +interface WrapperProps { + children: React.ReactNode; +} + +export const Wrapper: React.FunctionComponent = ({ children }) => ( +
{children}
+); diff --git a/addons/docs/src/blocks/index.ts b/addons/docs/src/blocks/index.ts new file mode 100644 index 00000000000..221fe9e567f --- /dev/null +++ b/addons/docs/src/blocks/index.ts @@ -0,0 +1,12 @@ +export { ColorPalette, ColorItem, IconGallery, IconItem, Typeset } from '@storybook/components'; + +export * from './Description'; +export * from './DocsContext'; +export * from './DocsPage'; +export * from './DocsContainer'; +export * from './Meta'; +export * from './Preview'; +export * from './Props'; +export * from './Source'; +export * from './Story'; +export * from './Wrapper'; diff --git a/addons/docs/src/blocks/shared.ts b/addons/docs/src/blocks/shared.ts new file mode 100644 index 00000000000..61d2a7f93f5 --- /dev/null +++ b/addons/docs/src/blocks/shared.ts @@ -0,0 +1,2 @@ +export const CURRENT_SELECTION = '.'; +export type Component = any; diff --git a/addons/docs/src/lib/getPropDefs.ts b/addons/docs/src/lib/getPropDefs.ts new file mode 100644 index 00000000000..2837e205847 --- /dev/null +++ b/addons/docs/src/lib/getPropDefs.ts @@ -0,0 +1,88 @@ +/* eslint-disable no-underscore-dangle */ + +import PropTypes from 'prop-types'; +import { PropDef } from '@storybook/components'; +import { Component } from '../blocks/shared'; + +interface PropDefMap { + [p: string]: PropDef; +} + +export type PropDefGetter = (type: Component) => PropDef[] | null; + +const propTypesMap = new Map(); + +Object.keys(PropTypes).forEach(typeName => { + // @ts-ignore + const type = PropTypes[typeName]; + + propTypesMap.set(type, typeName); + propTypesMap.set(type.isRequired, typeName); +}); + +const hasDocgen = (obj: any) => obj && obj.props && Object.keys(obj.props).length > 0; + +const propsFromDocgen: PropDefGetter = type => { + const props: PropDefMap = {}; + const docgenInfoProps = type.__docgenInfo.props; + + Object.keys(docgenInfoProps).forEach(property => { + const docgenInfoProp = docgenInfoProps[property]; + const defaultValueDesc = docgenInfoProp.defaultValue || {}; + const propType = docgenInfoProp.flowType || docgenInfoProp.type || 'other'; + + props[property] = { + name: property, + type: propType, + required: docgenInfoProp.required, + description: docgenInfoProp.description, + defaultValue: defaultValueDesc.value, + }; + }); + + return Object.values(props); +}; + +const propsFromPropTypes: PropDefGetter = type => { + const props: PropDefMap = {}; + + if (type.propTypes) { + Object.keys(type.propTypes).forEach(property => { + const typeInfo = type.propTypes[property]; + const required = typeInfo.isRequired === undefined; + const docgenInfo = + type.__docgenInfo && type.__docgenInfo.props && type.__docgenInfo.props[property]; + const description = docgenInfo ? docgenInfo.description : null; + let propType = propTypesMap.get(typeInfo) || 'other'; + + if (propType === 'other') { + if (docgenInfo && docgenInfo.type) { + propType = docgenInfo.type.name; + } + } + + props[property] = { name: property, type: propType, required, description }; + }); + } + + if (type.defaultProps) { + Object.keys(type.defaultProps).forEach(property => { + const value = type.defaultProps[property]; + + if (value === undefined) { + return; + } + + if (!props[property]) { + props[property] = { name: property, type: 'any', required: false }; + } + + props[property].defaultValue = value; + }); + } + + return Object.values(props); +}; + +export const getPropDefs: PropDefGetter = type => + hasDocgen(type.__docgenInfo) ? propsFromDocgen(type) : propsFromPropTypes(type); diff --git a/addons/docs/src/typings.d.ts b/addons/docs/src/typings.d.ts new file mode 100644 index 00000000000..005ee92d6b8 --- /dev/null +++ b/addons/docs/src/typings.d.ts @@ -0,0 +1 @@ +declare module '@mdx-js/react'; diff --git a/addons/docs/vue/index.js b/addons/docs/vue/index.js new file mode 100644 index 00000000000..38c1756201b --- /dev/null +++ b/addons/docs/vue/index.js @@ -0,0 +1 @@ +module.exports = require('../common/index'); diff --git a/addons/docs/vue/preset.js b/addons/docs/vue/preset.js new file mode 100644 index 00000000000..a9b8af2cce0 --- /dev/null +++ b/addons/docs/vue/preset.js @@ -0,0 +1 @@ +module.exports = require('../common/preset'); diff --git a/addons/events/package.json b/addons/events/package.json index a9271dfd4e0..b4471567165 100644 --- a/addons/events/package.json +++ b/addons/events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-events", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Add events to your Storybook stories.", "keywords": [ "addon", @@ -24,10 +24,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/client-api": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/client-api": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "core-js": "^3.0.1", "format-json": "^1.0.3", "lodash": "^4.17.11", diff --git a/addons/google-analytics/package.json b/addons/google-analytics/package.json index 8597020c20f..c518e6aa12a 100644 --- a/addons/google-analytics/package.json +++ b/addons/google-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-google-analytics", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Storybook addon for google analytics", "keywords": [ "addon", @@ -20,8 +20,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", "core-js": "^3.0.1", "global": "^4.3.2", "react-ga": "^2.5.7" diff --git a/addons/graphql/package.json b/addons/graphql/package.json index e4a38145ee8..dcb2025a110 100644 --- a/addons/graphql/package.json +++ b/addons/graphql/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-graphql", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Storybook addon to display the GraphiQL IDE", "keywords": [ "addon", @@ -22,8 +22,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", "core-js": "^3.0.1", "global": "^4.3.2", "graphiql": "^0.13.0", diff --git a/addons/info/package.json b/addons/info/package.json index 65ddf062ed6..5ef51e2c016 100644 --- a/addons/info/package.json +++ b/addons/info/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-info", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "A Storybook addon to show additional information for your stories.", "keywords": [ "addon", @@ -22,10 +22,10 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/client-logger": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/client-logger": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "core-js": "^3.0.1", "global": "^4.3.2", "jsx-to-string": "^1.4.0", diff --git a/addons/info/src/__snapshots__/index.test.js.snap b/addons/info/src/__snapshots__/index.test.js.snap index 64aa1bba1d5..c590f5aab76 100644 --- a/addons/info/src/__snapshots__/index.test.js.snap +++ b/addons/info/src/__snapshots__/index.test.js.snap @@ -1331,7 +1331,7 @@ exports[`addon Info should render component description if story kind matches co bordered={true} className={null} copyable={true} - format={true} + format={false} language="js" padded={false} > @@ -5888,7 +5888,7 @@ exports[`addon Info should render component description if story name matches co bordered={true} className={null} copyable={true} - format={true} + format={false} language="js" padded={false} > diff --git a/addons/info/src/components/markdown/code.js b/addons/info/src/components/markdown/code.js index 3bd41509241..4e6b24ba7de 100644 --- a/addons/info/src/components/markdown/code.js +++ b/addons/info/src/components/markdown/code.js @@ -5,7 +5,7 @@ import { ThemeProvider, convert } from '@storybook/theming'; const Code = ({ code, language = 'plaintext', ...rest }) => ( - + {code} diff --git a/addons/jest/package.json b/addons/jest/package.json index 3997f1a073d..716f00a4178 100644 --- a/addons/jest/package.json +++ b/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "React storybook addon that show component jest report", "keywords": [ "addon", @@ -28,11 +28,11 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "core-js": "^3.0.1", "global": "^4.3.2", "react": "^16.8.3", diff --git a/addons/knobs/package.json b/addons/knobs/package.json index 0d282c2187d..0e6af13ee87 100644 --- a/addons/knobs/package.json +++ b/addons/knobs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-knobs", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Storybook Addon Prop Editor Component", "keywords": [ "addon", @@ -22,11 +22,11 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/client-api": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/client-api": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "copy-to-clipboard": "^3.0.8", "core-js": "^3.0.1", "escape-html": "^1.0.3", diff --git a/addons/links/package.json b/addons/links/package.json index 520f10cb7fa..eba9df26ebe 100644 --- a/addons/links/package.json +++ b/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Story Links addon for storybook", "keywords": [ "addon", @@ -22,9 +22,9 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/router": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/router": "5.2.0-alpha.32", "common-tags": "^1.8.0", "core-js": "^3.0.1", "global": "^4.3.2", diff --git a/addons/notes/package.json b/addons/notes/package.json index acf67698144..240c4c7218c 100644 --- a/addons/notes/package.json +++ b/addons/notes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-notes", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Write notes for your Storybook stories.", "keywords": [ "addon", @@ -23,13 +23,13 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/client-logger": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/router": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/client-logger": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/router": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "core-js": "^3.0.1", "global": "^4.3.2", "markdown-to-jsx": "^6.9.3", diff --git a/addons/notes/src/Panel.tsx b/addons/notes/src/Panel.tsx index da8f76df14c..5daaaa7ba2f 100644 --- a/addons/notes/src/Panel.tsx +++ b/addons/notes/src/Panel.tsx @@ -68,7 +68,13 @@ export const SyntaxHighlighter = ({ className, children, ...props }: SyntaxHighl // className: "lang-jsx" const language = className.split('-'); return ( - + {children} ); diff --git a/addons/ondevice-actions/package.json b/addons/ondevice-actions/package.json index e1c5743b866..32725d450df 100644 --- a/addons/ondevice-actions/package.json +++ b/addons/ondevice-actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-actions", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Action Logger addon for react-native storybook", "keywords": [ "storybook" @@ -19,13 +19,13 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", "core-js": "^2.5.7", "fast-deep-equal": "^2.0.1" }, "devDependencies": { - "@storybook/addon-actions": "5.2.0-alpha.23" + "@storybook/addon-actions": "5.2.0-alpha.32" }, "peerDependencies": { "@storybook/addon-actions": "*", diff --git a/addons/ondevice-actions/src/components/ActionLogger/Inspect.tsx b/addons/ondevice-actions/src/components/ActionLogger/Inspect.tsx index bcf4f1fcac2..fb7ffbe513d 100644 --- a/addons/ondevice-actions/src/components/ActionLogger/Inspect.tsx +++ b/addons/ondevice-actions/src/components/ActionLogger/Inspect.tsx @@ -1,3 +1,5 @@ +/* eslint-disable react/no-array-index-key */ +/* eslint-disable no-nested-ternary */ import React from 'react'; import { Button, View, Text } from 'react-native'; @@ -22,6 +24,7 @@ const theme = { class Inspect extends React.Component<{ name?: string; value: any }, { expanded: boolean }> { state = { expanded: false }; + render() { const { name, value } = this.props; const { expanded } = this.state; @@ -52,7 +55,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded: {toggle} {nameComponent} - {': ' + (value.length === 0 ? '[]' : expanded ? '[' : '[...]')} + {`: ${value.length === 0 ? '[]' : expanded ? '[' : '[...]'}`} {expanded ? ( @@ -62,7 +65,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded: ))} - {']'} + ] ) : null} @@ -71,13 +74,13 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded: } return ( - {'['} + [ {value.map((v, i) => ( ))} - {']'} + ] ); } @@ -89,7 +92,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded: {toggle} {nameComponent} - {': ' + (Object.keys(value).length === 0 ? '{}' : expanded ? '{' : '{...}')} + {`: ${Object.keys(value).length === 0 ? '{}' : expanded ? '{' : '{...}'}`} {expanded ? ( @@ -124,7 +127,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded: {toggle} {nameComponent} - {': '} + : ); @@ -147,7 +150,7 @@ function Value({ value }: { value: any }) { if (value instanceof RegExp) { return ( - {'/' + value.source + '/' + value.flags} + {`/${value.source}/${value.flags}`} ); } @@ -166,8 +169,9 @@ function Value({ value }: { value: any }) { ); case 'function': return [Function]; + default: + return {JSON.stringify(value)}; } - return {JSON.stringify(value)}; } export default Inspect; diff --git a/addons/ondevice-backgrounds/package.json b/addons/ondevice-backgrounds/package.json index fb008630355..28b4a5dbba9 100644 --- a/addons/ondevice-backgrounds/package.json +++ b/addons/ondevice-backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-backgrounds", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "A react-native storybook addon to show different backgrounds for your preview", "keywords": [ "addon", @@ -24,7 +24,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", "core-js": "^3.0.1", "prop-types": "^15.7.2" }, diff --git a/addons/ondevice-backgrounds/src/BackgroundPanel.js b/addons/ondevice-backgrounds/src/BackgroundPanel.js index cd28c6d73c1..3442ecfc04d 100644 --- a/addons/ondevice-backgrounds/src/BackgroundPanel.js +++ b/addons/ondevice-backgrounds/src/BackgroundPanel.js @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types, react/destructuring-assignment, import/no-extraneous-dependencies */ import React, { Component } from 'react'; import { View, Text } from 'react-native'; import Events from '@storybook/core-events'; @@ -36,10 +37,6 @@ const Instructions = () => ( ); export default class BackgroundPanel extends Component { - setBackgroundFromSwatch = background => { - this.props.channel.emit(Constants.UPDATE_BACKGROUND, background); - }; - componentDidMount() { this.props.channel.on(Events.SELECT_STORY, this.onStorySelected); } @@ -48,6 +45,10 @@ export default class BackgroundPanel extends Component { this.props.channel.removeListener(Events.SELECT_STORY, this.onStorySelected); } + setBackgroundFromSwatch = background => { + this.props.channel.emit(Constants.UPDATE_BACKGROUND, background); + }; + onStorySelected = selection => { this.setState({ selection }); }; diff --git a/addons/ondevice-backgrounds/src/container.js b/addons/ondevice-backgrounds/src/container.js index f5b03964bb1..523e4ae4a31 100644 --- a/addons/ondevice-backgrounds/src/container.js +++ b/addons/ondevice-backgrounds/src/container.js @@ -19,9 +19,9 @@ export default class Container extends React.Component { channel.removeListener(Constants.UPDATE_BACKGROUND, this.onBackgroundChange); } - onBackgroundChange = (background) => { + onBackgroundChange = background => { this.setState({ background }); - } + }; render() { const { background } = this.state; diff --git a/addons/ondevice-knobs/package.json b/addons/ondevice-knobs/package.json index fbab2758ad0..9e990097719 100644 --- a/addons/ondevice-knobs/package.json +++ b/addons/ondevice-knobs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-knobs", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Display storybook story knobs on your deviced.", "keywords": [ "addon", @@ -21,8 +21,8 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", "core-js": "^3.0.1", "deep-equal": "^1.0.1", "prop-types": "^15.7.2", diff --git a/addons/ondevice-knobs/src/PropForm.js b/addons/ondevice-knobs/src/PropForm.js index 93770e5e3e7..e0c35334cf1 100644 --- a/addons/ondevice-knobs/src/PropForm.js +++ b/addons/ondevice-knobs/src/PropForm.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import { View } from 'react-native'; import PropField from './PropField'; -export default class propForm extends React.Component { +export default class PropForm extends React.Component { makeChangeHandler(name, type) { return value => { const { onFieldChange } = this.props; @@ -38,13 +38,13 @@ export default class propForm extends React.Component { } } -propForm.displayName = 'propForm'; +PropForm.displayName = 'PropForm'; -propForm.defaultProps = { +PropForm.defaultProps = { knobs: [], }; -propForm.propTypes = { +PropForm.propTypes = { knobs: PropTypes.arrayOf( PropTypes.shape({ name: PropTypes.string, diff --git a/addons/ondevice-notes/package.json b/addons/ondevice-notes/package.json index 2f83a8ae86a..4f1522fba87 100644 --- a/addons/ondevice-notes/package.json +++ b/addons/ondevice-notes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-ondevice-notes", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Write notes for your react-native Storybook stories.", "keywords": [ "addon", @@ -20,7 +20,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", "core-js": "^3.0.1", "prop-types": "^15.7.2", "react-native-simple-markdown": "^1.1.0" diff --git a/addons/ondevice-notes/src/index.js b/addons/ondevice-notes/src/index.js index 5200b63f845..28be51837ef 100644 --- a/addons/ondevice-notes/src/index.js +++ b/addons/ondevice-notes/src/index.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-undef if (__DEV__) { console.log("import '@storybook/addon-ondevice-notes/register' to register the notes addon"); -} \ No newline at end of file +} diff --git a/addons/ondevice-notes/src/register.js b/addons/ondevice-notes/src/register.js index 1ed3a38bfcd..b68ccc3a6d5 100644 --- a/addons/ondevice-notes/src/register.js +++ b/addons/ondevice-notes/src/register.js @@ -1,3 +1,6 @@ +/* eslint-disable react/prop-types */ +/* eslint-disable react/destructuring-assignment */ +/* eslint-disable import/no-extraneous-dependencies */ import React from 'react'; import { View } from 'react-native'; import Markdown from 'react-native-simple-markdown'; @@ -7,10 +10,6 @@ import Events from '@storybook/core-events'; export const PARAM_KEY = `notes`; class Notes extends React.Component { - setBackgroundFromSwatch = background => { - this.props.channel.emit(Constants.UPDATE_BACKGROUND, background); - }; - componentDidMount() { this.props.channel.on(Events.SELECT_STORY, this.onStorySelected); } diff --git a/addons/options/package.json b/addons/options/package.json index c16a073f195..fd3f950c6dc 100644 --- a/addons/options/package.json +++ b/addons/options/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-options", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "Options addon for storybook", "keywords": [ "addon", @@ -22,7 +22,7 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", "core-js": "^3.0.1", "util-deprecate": "^1.0.2" }, diff --git a/addons/queryparams/package.json b/addons/queryparams/package.json index 854adf15c50..653a821d664 100644 --- a/addons/queryparams/package.json +++ b/addons/queryparams/package.json @@ -1,19 +1,19 @@ { "name": "@storybook/addon-queryparams", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "parameter addon for storybook", "keywords": [ "addon", "storybook", "query" ], - "homepage": "https://github.com/storybooks/storybook#readme", + "homepage": "https://github.com/storybookjs/storybook#readme", "bugs": { - "url": "https://github.com/storybooks/storybook/issues" + "url": "https://github.com/storybookjs/storybook/issues" }, "repository": { "type": "git", - "url": "git+https://github.com/storybooks/storybook.git", + "url": "git+https://github.com/storybookjs/storybook.git", "directory": "addons/addon-queryparams" }, "license": "MIT", @@ -23,14 +23,14 @@ "prepare": "node ../../scripts/prepare.js" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/api": "5.2.0-alpha.23", - "@storybook/client-logger": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/api": "5.2.0-alpha.32", + "@storybook/client-logger": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "common-tags": "^1.8.0", - "core-js": "^2.6.5", + "core-js": "^3.0.1", "global": "^4.3.2", "qs": "^6.6.0", "react": "^16.8.3" diff --git a/addons/storyshots/storyshots-core/package.json b/addons/storyshots/storyshots-core/package.json index fd0354d15b3..8abc62d17cb 100644 --- a/addons/storyshots/storyshots-core/package.json +++ b/addons/storyshots/storyshots-core/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storyshots", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.", "keywords": [ "addon", @@ -25,7 +25,7 @@ "storybook": "start-storybook -p 6006" }, "dependencies": { - "@storybook/addons": "5.2.0-alpha.23", + "@storybook/addons": "5.2.0-alpha.32", "core-js": "^3.0.1", "glob": "^7.1.3", "global": "^4.3.2", diff --git a/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.js b/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.js index 684c99c4b9e..cc7fa979914 100644 --- a/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.js +++ b/addons/storyshots/storyshots-core/src/api/integrityTestTemplate.js @@ -16,7 +16,8 @@ function integrityTest(integrityOptions, stories2snapsConverter) { const possibleStoriesFiles = stories2snapsConverter.getPossibleStoriesFiles(fileName); return !possibleStoriesFiles.some(fs.existsSync); }); - expect(abandonedStoryshots.length).toBe(0); + + expect(abandonedStoryshots).toEqual([]); }); }); } diff --git a/addons/storyshots/storyshots-core/stories/required_with_context/Button.stories.js b/addons/storyshots/storyshots-core/stories/required_with_context/Button.stories.js index e63d097b98b..6dbfd97a1cd 100644 --- a/addons/storyshots/storyshots-core/stories/required_with_context/Button.stories.js +++ b/addons/storyshots/storyshots-core/stories/required_with_context/Button.stories.js @@ -5,6 +5,9 @@ import { action } from '@storybook/addon-actions'; import { Button } from '@storybook/react/demo'; storiesOf('Button', module) + .addParameters({ + component: Button, + }) .add('with text', () => ) .add('with some emoji', () => ( -)); +); diff --git a/examples/cra-kitchen-sink/src/stories/index.stories.js b/examples/cra-kitchen-sink/src/stories/index.stories.js index f77af5ff862..0f0d2610399 100644 --- a/examples/cra-kitchen-sink/src/stories/index.stories.js +++ b/examples/cra-kitchen-sink/src/stories/index.stories.js @@ -1,5 +1,5 @@ +/* eslint-disable react/destructuring-assignment */ import React from 'react'; -import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { withInfo } from '@storybook/addon-info'; import { Button } from '@storybook/react/demo'; @@ -23,43 +23,61 @@ const InfoButton = () => ( ); -storiesOf('Button', module) - .add('with text', () => , { +export default { + title: 'Button', + + parameters: { + component: Button, + }, +}; + +export const story1 = () => ; +story1.story = { + name: 'with text', + parameters: { options: { selectedPanel: 'storybook/actions/panel' }, - }) - .add( - 'with some emoji', - () => ( - - ), - { - options: { selectedPanel: 'storybook/actions/panel' }, - } - ) - .add('with notes', () => , { + }, +}; + +export const story2 = () => ( + +); +story2.story = { + name: 'with some emoji', + parameters: { + options: { selectedPanel: 'storybook/actions/panel' }, + }, +}; + +export const story3 = () => ; +story3.story = { + name: 'with notes', + parameters: { notes: 'A very simple button', options: { selectedPanel: 'storybook/notes/panel' }, - }) - .add( - 'with new info', - context => ( - - - click the label in top right for info about "{context.name}" - - - ), - { - notes: 'Composition: Info(Notes())', - options: { selectedPanel: 'storybook/info/panel' }, - decorators: [ - withInfo( - 'Use the [info addon](https://github.com/storybookjs/storybook/tree/master/addons/info) with its new painless API.' - ), - ], - } - ); + }, +}; + +export const story4 = context => ( + + + click the label in top right for info about "{context.name}" + + +); +story4.story = { + name: 'with new info', + parameters: { + notes: 'Composition: Info(Notes())', + options: { selectedPanel: 'storybook/info/panel' }, + decorators: [ + withInfo( + 'Use the [info addon](https://github.com/storybookjs/storybook/tree/master/addons/info) with its new painless API.' + ), + ], + }, +}; diff --git a/examples/cra-kitchen-sink/src/stories/long-description.stories.js b/examples/cra-kitchen-sink/src/stories/long-description.stories.js index d5d6124ab87..02b61f38868 100644 --- a/examples/cra-kitchen-sink/src/stories/long-description.stories.js +++ b/examples/cra-kitchen-sink/src/stories/long-description.stories.js @@ -1,9 +1,12 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import centered from '@storybook/addon-centered/react'; import { Button } from '@storybook/react/demo'; -storiesOf('Some really long story kind description', module) - .addDecorator(centered) - .add('with text', () => ); +export default { + title: 'Some really long story kind description', + decorators: [centered], +}; + +export const story1 = () => ; +story1.story = { name: 'with text' }; diff --git a/examples/cra-kitchen-sink/src/stories/welcome.js b/examples/cra-kitchen-sink/src/stories/welcome.js index 9610f12d04e..cbadd8d9b90 100644 --- a/examples/cra-kitchen-sink/src/stories/welcome.js +++ b/examples/cra-kitchen-sink/src/stories/welcome.js @@ -1,6 +1,14 @@ import React from 'react'; import { Welcome } from '@storybook/react/demo'; -import { storiesOf } from '@storybook/react'; import { linkTo } from '@storybook/addon-links'; -storiesOf('Welcome', module).add('to Storybook', () => ); +export default { + title: 'Welcome', + + parameters: { + component: Welcome, + }, +}; + +export const story1 = () => ; +story1.title = 'to Storybook'; diff --git a/examples/cra-react15/.storybook/config.js b/examples/cra-react15/.storybook/config.js index 17104723187..115943f0f4f 100644 --- a/examples/cra-react15/.storybook/config.js +++ b/examples/cra-react15/.storybook/config.js @@ -1,14 +1,10 @@ -import { configure, addParameters } from '@storybook/react'; +import { load, addParameters } from '@storybook/react'; import { create } from '@storybook/theming/create'; -function loadStories() { - require('../src/stories'); -} - addParameters({ options: { theme: create({ colorPrimary: 'hotpink', colorSecondary: 'orangered' }), }, }); -configure(loadStories, module); +load(require.context('../src/stories', true, /\.stories\.js$/), module); diff --git a/examples/cra-react15/package.json b/examples/cra-react15/package.json index 39af8718daf..4930c5dc090 100644 --- a/examples/cra-react15/package.json +++ b/examples/cra-react15/package.json @@ -1,6 +1,6 @@ { "name": "cra-react15", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "dependencies": { "babel-loader": "8.0.6", @@ -19,10 +19,10 @@ "build-storybook": "build-storybook -s public" }, "devDependencies": { - "@storybook/addon-actions": "5.2.0-alpha.23", - "@storybook/addon-links": "5.2.0-alpha.23", - "@storybook/react": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addon-actions": "5.2.0-alpha.32", + "@storybook/addon-links": "5.2.0-alpha.32", + "@storybook/react": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "babel-core": "6", "babel-runtime": "6" } diff --git a/examples/cra-react15/src/stories/button.stories.js b/examples/cra-react15/src/stories/button.stories.js new file mode 100644 index 00000000000..3c443e29464 --- /dev/null +++ b/examples/cra-react15/src/stories/button.stories.js @@ -0,0 +1,22 @@ +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { Button } from '@storybook/react/demo'; + +export default { + title: 'Button', + parameters: { + component: Button, + }, +}; + +export const story1 = () => ; +story1.story = { name: 'with text' }; + +export const story2 = () => ( + +); +story2.story = { name: 'with some emoji' }; diff --git a/examples/cra-react15/src/stories/index.js b/examples/cra-react15/src/stories/index.js deleted file mode 100644 index aa04241802d..00000000000 --- a/examples/cra-react15/src/stories/index.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; - -import { storiesOf } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; -import { linkTo } from '@storybook/addon-links'; - -import { Button, Welcome } from '@storybook/react/demo'; - -storiesOf('Welcome', module).add('to Storybook', () => ); - -storiesOf('Button', module) - .add('with text', () => ) - .add('with some emoji', () => ( - - )); diff --git a/examples/cra-react15/src/stories/welcome.stories.js b/examples/cra-react15/src/stories/welcome.stories.js new file mode 100644 index 00000000000..b32255e0408 --- /dev/null +++ b/examples/cra-react15/src/stories/welcome.stories.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { linkTo } from '@storybook/addon-links'; +import { Welcome } from '@storybook/react/demo'; + +export default { + title: 'Welcome', + parameters: { + component: Welcome, + }, +}; + +export const story1 = () => ; +story1.story = { name: 'to Storybook' }; diff --git a/examples/cra-ts-kitchen-sink/package.json b/examples/cra-ts-kitchen-sink/package.json index 344b2e251fc..9b6f36b6e08 100644 --- a/examples/cra-ts-kitchen-sink/package.json +++ b/examples/cra-ts-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "cra-ts-kitchen-sink", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "scripts": { "build-storybook": "build-storybook -s public", @@ -14,12 +14,12 @@ "react-dom": "^16.8.3" }, "devDependencies": { - "@storybook/addon-a11y": "5.2.0-alpha.23", - "@storybook/addon-actions": "5.2.0-alpha.23", - "@storybook/addon-info": "5.2.0-alpha.23", - "@storybook/addon-options": "5.2.0-alpha.23", - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/react": "5.2.0-alpha.23", + "@storybook/addon-a11y": "5.2.0-alpha.32", + "@storybook/addon-actions": "5.2.0-alpha.32", + "@storybook/addon-info": "5.2.0-alpha.32", + "@storybook/addon-options": "5.2.0-alpha.32", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/react": "5.2.0-alpha.32", "@types/enzyme": "^3.9.0", "@types/react": "^16.8.3", "@types/react-dom": "^16.8.2", diff --git a/examples/dev-kits/package.json b/examples/dev-kits/package.json index baf55a3b29c..6b539990bf9 100644 --- a/examples/dev-kits/package.json +++ b/examples/dev-kits/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/example-devkits", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "scripts": { "build-storybook": "build-storybook -c ./ -s built-storybooks", @@ -8,15 +8,15 @@ "storybook": "start-storybook -p 9011 -c ./" }, "devDependencies": { - "@storybook/addon-decorator": "5.2.0-alpha.23", - "@storybook/addon-roundtrip": "5.2.0-alpha.23", - "@storybook/addon-parameter": "5.2.0-alpha.23", - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/node-logger": "5.2.0-alpha.23", - "@storybook/react": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addon-decorator": "5.2.0-alpha.32", + "@storybook/addon-parameter": "5.2.0-alpha.32", + "@storybook/addon-roundtrip": "5.2.0-alpha.32", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/node-logger": "5.2.0-alpha.32", + "@storybook/react": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "cors": "^2.8.5", "cross-env": "^5.2.0", "enzyme-to-json": "^3.3.5", diff --git a/examples/ember-cli/.storybook/config.js b/examples/ember-cli/.storybook/config.js index e887baca878..06eca1d4f6a 100644 --- a/examples/ember-cli/.storybook/config.js +++ b/examples/ember-cli/.storybook/config.js @@ -1,4 +1,4 @@ -import { configure, addParameters, addDecorator } from '@storybook/ember'; +import { load, addParameters, addDecorator } from '@storybook/ember'; import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); @@ -9,11 +9,4 @@ addParameters({ }, }); -function loadStories() { - require('../stories/index.stories'); - - const req = require.context('../stories', true, /\.stories\.js$/); - req.keys().forEach(filename => req(filename)); -} - -configure(loadStories, module); +load(require.context('../stories', true, /\.stories\.js$/), module); diff --git a/examples/ember-cli/package.json b/examples/ember-cli/package.json index 6425b7f9072..a49d4505ef4 100644 --- a/examples/ember-cli/package.json +++ b/examples/ember-cli/package.json @@ -1,6 +1,6 @@ { "name": "ember-example", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "scripts": { "build": "ember build", @@ -15,18 +15,19 @@ }, "devDependencies": { "@babel/core": "^7.3.4", - "@storybook/addon-a11y": "5.2.0-alpha.23", - "@storybook/addon-actions": "5.2.0-alpha.23", - "@storybook/addon-backgrounds": "5.2.0-alpha.23", - "@storybook/addon-centered": "5.2.0-alpha.23", - "@storybook/addon-knobs": "5.2.0-alpha.23", - "@storybook/addon-links": "5.2.0-alpha.23", - "@storybook/addon-notes": "5.2.0-alpha.23", - "@storybook/addon-options": "5.2.0-alpha.23", - "@storybook/addon-storysource": "5.2.0-alpha.23", - "@storybook/addon-viewport": "5.2.0-alpha.23", - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/ember": "5.2.0-alpha.23", + "@storybook/addon-a11y": "5.2.0-alpha.32", + "@storybook/addon-actions": "5.2.0-alpha.32", + "@storybook/addon-backgrounds": "5.2.0-alpha.32", + "@storybook/addon-centered": "5.2.0-alpha.32", + "@storybook/addon-knobs": "5.2.0-alpha.32", + "@storybook/addon-links": "5.2.0-alpha.32", + "@storybook/addon-notes": "5.2.0-alpha.32", + "@storybook/addon-options": "5.2.0-alpha.32", + "@storybook/addon-storysource": "5.2.0-alpha.32", + "@storybook/addon-viewport": "5.2.0-alpha.32", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/ember": "5.2.0-alpha.32", + "@storybook/source-loader": "5.2.0-alpha.32", "babel-loader": "^8", "broccoli-asset-rev": "^3.0.0", "cross-env": "^5.2.0", diff --git a/examples/ember-cli/stories/addon-a11y.stories.js b/examples/ember-cli/stories/addon-a11y.stories.js index 83649432ade..66ca80ec35a 100644 --- a/examples/ember-cli/stories/addon-a11y.stories.js +++ b/examples/ember-cli/stories/addon-a11y.stories.js @@ -1,15 +1,22 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; import { checkA11y } from '@storybook/addon-a11y'; -storiesOf('Addon|a11y', module) - .addDecorator(checkA11y) - .addParameters({ options: { selectedPanel: '@storybook/a11y/panel' } }) - .add('Default', () => hbs``) - .add('Label', () => hbs``) - .add('Disabled', () => hbs``) - .add( - 'Invalid contrast', - () => - hbs`` - ); +export default { + title: 'Addon|a11y', + decorators: [checkA11y], + + parameters: { + options: { selectedPanel: '@storybook/a11y/panel' }, + }, +}; + +export const Default = () => hbs``; +export const Label = () => hbs``; +export const Disabled = () => hbs``; + +export const invalidContrast = () => + hbs``; + +invalidContrast.story = { + name: 'Invalid contrast', +}; diff --git a/examples/ember-cli/stories/addon-actions.stories.js b/examples/ember-cli/stories/addon-actions.stories.js index a85fc34b922..e11f8c8201b 100644 --- a/examples/ember-cli/stories/addon-actions.stories.js +++ b/examples/ember-cli/stories/addon-actions.stories.js @@ -1,16 +1,19 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; import { action } from '@storybook/addon-actions'; -storiesOf('Addon|Actions', module) - .addParameters({ +export default { + title: 'Addon|Actions', + + parameters: { options: { selectedPanel: 'storybook/actions/panel', }, - }) - .add('button', () => ({ - template: hbs``, - context: { - onClick: action('clicked'), - }, - })); + }, +}; + +export const button = () => ({ + template: hbs``, + context: { + onClick: action('clicked'), + }, +}); diff --git a/examples/ember-cli/stories/addon-backgrounds.stories.js b/examples/ember-cli/stories/addon-backgrounds.stories.js index 18d610d52c5..ea282fa81c5 100644 --- a/examples/ember-cli/stories/addon-backgrounds.stories.js +++ b/examples/ember-cli/stories/addon-backgrounds.stories.js @@ -1,16 +1,28 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; -storiesOf('Addon|Backgrounds', module) - .addParameters({ +export default { + title: 'Addon|Backgrounds', + + parameters: { backgrounds: [ { name: 'light', value: '#eeeeee' }, { name: 'dark', value: '#222222', default: true }, ], - }) - .add('story 1', () => ({ - template: hbs``, - })) - .add('story 2', () => ({ - template: hbs``, - })); + }, +}; + +export const story1 = () => ({ + template: hbs``, +}); + +story1.story = { + name: 'story 1', +}; + +export const story2 = () => ({ + template: hbs``, +}); + +story2.story = { + name: 'story 2', +}; diff --git a/examples/ember-cli/stories/addon-centered.stories.js b/examples/ember-cli/stories/addon-centered.stories.js index f6a46d022c8..3cdd11dee89 100644 --- a/examples/ember-cli/stories/addon-centered.stories.js +++ b/examples/ember-cli/stories/addon-centered.stories.js @@ -1,9 +1,15 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; import Centered from '@storybook/addon-centered/ember'; -storiesOf('Addon|Centered', module) - .addDecorator(Centered) - .add('button', () => ({ - template: hbs``, - })); +export default { + title: 'Addon|Centered', + decorators: [Centered], + + parameters: { + component: Centered, + }, +}; + +export const button = () => ({ + template: hbs``, +}); diff --git a/examples/ember-cli/stories/addon-knobs.stories.js b/examples/ember-cli/stories/addon-knobs.stories.js index 146d459ac05..f0fcbb19c4d 100644 --- a/examples/ember-cli/stories/addon-knobs.stories.js +++ b/examples/ember-cli/stories/addon-knobs.stories.js @@ -1,13 +1,18 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; import { withKnobs, text, color, boolean } from '@storybook/addon-knobs'; import { action } from '@storybook/addon-actions'; -storiesOf('Addon|Knobs', module) - .addDecorator(withKnobs) - .addParameters({ options: { selectedPanel: 'storybookjs/knobs/panel' } }) - .add('with text', () => ({ - template: hbs` +export default { + title: 'Addon|Knobs', + decorators: [withKnobs], + + parameters: { + options: { selectedPanel: 'storybookjs/knobs/panel' }, + }, +}; + +export const withText = () => ({ + template: hbs` {{welcome-banner style=(if hidden "display: none") backgroundColor=backgroundColor @@ -18,13 +23,17 @@ storiesOf('Addon|Knobs', module) click=(action onClick) }} `, - context: { - hidden: boolean('hidden', false), - backgroundColor: color('backgroundColor', '#FDF4E7'), - titleColor: color('titleColor', '#DF4D37'), - subTitleColor: color('subTitleColor', '#B8854F'), - title: text('title', 'Welcome to storybook'), - subtitle: text('subtitle', 'This environment is completely editable'), - onClick: action('clicked'), - }, - })); + context: { + hidden: boolean('hidden', false), + backgroundColor: color('backgroundColor', '#FDF4E7'), + titleColor: color('titleColor', '#DF4D37'), + subTitleColor: color('subTitleColor', '#B8854F'), + title: text('title', 'Welcome to storybook'), + subtitle: text('subtitle', 'This environment is completely editable'), + onClick: action('clicked'), + }, +}); + +withText.story = { + name: 'with text', +}; diff --git a/examples/ember-cli/stories/addon-links.stories.js b/examples/ember-cli/stories/addon-links.stories.js index 8357abb4156..6e1e16610e2 100644 --- a/examples/ember-cli/stories/addon-links.stories.js +++ b/examples/ember-cli/stories/addon-links.stories.js @@ -1,10 +1,17 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; import { linkTo } from '@storybook/addon-links'; -storiesOf('Addon|Links', module).add('Go to welcome', () => ({ +export default { + title: 'Addon|Links', +}; + +export const goToWelcome = () => ({ template: hbs``, context: { onClick: linkTo('Welcome'), }, -})); +}); + +goToWelcome.story = { + name: 'Go to welcome', +}; diff --git a/examples/ember-cli/stories/addon-notes.stories.js b/examples/ember-cli/stories/addon-notes.stories.js index 431fb6ae630..ac437cc6213 100644 --- a/examples/ember-cli/stories/addon-notes.stories.js +++ b/examples/ember-cli/stories/addon-notes.stories.js @@ -1,26 +1,32 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; -storiesOf('Addon|Notes', module) - .add( - 'Simple note', - () => ({ - template: hbs`

Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam sed vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec consectetur velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus arcu. Nullam sit amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at fermentum. Nulla sollicitudin, mauris quis semper tempus, sem metus tristique diam, efficitur pulvinar mi urna id urna.

`, - }), - { notes: 'My notes on some bold text' } - ) - .add( - 'Note with HTML', - () => ({ - template: hbs`

๐Ÿค”๐Ÿ˜ณ๐Ÿ˜ฏ๐Ÿ˜ฎ
๐Ÿ˜„๐Ÿ˜ฉ๐Ÿ˜“๐Ÿ˜ฑ
๐Ÿค“๐Ÿ˜‘๐Ÿ˜ถ๐Ÿ˜Š

`, - }), - { - notes: ` -

My notes on emojies

+export default { + title: 'Addon|Notes', +}; - It's not all that important to be honest, but.. +export const simpleNote = () => ({ + template: hbs`

Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam sed vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec consectetur velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus arcu. Nullam sit amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at fermentum. Nulla sollicitudin, mauris quis semper tempus, sem metus tristique diam, efficitur pulvinar mi urna id urna.

`, +}); - Emojis are great, I love emojis, in fact I like using them in my Component notes too! ๐Ÿ˜‡ - `, - } - ); +simpleNote.story = { + name: 'Simple note', + parameters: { notes: 'My notes on some bold text' }, +}; + +export const noteWithHtml = () => ({ + template: hbs`

๐Ÿค”๐Ÿ˜ณ๐Ÿ˜ฏ๐Ÿ˜ฎ
๐Ÿ˜„๐Ÿ˜ฉ๐Ÿ˜“๐Ÿ˜ฑ
๐Ÿค“๐Ÿ˜‘๐Ÿ˜ถ๐Ÿ˜Š

`, +}); + +noteWithHtml.story = { + name: 'Note with HTML', + + parameters: { + notes: ` +

My notes on emojies

+ + It's not all that important to be honest, but.. + + Emojis are great, I love emojis, in fact I like using them in my Component notes too! ๐Ÿ˜‡ + `, + }, +}; diff --git a/examples/ember-cli/stories/index.stories.js b/examples/ember-cli/stories/index.stories.js index 9b0f4314edf..4c194a8a2dd 100644 --- a/examples/ember-cli/stories/index.stories.js +++ b/examples/ember-cli/stories/index.stories.js @@ -1,10 +1,15 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; -storiesOf('Welcome', module) - .addParameters({ options: { showPanel: false } }) - .add('basic', () => ({ - template: hbs` +export default { + title: 'Welcome', + + parameters: { + options: { showPanel: false }, + }, +}; + +export const basic = () => ({ + template: hbs` {{welcome-page}} `, - })); +}); diff --git a/examples/ember-cli/stories/welcome-banner.stories.js b/examples/ember-cli/stories/welcome-banner.stories.js index f322ec9bc05..3a914a80b41 100644 --- a/examples/ember-cli/stories/welcome-banner.stories.js +++ b/examples/ember-cli/stories/welcome-banner.stories.js @@ -1,8 +1,11 @@ import hbs from 'htmlbars-inline-precompile'; -import { storiesOf } from '@storybook/ember'; import { action } from '@storybook/addon-actions'; -storiesOf('welcome-banner', module).add('basic', () => ({ +export default { + title: 'welcome-banner', +}; + +export const basic = () => ({ template: hbs` {{welcome-banner backgroundColor=backgroundColor @@ -21,4 +24,4 @@ storiesOf('welcome-banner', module).add('basic', () => ({ subtitle: 'This environment is completely editable', onClick: action('clicked'), }, -})); +}); diff --git a/examples/html-kitchen-sink/.storybook/config.js b/examples/html-kitchen-sink/.storybook/config.js index df93c95611e..eeb82641683 100644 --- a/examples/html-kitchen-sink/.storybook/config.js +++ b/examples/html-kitchen-sink/.storybook/config.js @@ -1,4 +1,4 @@ -import { configure, addParameters, addDecorator } from '@storybook/html'; +import { load, addParameters, addDecorator } from '@storybook/html'; import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); @@ -16,12 +16,4 @@ addParameters({ }, }); -// automatically import all files ending in *.stories.js -const req = require.context('../stories', true, /\.stories\.js$/); -function loadStories() { - // Make welcome story default - require('../stories/index.stories'); - req.keys().forEach(filename => req(filename)); -} - -configure(loadStories, module); +load(require.context('../stories', true, /\.stories\.js$/), module); diff --git a/examples/html-kitchen-sink/package.json b/examples/html-kitchen-sink/package.json index d06a51fdd90..ea7de03bfa1 100644 --- a/examples/html-kitchen-sink/package.json +++ b/examples/html-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "html-kitchen-sink", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "description": "", "keywords": [], @@ -14,24 +14,25 @@ "storybook": "start-storybook -p 9006" }, "devDependencies": { - "@storybook/addon-a11y": "5.2.0-alpha.23", - "@storybook/addon-actions": "5.2.0-alpha.23", - "@storybook/addon-backgrounds": "5.2.0-alpha.23", - "@storybook/addon-centered": "5.2.0-alpha.23", - "@storybook/addon-events": "5.2.0-alpha.23", - "@storybook/addon-jest": "5.2.0-alpha.23", - "@storybook/addon-knobs": "5.2.0-alpha.23", - "@storybook/addon-links": "5.2.0-alpha.23", - "@storybook/addon-notes": "5.2.0-alpha.23", - "@storybook/addon-options": "5.2.0-alpha.23", - "@storybook/addon-storyshots": "5.2.0-alpha.23", - "@storybook/addon-storysource": "5.2.0-alpha.23", - "@storybook/addon-viewport": "5.2.0-alpha.23", - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/client-api": "5.2.0-alpha.23", - "@storybook/core": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/html": "5.2.0-alpha.23", + "@storybook/addon-a11y": "5.2.0-alpha.32", + "@storybook/addon-actions": "5.2.0-alpha.32", + "@storybook/addon-backgrounds": "5.2.0-alpha.32", + "@storybook/addon-centered": "5.2.0-alpha.32", + "@storybook/addon-events": "5.2.0-alpha.32", + "@storybook/addon-jest": "5.2.0-alpha.32", + "@storybook/addon-knobs": "5.2.0-alpha.32", + "@storybook/addon-links": "5.2.0-alpha.32", + "@storybook/addon-notes": "5.2.0-alpha.32", + "@storybook/addon-options": "5.2.0-alpha.32", + "@storybook/addon-storyshots": "5.2.0-alpha.32", + "@storybook/addon-storysource": "5.2.0-alpha.32", + "@storybook/addon-viewport": "5.2.0-alpha.32", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/client-api": "5.2.0-alpha.32", + "@storybook/core": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/html": "5.2.0-alpha.32", + "@storybook/source-loader": "5.2.0-alpha.32", "eventemitter3": "^3.1.0", "format-json": "^1.0.3", "global": "^4.3.2" diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-a11y.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-a11y.stories.storyshot deleted file mode 100644 index 8c979f07574..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-a11y.stories.storyshot +++ /dev/null @@ -1,27 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|a11y Default 1`] = ` -`; - -exports[`Storyshots Addons|a11y Invalid contrast 1`] = ` - -`; - -exports[`Storyshots Addons|a11y Label 1`] = ` - -`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-actions.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-actions.stories.storyshot deleted file mode 100644 index b5a33580d65..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-actions.stories.storyshot +++ /dev/null @@ -1,62 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Actions Decorated actions + config 1`] = ` - -`; - -exports[`Storyshots Addons|Actions Decorated actions 1`] = ` - -`; - -exports[`Storyshots Addons|Actions Hello World 1`] = ` - -`; - -exports[`Storyshots Addons|Actions Multiple actions + config 1`] = ` - -`; - -exports[`Storyshots Addons|Actions Multiple actions 1`] = ` - -`; - -exports[`Storyshots Addons|Actions Multiple actions, object + config 1`] = ` - -`; - -exports[`Storyshots Addons|Actions Multiple actions, object 1`] = ` - -`; - -exports[`Storyshots Addons|Actions Multiple actions, selector 1`] = ` - - -`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-backgrounds.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-backgrounds.stories.storyshot deleted file mode 100644 index 211e0b45345..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-backgrounds.stories.storyshot +++ /dev/null @@ -1,17 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Backgrounds story 1 1`] = ` - - You should be able to switch backgrounds for this story - -`; - -exports[`Storyshots Addons|Backgrounds story 2 1`] = ` - - This one too! - -`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-centered.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-centered.stories.storyshot deleted file mode 100644 index 681a29fffda..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-centered.stories.storyshot +++ /dev/null @@ -1,17 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Centered button in center 1`] = ` -
-
- -
-
-`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-events.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-events.stories.storyshot deleted file mode 100644 index 84466dd440a..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-events.stories.storyshot +++ /dev/null @@ -1,6 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Events Logger 1`] = ` - - -`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-jest.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-jest.stories.storyshot deleted file mode 100644 index 7c83d5b812b..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-jest.stories.storyshot +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Jest withTests 1`] = `This story shows test results`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-knobs.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-knobs.stories.storyshot deleted file mode 100644 index 7a21a63b844..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-knobs.stories.storyshot +++ /dev/null @@ -1,70 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Knobs All knobs 1`] = ` -
- - -

- My name is Jane, -

- - -

- today is January 20, 2017 -

- - -

- I have a stock of 20 apples, costing $2.25 each. -

- - -

- Also, I have: -

- - -
    -
  • - Laptop -
  • -
  • - Book -
  • -
  • - Whiskey -
  • -
- - -

- Nice to meet you! -

- - -
-`; - -exports[`Storyshots Addons|Knobs CSS transitions 1`] = ` -

- John Doe -

-`; - -exports[`Storyshots Addons|Knobs DOM 1`] = ` -

- John Doe -

-`; - -exports[`Storyshots Addons|Knobs Simple 1`] = ` -
- I am John Doe and I'm 44 years old. -
-`; - -exports[`Storyshots Addons|Knobs XSS safety 1`] = `<img src=x onerror="alert('XSS Attack')" >`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/addon-notes.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/addon-notes.stories.storyshot deleted file mode 100644 index b7b58fa7bad..00000000000 --- a/examples/html-kitchen-sink/stories/__snapshots__/addon-notes.stories.storyshot +++ /dev/null @@ -1,15 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Notes Simple note 1`] = ` -

- - - - - This is a fragment of HTML - - - - -

-`; diff --git a/examples/html-kitchen-sink/stories/__snapshots__/index.stories.storyshot b/examples/html-kitchen-sink/stories/__snapshots__/welcome.stories.storyshot similarity index 80% rename from examples/html-kitchen-sink/stories/__snapshots__/index.stories.storyshot rename to examples/html-kitchen-sink/stories/__snapshots__/welcome.stories.storyshot index 9fc15594022..8b68425a1ea 100644 --- a/examples/html-kitchen-sink/stories/__snapshots__/index.stories.storyshot +++ b/examples/html-kitchen-sink/stories/__snapshots__/welcome.stories.storyshot @@ -1,34 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Demo button 1`] = ` - -`; - -exports[`Storyshots Demo heading 1`] = ` -

- Hello World -

-`; - -exports[`Storyshots Demo headings 1`] = ` -
-

- Hello World -

-

- Hello World -

-

- Hello World -

-

- Hello World -

-
-`; - exports[`Storyshots Welcome Welcome 1`] = `
``) - .add('Label', () => ``) - .add('Disabled', () => ``) - .add( - 'Invalid contrast', - () => `` - ) - .add('Delayed render', () => { - const div = document.createElement('div'); - setTimeout(() => { - div.innerHTML = ``; - }, 1000); - return div; - }); +export default { + title: 'Addons|a11y', + decorators: [withA11y], + parameters: { + options: { selectedPanel: 'storybook/a11y/panel' }, + }, +}; + +export const Default = () => ``; +export const Label = () => ``; +export const Disabled = () => ``; +export const story4 = () => + ``; +story4.story = { name: 'Invalid contrast' }; + +export const story5 = () => { + const div = document.createElement('div'); + setTimeout(() => { + div.innerHTML = ``; + }, 1000); + return div; +}; +story5.story = { name: 'Delayed render' }; diff --git a/examples/html-kitchen-sink/stories/addon-actions.stories.js b/examples/html-kitchen-sink/stories/addon-actions.stories.js index 09f606d58dd..82008bb1115 100644 --- a/examples/html-kitchen-sink/stories/addon-actions.stories.js +++ b/examples/html-kitchen-sink/stories/addon-actions.stories.js @@ -1,34 +1,44 @@ -import { storiesOf } from '@storybook/html'; import { withActions, decorate } from '@storybook/addon-actions'; const pickTarget = decorate([args => [args[0].target]]); const button = () => ``; -storiesOf('Addons|Actions', module) - .add('Hello World', () => withActions('click')(button)) - .add('Multiple actions', () => withActions('click', 'contextmenu')(button)) - .add('Multiple actions + config', () => - withActions('click', 'contextmenu', { clearOnStoryChange: false })(button) - ) - .add('Multiple actions, object', () => - withActions({ click: 'clicked', contextmenu: 'right clicked' })(button) - ) - .add('Multiple actions, selector', () => - withActions({ 'click .btn': 'clicked', contextmenu: 'right clicked' })( - () => ` +export default { + title: 'Addons|Actions', +}; + +export const story1 = () => withActions('click')(button); +story1.story = { name: 'Hello World' }; +export const story2 = () => withActions('click', 'contextmenu')(button); +story2.story = { name: 'Multiple actions' }; + +export const story3 = () => + withActions('click', 'contextmenu', { clearOnStoryChange: false })(button); +story3.story = { name: 'Multiple actions + config' }; + +export const story4 = () => withActions({ click: 'clicked', contextmenu: 'right clicked' })(button); +story4.story = { name: 'Multiple actions, object' }; + +export const story5 = () => + withActions({ 'click .btn': 'clicked', contextmenu: 'right clicked' })( + () => `
Clicks on this button will be logged:
` - ) - ) - .add('Multiple actions, object + config', () => - withActions({ click: 'clicked', contextmenu: 'right clicked' }, { clearOnStoryChange: false })( - button - ) - ) - .add('Decorated actions', () => pickTarget.withActions('click', 'contextmenu')(button)) - .add('Decorated actions + config', () => - pickTarget.withActions('click', 'contextmenu', { clearOnStoryChange: false })(button) ); +story5.story = { name: 'Multiple actions, selector' }; + +export const story6 = () => + withActions({ click: 'clicked', contextmenu: 'right clicked' }, { clearOnStoryChange: false })( + button + ); +story6.story = { name: 'Multiple actions, object + config' }; + +export const story7 = () => pickTarget.withActions('click', 'contextmenu')(button); +story7.story = { name: 'Decorated actions' }; + +export const story8 = () => + pickTarget.withActions('click', 'contextmenu', { clearOnStoryChange: false })(button); +story8.story = { name: 'Decorated actions + config' }; diff --git a/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js b/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js index 7e8689f9656..4a63ab1fce6 100644 --- a/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js +++ b/examples/html-kitchen-sink/stories/addon-backgrounds.stories.js @@ -1,15 +1,16 @@ -import { storiesOf } from '@storybook/html'; - -storiesOf('Addons|Backgrounds', module) - .addParameters({ +export default { + title: 'Addons|Backgrounds', + parameters: { backgrounds: [ { name: 'light', value: '#eeeeee' }, { name: 'dark', value: '#222222', default: true }, ], - }) - .add( - 'story 1', - () => - 'You should be able to switch backgrounds for this story' - ) - .add('story 2', () => 'This one too!'); + }, +}; + +export const story1 = () => + 'You should be able to switch backgrounds for this story'; +story1.story = { name: 'story 1' }; + +export const story2 = () => 'This one too!'; +story2.story = { name: 'story 2' }; diff --git a/examples/html-kitchen-sink/stories/addon-centered.stories.js b/examples/html-kitchen-sink/stories/addon-centered.stories.js index 49edcdfb482..8242764f7fe 100644 --- a/examples/html-kitchen-sink/stories/addon-centered.stories.js +++ b/examples/html-kitchen-sink/stories/addon-centered.stories.js @@ -1,6 +1,9 @@ -import { storiesOf } from '@storybook/html'; import centered from '@storybook/addon-centered/html'; -storiesOf('Addons|Centered', module) - .addDecorator(centered) - .add('button in center', () => ''); +export default { + title: 'Addons|Centered', + decorators: [centered], +}; + +export const story1 = () => ''; +story1.story = { name: 'button in center' }; diff --git a/examples/html-kitchen-sink/stories/addon-events.stories.js b/examples/html-kitchen-sink/stories/addon-events.stories.js index 4fbac130097..c743cd7f685 100644 --- a/examples/html-kitchen-sink/stories/addon-events.stories.js +++ b/examples/html-kitchen-sink/stories/addon-events.stories.js @@ -1,5 +1,4 @@ import EventEmitter from 'eventemitter3'; -import { storiesOf } from '@storybook/html'; import addons from '@storybook/addons'; import { useEffect, useState } from '@storybook/client-api'; import CoreEvents from '@storybook/core-events'; @@ -19,8 +18,9 @@ const TEST_EVENTS = { const emitter = new EventEmitter(); const emit = emitter.emit.bind(emitter); -storiesOf('Addons|Events', module) - .addDecorator( +export default { + title: 'Addons|Events', + decorators: [ withEvents({ emit, events: [ @@ -70,41 +70,43 @@ storiesOf('Addons|Events', module) ], }, ], - }) - ) - .add('Logger', () => { - const [events, setEvents] = useState([]); - useEffect(() => { - const eventHandlers = Object.values(TEST_EVENTS).map(name => ({ - name, - handler: payload => { - setEvents(prevEvents => [...prevEvents, { name, payload }]); - }, - })); - eventHandlers.forEach(({ name, handler }) => emitter.on(name, handler)); - return () => - eventHandlers.forEach(({ name, handler }) => emitter.removeListener(name, handler)); - }, []); + }), + ], +}; - return ` -
-

Logger

-
- ${events - .map( - ({ name, payload }) => ` -
-
- Event name: ${name} -
-
- Event payload: ${json.plain(payload)} -
-
- ` - ) - .join('')} -
-
- `; - }); +export const Logger = () => { + const [events, setEvents] = useState([]); + useEffect(() => { + const eventHandlers = Object.values(TEST_EVENTS).map(name => ({ + name, + handler: payload => { + setEvents(prevEvents => [...prevEvents, { name, payload }]); + }, + })); + eventHandlers.forEach(({ name, handler }) => emitter.on(name, handler)); + return () => + eventHandlers.forEach(({ name, handler }) => emitter.removeListener(name, handler)); + }, []); + + return ` +
+

Logger

+
+ ${events + .map( + ({ name, payload }) => ` +
+
+ Event name: ${name} +
+
+ Event payload: ${json.plain(payload)} +
+
+ ` + ) + .join('')} +
+
+ `; +}; diff --git a/examples/html-kitchen-sink/stories/addon-jest.stories.js b/examples/html-kitchen-sink/stories/addon-jest.stories.js index 11a88e0570e..d39a86527ed 100644 --- a/examples/html-kitchen-sink/stories/addon-jest.stories.js +++ b/examples/html-kitchen-sink/stories/addon-jest.stories.js @@ -1,8 +1,10 @@ -import { storiesOf } from '@storybook/html'; - -import { withTests } from '@storybook/addon-jest'; +import { withTests as wt } from '@storybook/addon-jest'; import results from './addon-jest.testresults.json'; -storiesOf('Addons|Jest', module) - .addDecorator(withTests({ results })) - .add('withTests', () => 'This story shows test results', { jest: 'addon-jest' }); +export default { + title: 'Addons|Jest', + decorators: [wt({ results })], +}; + +export const withTests = () => 'This story shows test results'; +withTests.parameters = { jest: 'addon-jest' }; diff --git a/examples/html-kitchen-sink/stories/addon-knobs.stories.js b/examples/html-kitchen-sink/stories/addon-knobs.stories.js index 85a364b5b68..edae4ae8933 100644 --- a/examples/html-kitchen-sink/stories/addon-knobs.stories.js +++ b/examples/html-kitchen-sink/stories/addon-knobs.stories.js @@ -1,4 +1,3 @@ -import { storiesOf } from '@storybook/html'; import { action } from '@storybook/addon-actions'; import { document } from 'global'; @@ -15,63 +14,68 @@ import { } from '@storybook/addon-knobs'; const cachedContainer = document.createElement('p'); -storiesOf('Addons|Knobs', module) - .addDecorator(withKnobs) - .add('Simple', () => { - const name = text('Name', 'John Doe'); - const age = number('Age', 44); - const content = `I am ${name} and I'm ${age} years old.`; - return `
${content}
`; - }) - .add('DOM', () => { - const name = text('Name', 'John Doe'); - const container = document.createElement('p'); - container.textContent = name; - return container; - }) - .add('CSS transitions', () => { - const name = text('Name', 'John Doe'); - const textColor = color('Text color', 'orangered'); - cachedContainer.textContent = name; - cachedContainer.style.transition = 'color 0.5s ease-out'; - cachedContainer.style.color = textColor; - return cachedContainer; - }) - .add('All knobs', () => { - const name = text('Name', 'Jane'); - const stock = number('Stock', 20, { - range: true, - min: 0, - max: 30, - step: 5, - }); - const fruits = { - Apple: 'apples', - Banana: 'bananas', - Cherry: 'cherries', - }; - const fruit = select('Fruit', fruits, 'apples'); +export default { + title: 'Addons|Knobs', + decorators: [withKnobs], +}; - const price = number('Price', 2.25); +export const Simple = () => { + const name = text('Name', 'John Doe'); + const age = number('Age', 44); + const content = `I am ${name} and I'm ${age} years old.`; + return `
${content}
`; +}; - const colour = color('Border', 'deeppink'); - const today = date('Today', new Date('Jan 20 2017 GMT+0')); - const items = array('Items', ['Laptop', 'Book', 'Whiskey']); - const nice = boolean('Nice', true); +export const DOM = () => { + const name = text('Name', 'John Doe'); + const container = document.createElement('p'); + container.textContent = name; + return container; +}; - const stockMessage = stock - ? `I have a stock of ${stock} ${fruit}, costing $${price} each.` - : `I'm out of ${fruit}${nice ? ', Sorry!' : '.'}`; +export const story3 = () => { + const name = text('Name', 'John Doe'); + const textColor = color('Text color', 'orangered'); + cachedContainer.textContent = name; + cachedContainer.style.transition = 'color 0.5s ease-out'; + cachedContainer.style.color = textColor; + return cachedContainer; +}; +story3.story = { name: 'CSS transitions' }; - const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!'; - const dateOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }; +export const story4 = () => { + const name = text('Name', 'Jane'); + const stock = number('Stock', 20, { + range: true, + min: 0, + max: 30, + step: 5, + }); + const fruits = { + Apple: 'apples', + Banana: 'bananas', + Cherry: 'cherries', + }; + const fruit = select('Fruit', fruits, 'apples'); + const price = number('Price', 2.25); + const colour = color('Border', 'deeppink'); + const today = date('Today', new Date('Jan 20 2017 GMT+0')); + const items = array('Items', ['Laptop', 'Book', 'Whiskey']); + const nice = boolean('Nice', true); - button('Arbitrary action', action('You clicked it!')); + const stockMessage = stock + ? `I have a stock of ${stock} ${fruit}, costing $${price} each.` + : `I'm out of ${fruit}${nice ? ', Sorry!' : '.'}`; - const style = `border: 2px dotted ${colour}; padding: 8px 22px; border-radius: 8px`; + const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!'; + const dateOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }; - return `
+ button('Arbitrary action', action('You clicked it!')); + + const style = `border: 2px dotted ${colour}; padding: 8px 22px; border-radius: 8px`; + + return `

My name is ${name},

today is ${new Date(today).toLocaleDateString('en-US', dateOptions)}

${stockMessage}

@@ -80,5 +84,8 @@ storiesOf('Addons|Knobs', module)

${salutation}

`; - }) - .add('XSS safety', () => text('Rendered string', '')); +}; +story4.story = { name: 'All knobs' }; + +export const story5 = () => text('Rendered string', ''); +story5.story = { name: 'XSS safety' }; diff --git a/examples/html-kitchen-sink/stories/addon-notes.stories.js b/examples/html-kitchen-sink/stories/addon-notes.stories.js index fab6f368a32..8fd33be9c37 100644 --- a/examples/html-kitchen-sink/stories/addon-notes.stories.js +++ b/examples/html-kitchen-sink/stories/addon-notes.stories.js @@ -1,14 +1,16 @@ -import { storiesOf } from '@storybook/html'; +export default { + title: 'Addons|Notes', +}; -storiesOf('Addons|Notes', module).add( - 'Simple note', - () => - `

- - This is a fragment of HTML - -

`, - { +export const story1 = () => + `

+ + This is a fragment of HTML + +

`; +story1.story = { + name: 'Simple note', + parameters: { notes: 'My notes on some bold text', - } -); + }, +}; diff --git a/examples/html-kitchen-sink/stories/button.stories.js b/examples/html-kitchen-sink/stories/button.stories.js new file mode 100644 index 00000000000..02ed6aae869 --- /dev/null +++ b/examples/html-kitchen-sink/stories/button.stories.js @@ -0,0 +1,17 @@ +import { document } from 'global'; +import { action } from '@storybook/addon-actions'; + +export default { + title: 'Demo', +}; + +export const heading = () => '

Hello World

'; +export const headings = () => + '

Hello World

Hello World

Hello World

Hello World

'; + +export const button = () => { + const btn = document.createElement('button'); + btn.innerHTML = 'Hello Button'; + btn.addEventListener('click', action('Click')); + return btn; +}; diff --git a/examples/html-kitchen-sink/stories/index.stories.js b/examples/html-kitchen-sink/stories/index.stories.js deleted file mode 100644 index 1dcedbdb352..00000000000 --- a/examples/html-kitchen-sink/stories/index.stories.js +++ /dev/null @@ -1,24 +0,0 @@ -import { document } from 'global'; -import { storiesOf } from '@storybook/html'; -import { action } from '@storybook/addon-actions'; -import { withLinks } from '@storybook/addon-links'; - -import './welcome.css'; -import welcome from './welcome.html'; - -storiesOf('Welcome', module) - .addDecorator(withLinks) - .add('Welcome', () => welcome); - -storiesOf('Demo', module) - .add('heading', () => '

Hello World

') - .add( - 'headings', - () => '

Hello World

Hello World

Hello World

Hello World

' - ) - .add('button', () => { - const button = document.createElement('button'); - button.innerHTML = 'Hello Button'; - button.addEventListener('click', action('Click')); - return button; - }); diff --git a/examples/html-kitchen-sink/stories/welcome.stories.js b/examples/html-kitchen-sink/stories/welcome.stories.js new file mode 100644 index 00000000000..6410a83ee83 --- /dev/null +++ b/examples/html-kitchen-sink/stories/welcome.stories.js @@ -0,0 +1,11 @@ +import { withLinks } from '@storybook/addon-links'; + +import './welcome.css'; +import welcome from './welcome.html'; + +export default { + title: 'Welcome', + decorators: [withLinks], +}; + +export const Welcome = () => welcome; diff --git a/examples/html-kitchen-sink/tests/__snapshots__/htmlshots.test.js.snap b/examples/html-kitchen-sink/tests/__snapshots__/htmlshots.test.js.snap new file mode 100644 index 00000000000..0c1b56a014c --- /dev/null +++ b/examples/html-kitchen-sink/tests/__snapshots__/htmlshots.test.js.snap @@ -0,0 +1,513 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots Addons|Actions Decorated actions + config 1`] = ` + +`; + +exports[`Storyshots Addons|Actions Decorated actions 1`] = ` + +`; + +exports[`Storyshots Addons|Actions Hello World 1`] = ` + +`; + +exports[`Storyshots Addons|Actions Multiple actions + config 1`] = ` + +`; + +exports[`Storyshots Addons|Actions Multiple actions 1`] = ` + +`; + +exports[`Storyshots Addons|Actions Multiple actions, object + config 1`] = ` + +`; + +exports[`Storyshots Addons|Actions Multiple actions, object 1`] = ` + +`; + +exports[`Storyshots Addons|Actions Multiple actions, selector 1`] = ` + + +`; + +exports[`Storyshots Addons|Actions story1 1`] = ` + +`; + +exports[`Storyshots Addons|Actions story2 1`] = ` + +`; + +exports[`Storyshots Addons|Actions story3 1`] = ` + +`; + +exports[`Storyshots Addons|Actions story4 1`] = ` + +`; + +exports[`Storyshots Addons|Actions story5 1`] = ` + + +`; + +exports[`Storyshots Addons|Actions story6 1`] = ` + +`; + +exports[`Storyshots Addons|Actions story7 1`] = ` + +`; + +exports[`Storyshots Addons|Actions story8 1`] = ` + +`; + +exports[`Storyshots Addons|Backgrounds story 1 1`] = ` + + You should be able to switch backgrounds for this story + +`; + +exports[`Storyshots Addons|Backgrounds story 2 1`] = ` + + This one too! + +`; + +exports[`Storyshots Addons|Backgrounds story1 1`] = ` + + You should be able to switch backgrounds for this story + +`; + +exports[`Storyshots Addons|Backgrounds story2 1`] = ` + + This one too! + +`; + +exports[`Storyshots Addons|Centered button in center 1`] = ` +
+
+ +
+
+`; + +exports[`Storyshots Addons|Centered story1 1`] = ` +
+
+ +
+
+`; + +exports[`Storyshots Addons|Events Logger 1`] = ` + + +`; + +exports[`Storyshots Addons|Jest withTests 1`] = `This story shows test results`; + +exports[`Storyshots Addons|Knobs All knobs 1`] = ` +
+ + +

+ My name is Jane, +

+ + +

+ today is January 20, 2017 +

+ + +

+ I have a stock of 20 apples, costing $2.25 each. +

+ + +

+ Also, I have: +

+ + +
    +
  • + Laptop +
  • +
  • + Book +
  • +
  • + Whiskey +
  • +
+ + +

+ Nice to meet you! +

+ + +
+`; + +exports[`Storyshots Addons|Knobs CSS transitions 1`] = ` +

+ John Doe +

+`; + +exports[`Storyshots Addons|Knobs DOM 1`] = ` +

+ John Doe +

+`; + +exports[`Storyshots Addons|Knobs Simple 1`] = ` +
+ I am John Doe and I'm 44 years old. +
+`; + +exports[`Storyshots Addons|Knobs XSS safety 1`] = `<img src=x onerror="alert('XSS Attack')" >`; + +exports[`Storyshots Addons|Knobs story3 1`] = ` +

+ John Doe +

+`; + +exports[`Storyshots Addons|Knobs story4 1`] = ` +
+ + +

+ My name is Jane, +

+ + +

+ today is January 20, 2017 +

+ + +

+ I have a stock of 20 apples, costing $2.25 each. +

+ + +

+ Also, I have: +

+ + +
    +
  • + Laptop +
  • +
  • + Book +
  • +
  • + Whiskey +
  • +
+ + +

+ Nice to meet you! +

+ + +
+`; + +exports[`Storyshots Addons|Knobs story5 1`] = `<img src=x onerror="alert('XSS Attack')" >`; + +exports[`Storyshots Addons|Notes Simple note 1`] = ` +

+ + + + + This is a fragment of HTML + + + + +

+`; + +exports[`Storyshots Addons|Notes story1 1`] = ` +

+ + + + + This is a fragment of HTML + + + + +

+`; + +exports[`Storyshots Addons|a11y Default 1`] = ` +`; + +exports[`Storyshots Addons|a11y Invalid contrast 1`] = ` + +`; + +exports[`Storyshots Addons|a11y Label 1`] = ` + +`; + +exports[`Storyshots Addons|a11y story4 1`] = ` + +`; + +exports[`Storyshots Addons|a11y story5 1`] = `
`; + +exports[`Storyshots Demo button 1`] = ` + +`; + +exports[`Storyshots Demo heading 1`] = ` +

+ Hello World +

+`; + +exports[`Storyshots Demo headings 1`] = ` +
+

+ Hello World +

+

+ Hello World +

+

+ Hello World +

+

+ Hello World +

+
+`; + +exports[`Storyshots Welcome Welcome 1`] = ` +
+ + +

+ Welcome to Storybook for HTML +

+ + +

+ This is a UI component dev environment for your plain HTML snippets. +

+ + +

+ + We've added some basic stories inside the + + stories + + directory. + +
+ + A story is a single state of one or more UI components. You can have as many stories as you want. + +
+ + (Basically a story is like a visual test case.) + +

+ + +

+ + See these sample + + stories + + + +

+ + +

+ +

+ + +

+ + Just like that, you can add your own snippets as stories. + +
+ + You can also edit those snippets and see changes right away. + +
+ + +

+ + +

+ + Usually we create stories with smaller UI components in the app. +
+ + Have a look at the + + + + Writing Stories + + + + section in our documentation. + +

+ + +
+`; diff --git a/examples/marko-cli/.storybook/config.js b/examples/marko-cli/.storybook/config.js index bee4a674354..9964ec17b8e 100644 --- a/examples/marko-cli/.storybook/config.js +++ b/examples/marko-cli/.storybook/config.js @@ -1,4 +1,4 @@ -import { configure, addParameters, addDecorator } from '@storybook/marko'; +import { load, addParameters, addDecorator } from '@storybook/marko'; import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); @@ -8,13 +8,4 @@ addParameters({ }, }); -function loadStories() { - // put welcome screen at the top of the list so it's the first one displayed - // require('../src/stories/welcome'); - - // automatically import all story js files that end with *.stories.js - const req = require.context('../src/stories', true, /\.stories\.js$/); - req.keys().forEach(filename => req(filename)); -} - -configure(loadStories, module); +load(require.context('../src/stories', true, /\.stories\.js$/), module); diff --git a/examples/marko-cli/package.json b/examples/marko-cli/package.json index 57d3538ab5c..cfd96257e4a 100644 --- a/examples/marko-cli/package.json +++ b/examples/marko-cli/package.json @@ -1,6 +1,6 @@ { "name": "marko-cli", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "description": "Demo of how to build an app using marko-starter", "repository": { @@ -24,13 +24,14 @@ "marko-starter": "^2.0.4" }, "devDependencies": { - "@storybook/addon-a11y": "5.2.0-alpha.23", - "@storybook/addon-actions": "5.2.0-alpha.23", - "@storybook/addon-knobs": "5.2.0-alpha.23", - "@storybook/addon-options": "5.2.0-alpha.23", - "@storybook/addon-storysource": "5.2.0-alpha.23", - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/marko": "5.2.0-alpha.23", + "@storybook/addon-a11y": "5.2.0-alpha.32", + "@storybook/addon-actions": "5.2.0-alpha.32", + "@storybook/addon-knobs": "5.2.0-alpha.32", + "@storybook/addon-options": "5.2.0-alpha.32", + "@storybook/addon-storysource": "5.2.0-alpha.32", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/marko": "5.2.0-alpha.32", + "@storybook/source-loader": "5.2.0-alpha.32", "prettier": "^1.16.4", "webpack": "^4.33.0" } diff --git a/examples/marko-cli/src/stories/addon-actions.stories.js b/examples/marko-cli/src/stories/addon-actions.stories.js index 73d25b05d3f..aeb7e22788b 100644 --- a/examples/marko-cli/src/stories/addon-actions.stories.js +++ b/examples/marko-cli/src/stories/addon-actions.stories.js @@ -1,7 +1,11 @@ -import { storiesOf } from '@storybook/marko'; import { action } from '@storybook/addon-actions'; import Button from '../components/action-button/index.marko'; -storiesOf('Addons|Actions/Button', module).add('Simple', () => - Button.renderSync({ click: action('action logged!') }) -); +export default { + title: 'Addons|Actions/Button', + parameters: { + component: Button, + }, +}; + +export const Simple = () => Button.renderSync({ click: action('action logged!') }); diff --git a/examples/marko-cli/src/stories/addon-knobs.stories.js b/examples/marko-cli/src/stories/addon-knobs.stories.js index 5c44b59e9fc..88595ecee27 100644 --- a/examples/marko-cli/src/stories/addon-knobs.stories.js +++ b/examples/marko-cli/src/stories/addon-knobs.stories.js @@ -1,15 +1,20 @@ -import { storiesOf } from '@storybook/marko'; import { withKnobs, text, number } from '@storybook/addon-knobs'; import Hello from '../components/hello/index.marko'; -storiesOf('Addons|Knobs/Hello', module) - .addParameters({ options: { panelPosition: 'right' } }) - .addDecorator(withKnobs) - .add('Simple', () => { - const name = text('Name', 'John Doe'); - const age = number('Age', 44); - return Hello.renderSync({ - name, - age, - }); +export default { + title: 'Addons|Knobs/Hello', + decorators: [withKnobs], + parameters: { + component: Hello, + options: { panelPosition: 'right' }, + }, +}; + +export const Simple = () => { + const name = text('Name', 'John Doe'); + const age = number('Age', 44); + return Hello.renderSync({ + name, + age, }); +}; diff --git a/examples/marko-cli/src/stories/clickcount.stories.js b/examples/marko-cli/src/stories/clickcount.stories.js new file mode 100644 index 00000000000..351c07daca6 --- /dev/null +++ b/examples/marko-cli/src/stories/clickcount.stories.js @@ -0,0 +1,11 @@ +import ClickCount from '../components/click-count/index.marko'; + +export default { + title: 'Main|ClickCount', + + parameters: { + component: ClickCount, + }, +}; + +export const Simple = () => ClickCount.renderSync({}); diff --git a/examples/marko-cli/src/stories/hello.stories.js b/examples/marko-cli/src/stories/hello.stories.js new file mode 100644 index 00000000000..bdefe281dc1 --- /dev/null +++ b/examples/marko-cli/src/stories/hello.stories.js @@ -0,0 +1,12 @@ +import Hello from '../components/hello/index.marko'; + +export default { + title: 'Main|Hello', + parameters: { + component: Hello, + }, +}; + +export const Simple = () => Hello.renderSync({ name: 'abc', age: 20 }); +export const story2 = () => 'NOT A MARKO RENDER_RESULT'; +story2.story = { name: 'with ERROR!' }; diff --git a/examples/marko-cli/src/stories/index.stories.js b/examples/marko-cli/src/stories/index.stories.js deleted file mode 100644 index 8ef9e6d38cb..00000000000 --- a/examples/marko-cli/src/stories/index.stories.js +++ /dev/null @@ -1,15 +0,0 @@ -import { storiesOf } from '@storybook/marko'; -import Hello from '../components/hello/index.marko'; -import ClickCount from '../components/click-count/index.marko'; -import StopWatch from '../components/stop-watch/index.marko'; -import Welcome from '../components/welcome/index.marko'; - -storiesOf('Main|Welcome', module).add('welcome', () => Welcome.renderSync({})); - -storiesOf('Main|Hello', module) - .add('Simple', () => Hello.renderSync({ name: 'abc', age: 20 })) - .add('with ERROR!', () => 'NOT A MARKO RENDER_RESULT'); - -storiesOf('Main|ClickCount', module).add('Simple', () => ClickCount.renderSync({})); - -storiesOf('Main|StopWatch', module).add('Simple', () => StopWatch.renderSync({})); diff --git a/examples/marko-cli/src/stories/stopwatch.stories.js b/examples/marko-cli/src/stories/stopwatch.stories.js new file mode 100644 index 00000000000..3fc37effb06 --- /dev/null +++ b/examples/marko-cli/src/stories/stopwatch.stories.js @@ -0,0 +1,10 @@ +import StopWatch from '../components/stop-watch/index.marko'; + +export default { + title: 'Main|StopWatch', + parameters: { + component: StopWatch, + }, +}; + +export const Simple = () => StopWatch.renderSync({}); diff --git a/examples/marko-cli/src/stories/welcome.stories.js b/examples/marko-cli/src/stories/welcome.stories.js new file mode 100644 index 00000000000..9cd2db67709 --- /dev/null +++ b/examples/marko-cli/src/stories/welcome.stories.js @@ -0,0 +1,10 @@ +import Welcome from '../components/welcome/index.marko'; + +export default { + title: 'Main|Welcome', + parameters: { + component: Welcome, + }, +}; + +export const welcome = () => Welcome.renderSync({}); diff --git a/examples/mithril-kitchen-sink/.storybook/config.js b/examples/mithril-kitchen-sink/.storybook/config.js index 1155598a41c..952cb333b8c 100644 --- a/examples/mithril-kitchen-sink/.storybook/config.js +++ b/examples/mithril-kitchen-sink/.storybook/config.js @@ -1,4 +1,4 @@ -import { configure, addParameters, addDecorator } from '@storybook/mithril'; +import { load, addParameters, addDecorator } from '@storybook/mithril'; import { withA11y } from '@storybook/addon-a11y'; addDecorator(withA11y); @@ -8,9 +8,4 @@ addParameters({ }, }); -function loadStories() { - const req = require.context('../src/stories', true, /\.stories\.js$/); - req.keys().forEach(filename => req(filename)); -} - -configure(loadStories, module); +load(require.context('../src/stories', true, /\.stories\.js$/), module); diff --git a/examples/mithril-kitchen-sink/package.json b/examples/mithril-kitchen-sink/package.json index ea7802446a9..f43ee259f0f 100644 --- a/examples/mithril-kitchen-sink/package.json +++ b/examples/mithril-kitchen-sink/package.json @@ -1,6 +1,6 @@ { "name": "mithril-example", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "scripts": { "build-storybook": "build-storybook", @@ -11,19 +11,20 @@ "mithril": "^1.1.6" }, "devDependencies": { - "@storybook/addon-a11y": "5.2.0-alpha.23", - "@storybook/addon-actions": "5.2.0-alpha.23", - "@storybook/addon-backgrounds": "5.2.0-alpha.23", - "@storybook/addon-centered": "5.2.0-alpha.23", - "@storybook/addon-knobs": "5.2.0-alpha.23", - "@storybook/addon-links": "5.2.0-alpha.23", - "@storybook/addon-notes": "5.2.0-alpha.23", - "@storybook/addon-options": "5.2.0-alpha.23", - "@storybook/addon-storyshots": "5.2.0-alpha.23", - "@storybook/addon-storysource": "5.2.0-alpha.23", - "@storybook/addon-viewport": "5.2.0-alpha.23", - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/mithril": "5.2.0-alpha.23", + "@storybook/addon-a11y": "5.2.0-alpha.32", + "@storybook/addon-actions": "5.2.0-alpha.32", + "@storybook/addon-backgrounds": "5.2.0-alpha.32", + "@storybook/addon-centered": "5.2.0-alpha.32", + "@storybook/addon-knobs": "5.2.0-alpha.32", + "@storybook/addon-links": "5.2.0-alpha.32", + "@storybook/addon-notes": "5.2.0-alpha.32", + "@storybook/addon-options": "5.2.0-alpha.32", + "@storybook/addon-storyshots": "5.2.0-alpha.32", + "@storybook/addon-storysource": "5.2.0-alpha.32", + "@storybook/addon-viewport": "5.2.0-alpha.32", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/mithril": "5.2.0-alpha.32", + "@storybook/source-loader": "5.2.0-alpha.32", "webpack": "^4.33.0" } } diff --git a/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js index 358031795d4..58e06373596 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-actions.stories.js @@ -1,37 +1,44 @@ /** @jsx m */ import m from 'mithril'; - -import { storiesOf } from '@storybook/mithril'; import { action, actions } from '@storybook/addon-actions'; import Button from '../Button'; -storiesOf('Addons|Actions', module) - .add('Action only', () => ({ - view: () => , - })) - .add('Multiple actions', () => ({ - view: () => ( - - ), - })) - .add('Multiple actions, object', () => ({ - view: () => ( - - ), - })) +export default { + title: 'Addons|Actions', +}; - .add('Action and method', () => ({ - view: () => ( - - ), - })); +export const story1 = () => ({ + view: () => , +}); +story1.story = { name: 'Action only' }; + +export const story2 = () => ({ + view: () => ( + + ), +}); +story2.story = { name: 'Multiple actions' }; + +export const story3 = () => ({ + view: () => ( + + ), +}); +story3.story = { name: 'Multiple actions, object' }; + +export const story4 = () => ({ + view: () => ( + + ), +}); +story4.story = { name: 'Action and method' }; diff --git a/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js index ea67de2836c..2a6e62c39d3 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-backgrounds.stories.js @@ -1,21 +1,24 @@ /** @jsx m */ import m from 'mithril'; - -import { storiesOf } from '@storybook/mithril'; - import BaseButton from '../BaseButton'; -storiesOf('Addons|Backgrounds', module) - .addParameters({ +export default { + title: 'Addons|Backgrounds', + parameters: { backgrounds: [ { name: 'light', value: '#eeeeee' }, { name: 'dark', value: '#222222', default: true }, ], - }) - .add('story 1', () => ({ - view: () => , - })) - .add('story 2', () => ({ - view: () => , - })); + }, +}; + +export const story1 = () => ({ + view: () => , +}); +story1.story = { name: 'story 1' }; + +export const story2 = () => ({ + view: () => , +}); +story2.story = { name: 'story 2' }; diff --git a/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js index e97deabdef5..f646d74b4a2 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-centered.stories.js @@ -1,13 +1,17 @@ /** @jsx m */ import m from 'mithril'; - -import { storiesOf } from '@storybook/mithril'; import Centered from '@storybook/addon-centered/mithril'; import Button from '../Button'; -storiesOf('Addons|Centered', module) - .addDecorator(Centered) - .add('button', () => ({ - view: () => , - })); +export default { + title: 'Addons|Centered', + decorators: [Centered], + parameters: { + component: Centered, + }, +}; + +export const button = () => ({ + view: () => , +}); diff --git a/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js index 244a3bd8a50..6d08bc923f1 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-knobs.stories.js @@ -1,8 +1,6 @@ /** @jsx m */ import m from 'mithril'; - -import { storiesOf } from '@storybook/mithril'; import { action } from '@storybook/addon-actions'; import { withKnobs, @@ -16,63 +14,70 @@ import { button, } from '@storybook/addon-knobs'; -storiesOf('Addons|Knobs', module) - .addDecorator(withKnobs) - .add('Simple', () => { - const name = text('Name', 'John Doe'); - const age = number('Age', 44); - const content = `I am ${name} and I'm ${age} years old.`; +export default { + title: 'Addons|Knobs', + decorators: [withKnobs], +}; - return { - view: () =>
{content}
, - }; - }) - .add('All knobs', () => { - const name = text('Name', 'Jane'); - const stock = number('Stock', 20, { - range: true, - min: 0, - max: 30, - step: 5, - }); - const fruits = { - Apple: 'apples', - Banana: 'bananas', - Cherry: 'cherries', - }; - const fruit = select('Fruit', fruits, 'apples'); - const price = number('Price', 2.25); +export const Simple = () => { + const name = text('Name', 'John Doe'); + const age = number('Age', 44); + const content = `I am ${name} and I'm ${age} years old.`; - const colour = color('Border', 'deeppink'); - const today = date('Today', new Date('Jan 20 2017 GMT+0')); - const items = array('Items', ['Laptop', 'Book', 'Whiskey']); - const nice = boolean('Nice', true); + return { + view: () =>
{content}
, + }; +}; - const stockMessage = stock - ? `I have a stock of ${stock} ${fruit}, costing $${price} each.` - : `I'm out of ${fruit}${nice ? ', Sorry!' : '.'}`; - const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!'; - const dateOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }; +export const story2 = () => { + const name = text('Name', 'Jane'); + const stock = number('Stock', 20, { + range: true, + min: 0, + max: 30, + step: 5, + }); + const fruits = { + Apple: 'apples', + Banana: 'bananas', + Cherry: 'cherries', + }; + const fruit = select('Fruit', fruits, 'apples'); + const price = number('Price', 2.25); - button('Arbitrary action', action('You clicked it!')); + const colour = color('Border', 'deeppink'); + const today = date('Today', new Date('Jan 20 2017 GMT+0')); + const items = array('Items', ['Laptop', 'Book', 'Whiskey']); + const nice = boolean('Nice', true); - return { - view: () => ( -
-

My name is {name},

-

today is {new Date(today).toLocaleDateString('en-US', dateOptions)}

-

{stockMessage}

-

Also, I have:

-
    - {items.map(item => ( -
  • {item}
  • - ))} -
-

{salutation}

-
- ), - }; - }) - .add('XSS safety', () => ({ - view: () => text('Rendered string', ''), - })); + const stockMessage = stock + ? `I have a stock of ${stock} ${fruit}, costing $${price} each.` + : `I'm out of ${fruit}${nice ? ', Sorry!' : '.'}`; + const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!'; + const dateOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }; + + button('Arbitrary action', action('You clicked it!')); + + return { + view: () => ( +
+

My name is {name},

+

today is {new Date(today).toLocaleDateString('en-US', dateOptions)}

+

{stockMessage}

+

Also, I have:

+
    + {items.map(item => ( +
  • {item}
  • + ))} +
+

{salutation}

+
+ ), + }; +}; +story2.story = { name: 'All knobs' }; + +export const story3 = () => ({ + view: () => text('Rendered string', ''), +}); +story3.story = { name: 'XSS safety' }; diff --git a/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js index 51e78629336..63ea9c04ab5 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-links.stories.js @@ -2,10 +2,14 @@ import m from 'mithril'; -import { storiesOf } from '@storybook/mithril'; import { linkTo } from '@storybook/addon-links'; import Button from '../Button'; -storiesOf('Addons|Links', module).add('Go to welcome', () => ({ +export default { + title: 'Addons|Links', +}; + +export const story1 = () => ({ view: () => , -})); +}); +story1.story = { name: 'Go to welcome' }; diff --git a/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js b/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js index 4e5287f1aeb..6af53269ecd 100644 --- a/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js +++ b/examples/mithril-kitchen-sink/src/stories/addon-notes.stories.js @@ -1,47 +1,52 @@ /** @jsx m */ import m from 'mithril'; -import { storiesOf } from '@storybook/mithril'; -storiesOf('Addons|Notes', module) - .add( - 'Simple note', - () => ({ - view: () => ( -

- - Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam - sed vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec - consectetur velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus - arcu. Nullam sit amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at - fermentum. Nulla sollicitudin, mauris quis semper tempus, sem metus tristique diam, - efficitur pulvinar mi urna id urna. - -

- ), - }), - { notes: 'My notes on some bold text' } - ) - .add( - 'Note with HTML', - () => ({ - view: () => ( -

- ๐Ÿค”๐Ÿ˜ณ๐Ÿ˜ฏ๐Ÿ˜ฎ -
- ๐Ÿ˜„๐Ÿ˜ฉ๐Ÿ˜“๐Ÿ˜ฑ -
- ๐Ÿค“๐Ÿ˜‘๐Ÿ˜ถ๐Ÿ˜Š -

- ), - }), - { - notes: ` -

My notes on emojies

+export default { + title: 'Addons|Notes', +}; - It's not all that important to be honest, but.. +export const story1 = () => ({ + view: () => ( +

+ + Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam sed + vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec consectetur + velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus arcu. Nullam sit + amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at fermentum. Nulla + sollicitudin, mauris quis semper tempus, sem metus tristique diam, efficitur pulvinar mi + urna id urna. + +

+ ), +}); - Emojis are great, I love emojis, in fact I like using them in my Component notes too! ๐Ÿ˜‡ - `, - } - ); +story1.story = { + name: 'Simple note', + parameters: { notes: 'My notes on some bold text' }, +}; + +export const story2 = () => ({ + view: () => ( +

+ ๐Ÿค”๐Ÿ˜ณ๐Ÿ˜ฏ๐Ÿ˜ฎ +
+ ๐Ÿ˜„๐Ÿ˜ฉ๐Ÿ˜“๐Ÿ˜ฑ +
+ ๐Ÿค“๐Ÿ˜‘๐Ÿ˜ถ๐Ÿ˜Š +

+ ), +}); + +story2.story = { + name: 'Note with HTML', + parameters: { + notes: ` +

My notes on emojies

+ + It's not all that important to be honest, but.. + + Emojis are great, I love emojis, in fact I like using them in my Component notes too! ๐Ÿ˜‡ + `, + }, +}; diff --git a/examples/mithril-kitchen-sink/src/stories/button.stories.js b/examples/mithril-kitchen-sink/src/stories/button.stories.js new file mode 100644 index 00000000000..ef051b16dec --- /dev/null +++ b/examples/mithril-kitchen-sink/src/stories/button.stories.js @@ -0,0 +1,28 @@ +import m from 'mithril'; + +import { action } from '@storybook/addon-actions'; +import { linkTo } from '@storybook/addon-links'; + +import Button from '../Button'; + +export default { + title: 'Button', + parameters: { + component: Button, + }, +}; + +export const story1 = () => ({ + view: () => m(Button, { onclick: action('clicked') }, 'Hello Button'), +}); +story1.story = { name: 'with text' }; + +export const story2 = () => ({ + view: () => + m( + Button, + { onclick: action('clicked') }, + m('span', { role: 'img', ariaLabel: 'so cool' }, '๐Ÿ˜€ ๐Ÿ˜Ž ๐Ÿ‘ ๐Ÿ’ฏ') + ), +}); +story2.story = { name: 'with some emoji' }; diff --git a/examples/mithril-kitchen-sink/src/stories/index.stories.js b/examples/mithril-kitchen-sink/src/stories/index.stories.js deleted file mode 100644 index a0952e562bf..00000000000 --- a/examples/mithril-kitchen-sink/src/stories/index.stories.js +++ /dev/null @@ -1,25 +0,0 @@ -import m from 'mithril'; - -import { storiesOf } from '@storybook/mithril'; -import { action } from '@storybook/addon-actions'; -import { linkTo } from '@storybook/addon-links'; - -import Button from '../Button'; -import Welcome from '../Welcome'; - -storiesOf('Welcome', module).add('to Storybook', () => ({ - view: () => m(Welcome, { showApp: linkTo('Button') }), -})); - -storiesOf('Button', module) - .add('with text', () => ({ - view: () => m(Button, { onclick: action('clicked') }, 'Hello Button'), - })) - .add('with some emoji', () => ({ - view: () => - m( - Button, - { onclick: action('clicked') }, - m('span', { role: 'img', ariaLabel: 'so cool' }, '๐Ÿ˜€ ๐Ÿ˜Ž ๐Ÿ‘ ๐Ÿ’ฏ') - ), - })); diff --git a/examples/mithril-kitchen-sink/src/stories/welcome.stories.js b/examples/mithril-kitchen-sink/src/stories/welcome.stories.js new file mode 100644 index 00000000000..a67ad2aa91a --- /dev/null +++ b/examples/mithril-kitchen-sink/src/stories/welcome.stories.js @@ -0,0 +1,15 @@ +import m from 'mithril'; +import { linkTo } from '@storybook/addon-links'; +import Welcome from '../Welcome'; + +export default { + title: 'Welcome', + parameters: { + component: Welcome, + }, +}; + +export const story1 = () => ({ + view: () => m(Welcome, { showApp: linkTo('Button') }), +}); +story1.story = { name: 'to Storybook' }; diff --git a/examples/official-storybook/config.js b/examples/official-storybook/config.js index 2e996bd8c0c..ae4db10692d 100644 --- a/examples/official-storybook/config.js +++ b/examples/official-storybook/config.js @@ -1,6 +1,7 @@ import React from 'react'; import { load, addDecorator, addParameters } from '@storybook/react'; import { Global, ThemeProvider, themes, createReset, convert } from '@storybook/theming'; +import { DocsPage } from '@storybook/addon-docs/blocks'; import { withCssResources } from '@storybook/addon-cssresources'; import { withA11y } from '@storybook/addon-a11y'; @@ -49,15 +50,17 @@ addParameters({ options: { hierarchySeparator: /\/|\./, hierarchyRootSeparator: '|', - theme: { base: 'light', brandTitle: 'Storybook!' }, + theme: themes.light, // { base: 'dark', brandTitle: 'Storybook!' }, }, backgrounds: [ { name: 'storybook app', value: themes.light.appBg, default: true }, { name: 'light', value: '#eeeeee' }, { name: 'dark', value: '#222222' }, ], + docs: DocsPage, }); load(require.context('../../lib/ui/src', true, /\.stories\.js$/), module); load(require.context('../../lib/components/src', true, /\.stories\.tsx?$/), module); load(require.context('./stories', true, /\.stories\.js$/), module); +load(require.context('./stories', true, /\.stories\.mdx$/), module); diff --git a/examples/official-storybook/package.json b/examples/official-storybook/package.json index 68da0571779..8b2d308072e 100644 --- a/examples/official-storybook/package.json +++ b/examples/official-storybook/package.json @@ -1,6 +1,6 @@ { "name": "official-storybook", - "version": "5.2.0-alpha.23", + "version": "5.2.0-alpha.32", "private": true, "scripts": { "build-storybook": "build-storybook -c ./ -s built-storybooks", @@ -15,33 +15,34 @@ }, "devDependencies": { "@packtracker/webpack-plugin": "^2.0.1", - "@storybook/addon-a11y": "5.2.0-alpha.23", - "@storybook/addon-actions": "5.2.0-alpha.23", - "@storybook/addon-backgrounds": "5.2.0-alpha.23", - "@storybook/addon-centered": "5.2.0-alpha.23", - "@storybook/addon-contexts": "5.2.0-alpha.23", - "@storybook/addon-cssresources": "5.2.0-alpha.23", - "@storybook/addon-design-assets": "5.2.0-alpha.23", - "@storybook/addon-docs": "5.2.0-alpha.23", - "@storybook/addon-events": "5.2.0-alpha.23", - "@storybook/addon-graphql": "5.2.0-alpha.23", - "@storybook/addon-info": "5.2.0-alpha.23", - "@storybook/addon-jest": "5.2.0-alpha.23", - "@storybook/addon-knobs": "5.2.0-alpha.23", - "@storybook/addon-links": "5.2.0-alpha.23", - "@storybook/addon-notes": "5.2.0-alpha.23", - "@storybook/addon-options": "5.2.0-alpha.23", - "@storybook/addon-queryparams": "5.2.0-alpha.23", - "@storybook/addon-storyshots": "5.2.0-alpha.23", - "@storybook/addon-storyshots-puppeteer": "5.2.0-alpha.23", - "@storybook/addon-storysource": "5.2.0-alpha.23", - "@storybook/addon-viewport": "5.2.0-alpha.23", - "@storybook/addons": "5.2.0-alpha.23", - "@storybook/components": "5.2.0-alpha.23", - "@storybook/core-events": "5.2.0-alpha.23", - "@storybook/node-logger": "5.2.0-alpha.23", - "@storybook/react": "5.2.0-alpha.23", - "@storybook/theming": "5.2.0-alpha.23", + "@storybook/addon-a11y": "5.2.0-alpha.32", + "@storybook/addon-actions": "5.2.0-alpha.32", + "@storybook/addon-backgrounds": "5.2.0-alpha.32", + "@storybook/addon-centered": "5.2.0-alpha.32", + "@storybook/addon-contexts": "5.2.0-alpha.32", + "@storybook/addon-cssresources": "5.2.0-alpha.32", + "@storybook/addon-design-assets": "5.2.0-alpha.32", + "@storybook/addon-docs": "5.2.0-alpha.32", + "@storybook/addon-events": "5.2.0-alpha.32", + "@storybook/addon-graphql": "5.2.0-alpha.32", + "@storybook/addon-info": "5.2.0-alpha.32", + "@storybook/addon-jest": "5.2.0-alpha.32", + "@storybook/addon-knobs": "5.2.0-alpha.32", + "@storybook/addon-links": "5.2.0-alpha.32", + "@storybook/addon-notes": "5.2.0-alpha.32", + "@storybook/addon-options": "5.2.0-alpha.32", + "@storybook/addon-queryparams": "5.2.0-alpha.32", + "@storybook/addon-storyshots": "5.2.0-alpha.32", + "@storybook/addon-storyshots-puppeteer": "5.2.0-alpha.32", + "@storybook/addon-storysource": "5.2.0-alpha.32", + "@storybook/addon-viewport": "5.2.0-alpha.32", + "@storybook/addons": "5.2.0-alpha.32", + "@storybook/components": "5.2.0-alpha.32", + "@storybook/core-events": "5.2.0-alpha.32", + "@storybook/node-logger": "5.2.0-alpha.32", + "@storybook/react": "5.2.0-alpha.32", + "@storybook/source-loader": "5.2.0-alpha.32", + "@storybook/theming": "5.2.0-alpha.32", "cors": "^2.8.5", "cross-env": "^5.2.0", "enzyme-to-json": "^3.3.5", diff --git a/examples/official-storybook/presets.js b/examples/official-storybook/presets.js new file mode 100644 index 00000000000..b1d463490f6 --- /dev/null +++ b/examples/official-storybook/presets.js @@ -0,0 +1 @@ +module.exports = ['@storybook/addon-docs/react/preset']; diff --git a/examples/official-storybook/stories/__snapshots__/addon-docs.stories.storyshot b/examples/official-storybook/stories/__snapshots__/addon-docs.stories.storyshot deleted file mode 100644 index e7ee2efa9cd..00000000000 --- a/examples/official-storybook/stories/__snapshots__/addon-docs.stories.storyshot +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Storyshots Addons|Docs default 1`] = ` -
- Click the docs tab to see the docs -
-`; diff --git a/examples/official-storybook/stories/addon-a11y.stories.js b/examples/official-storybook/stories/addon-a11y.stories.js deleted file mode 100644 index a4717e3ec9e..00000000000 --- a/examples/official-storybook/stories/addon-a11y.stories.js +++ /dev/null @@ -1,86 +0,0 @@ -import React, { Fragment } from 'react'; -import { storiesOf } from '@storybook/react'; - -import { Form } from '@storybook/components'; -import BaseButton from '../components/BaseButton'; -import DelayedRender from '../components/DelayedRender'; -import Button from '../components/addon-a11y/Button'; - -const text = 'Testing the a11y addon'; -const image = 'http://placehold.it/350x150'; -// eslint-disable-next-line no-script-url -const href = 'javascript:void 0'; - -storiesOf('Addons|A11y/BaseButton', module) - .addParameters({ options: { selectedPanel: 'storybook/a11y/panel' } }) - .add('Default', () => ) - .add('Label', () => ) - .add('Disabled', () => ) - .add('Invalid contrast', () => ( - // FIXME: has no effect on score - - )) - .add('delayed render', () => ( - - - - )); - -storiesOf('Addons|A11y/Button', module) - .addParameters({ options: { selectedPanel: 'storybook/a11y/panel' } }) - .add('Default', () => ) - .add('Multiple actions', () => ( - - )) - .add('Multiple actions + config', () => ( - - )) - .add('Multiple actions as object', () => ( - - )) - .add('Multiple actions, object + config', () => ( - - )) - .add('Decorated action', () => ( - - )) - .add('Decorated action + config', () => ( - - )) - .add('Decorated actions', () => ( - - )) - .add('Decorated actions + config', () => ( - - )) - .add('Circular Payload', () => { - const circular = { foo: {} }; - circular.foo.circular = circular; - return ; - }) - .add('Reserved keyword as name', () => ) - .add('All types', () => { - function A() {} - function B() {} +export const basicExample = () => ; - const bound = B.bind({}); +basicExample.story = { + name: 'Basic example', +}; - let file; - try { - file = new File([''], 'filename.txt', { type: 'text/plain', lastModified: new Date() }); - } catch (error) { - file = error; - } - const reg = /fooBar/g; +export const multipleActions = () => ( + +); - return ( - - - - - - - - - - - - - - - - - - - - - - - ); - }) +multipleActions.story = { + name: 'Multiple actions', +}; - .add('configureActionsDepth', () => { - configureActions({ - depth: 2, - }); +export const multipleActionsConfig = () => ( + +); - return ( - - ); - }) - .add('Persisting the action logger', () => ( +multipleActionsConfig.story = { + name: 'Multiple actions + config', +}; + +export const multipleActionsAsObject = () => ( + +); + +multipleActionsAsObject.story = { + name: 'Multiple actions as object', +}; + +export const multipleActionsObjectConfig = () => ( + +); + +multipleActionsObjectConfig.story = { + name: 'Multiple actions, object + config', +}; + +export const decoratedAction = () => ( + +); + +decoratedAction.story = { + name: 'Decorated action', +}; + +export const decoratedActionConfig = () => ( + +); + +decoratedActionConfig.story = { + name: 'Decorated action + config', +}; + +export const decoratedActions = () => ( + +); + +decoratedActions.story = { + name: 'Decorated actions', +}; + +export const decoratedActionsConfig = () => ( + +); + +decoratedActionsConfig.story = { + name: 'Decorated actions + config', +}; + +export const circularPayload = () => { + const circular = { foo: {} }; + circular.foo.circular = circular; + return ; +}; + +circularPayload.story = { + name: 'Circular Payload', +}; + +export const reservedKeywordAsName = () => ; + +reservedKeywordAsName.story = { + name: 'Reserved keyword as name', +}; + +export const allTypes = () => { + function A() {} + function B() {} + + const bound = B.bind({}); + + let file; + try { + file = new File([''], 'filename.txt', { type: 'text/plain', lastModified: new Date() }); + } catch (error) { + file = error; + } + const reg = /fooBar/g; + + return ( -

Moving away from this story will persist the action logger

- + + + + + + + + + + + + + + + + + + +
- )) - .add('Limit Action Output', () => { - configureActions({ - limit: 2, - }); + ); +}; - return ( - - - - - ); +allTypes.story = { + name: 'All types', +}; + +export const configureActionsDepth = () => { + configureActions({ + depth: 2, }); -storiesOf('Addons|Actions.deprecated', module).add('Decorated Action', () => ( - -)); + return ( + + ); +}; + +export const persistingTheActionLogger = () => ( + +

Moving away from this story will persist the action logger

+ +
+); + +persistingTheActionLogger.story = { + name: 'Persisting the action logger', +}; + +export const limitActionOutput = () => { + configureActions({ + limit: 2, + }); + + return ( + + + + + ); +}; +limitActionOutput.story = { + name: 'Limit Action Output', +}; diff --git a/examples/official-storybook/stories/addon-backgrounds.stories.js b/examples/official-storybook/stories/addon-backgrounds.stories.js index dc8cfbd0060..bf16d591860 100644 --- a/examples/official-storybook/stories/addon-backgrounds.stories.js +++ b/examples/official-storybook/stories/addon-backgrounds.stories.js @@ -1,10 +1,11 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; import BaseButton from '../components/BaseButton'; -storiesOf('Addons|Backgrounds', module) - .addParameters({ +export default { + title: 'Addons|Backgrounds', + + parameters: { backgrounds: [ { name: 'white', value: '#ffffff' }, { name: 'light', value: '#eeeeee' }, @@ -12,24 +13,52 @@ storiesOf('Addons|Backgrounds', module) { name: 'dark', value: '#222222', default: true }, { name: 'black', value: '#000000' }, ], - }) - .add('story 1', () => ( - - )) - .add('story 2', () => ) - .add('overriden', () => , { + }, +}; + +export const story1 = () => ( + +); + +story1.story = { + name: 'story 1', +}; + +export const story2 = () => ; + +story2.story = { + name: 'story 2', +}; + +export const overriden = () => ; + +overriden.story = { + parameters: { backgrounds: [ { name: 'pink', value: 'hotpink' }, { name: 'blue', value: 'deepskyblue', default: true }, ], - }) - .add('disabled via []', () => , { + }, +}; + +export const disabledVia = () => ; + +disabledVia.story = { + name: 'disabled via []', + + parameters: { backgrounds: [], - }) - .add( - 'skipped via disable:true', - () => , - { - backgrounds: { disable: true }, - } - ); + }, +}; + +export const skippedViaDisableTrue = () => ( + +); + +skippedViaDisableTrue.story = { + name: 'skipped via disable:true', + + parameters: { + backgrounds: { disable: true }, + }, +}; diff --git a/examples/official-storybook/stories/addon-centered.stories.js b/examples/official-storybook/stories/addon-centered.stories.js index 743e753dd89..a657323ae1f 100644 --- a/examples/official-storybook/stories/addon-centered.stories.js +++ b/examples/official-storybook/stories/addon-centered.stories.js @@ -1,9 +1,15 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; import centered from '@storybook/addon-centered/react'; import BaseButton from '../components/BaseButton'; -storiesOf('Addons|Centered', module) - .addDecorator(centered) - .add('story 1', () => ); +export default { + title: 'Addons|Centered', + decorators: [centered], +}; + +export const story1 = () => ; + +story1.story = { + name: 'story 1', +}; diff --git a/examples/official-storybook/stories/addon-contexts.stories.js b/examples/official-storybook/stories/addon-contexts.stories.js index 7f646826d73..9edc06cbf67 100644 --- a/examples/official-storybook/stories/addon-contexts.stories.js +++ b/examples/official-storybook/stories/addon-contexts.stories.js @@ -1,5 +1,4 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; import { withContexts } from '@storybook/addon-contexts/react'; // Example A: Simple CSS Theming @@ -39,15 +38,20 @@ const storyLevelContexts = [ }, ]; -const stories = storiesOf('Addons|Contexts', module).addDecorator(withContexts(topLevelContexts)); +export default { + title: 'Addons|Contexts', + decorators: [withContexts(topLevelContexts)], +}; -stories.add( - 'Simple CSS Theming', - () => <>I'm a children of the injected 'div' (where provides a theming context)., - { - contexts: storyLevelContexts, - } +export const simpleCssTheming = () => ( + <>I'm a children of the injected 'div' (where provides a theming context). ); +simpleCssTheming.story = { + name: 'Simple CSS Theming', + parameters: { + contexts: storyLevelContexts, + }, +}; // Example B: Language (React Contexts API) const NaiveIntlContext = React.createContext({ @@ -55,14 +59,14 @@ const NaiveIntlContext = React.createContext({ greeting: 'NULL', }); -stories.add( - 'Languages', - () => ( - - {({ locale, greeting }) => `Your locale is "${locale}", so I say "${greeting}"!`} - - ), - { +export const Languages = () => ( + + {({ locale, greeting }) => `Your locale is "${locale}", so I say "${greeting}"!`} + +); + +Languages.story = { + parameters: { contexts: [ { icon: 'globe', @@ -93,5 +97,5 @@ stories.add( }, }, ], - } -); + }, +}; diff --git a/examples/official-storybook/stories/addon-cssresources.stories.js b/examples/official-storybook/stories/addon-cssresources.stories.js index 4cc9bceef29..70a29ac628e 100644 --- a/examples/official-storybook/stories/addon-cssresources.stories.js +++ b/examples/official-storybook/stories/addon-cssresources.stories.js @@ -1,8 +1,17 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; -storiesOf('Addons|Cssresources', module) - .addParameters({ +export default { + title: 'Addons|Cssresources', +}; + +export const primaryLargeButton = () => ( + +); +primaryLargeButton.story = { + name: 'Primary Large Button', + parameters: { cssresources: [ { id: `bootstrap v4.1.3`, @@ -18,15 +27,13 @@ storiesOf('Addons|Cssresources', module) options: { selectedPanel: 'storybook/cssresources/panel', }, - }) - .add('Primary Large Button', () => ( - - )); + }, +}; -storiesOf('Addons|Cssresources', module) - .addParameters({ +export const cameraIcon = () => Camera Icon; +cameraIcon.story = { + name: 'Camera Icon', + parameters: { cssresources: [ { id: `fontawesome`, @@ -42,6 +49,5 @@ storiesOf('Addons|Cssresources', module) options: { selectedPanel: 'storybook/cssresources/panel', }, - }) - - .add('Camera Icon', () => Camera Icon); + }, +}; diff --git a/examples/official-storybook/stories/addon-design-assets.stories.js b/examples/official-storybook/stories/addon-design-assets.stories.js index da56eca8c52..9b5185fcea5 100644 --- a/examples/official-storybook/stories/addon-design-assets.stories.js +++ b/examples/official-storybook/stories/addon-design-assets.stories.js @@ -1,33 +1,66 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; -storiesOf('Addons|Design assets', module) - .addParameters({ +export default { + title: 'Addons|Design assets', + + parameters: { options: { selectedPanel: 'storybook/design-assets/panel', }, - }) - .add('single image', () =>
This story should a single image in the assets panel
, { - assets: ['https://via.placeholder.com/300/09f/fff.png'], - }) - .add('single webpage', () =>
This story should a single image in the assets panel
, { - assets: ['https://www.example.com'], - }) - .add('youtube video', () =>
This story should a single image in the assets panel
, { - assets: ['https://www.youtube.com/embed/p-LFh5Y89eM'], - }) + }, +}; - .add( - 'multiple images', - () =>
This story should a multiple images in the assets panel
, - { - assets: [ - 'https://via.placeholder.com/600/09f/fff.png', - 'https://via.placeholder.com/600/f90/fff.png', - ], - } - ) - .add('named assets', () =>
This story should a single image in the assets panel
, { +export const singleImage = () =>
This story should a single image in the assets panel
; + +singleImage.story = { + name: 'single image', + + parameters: { + assets: ['https://via.placeholder.com/300/09f/fff.png'], + }, +}; + +export const singleWebpage = () =>
This story should a single image in the assets panel
; + +singleWebpage.story = { + name: 'single webpage', + + parameters: { + assets: ['https://www.example.com'], + }, +}; + +export const youtubeVideo = () =>
This story should a single image in the assets panel
; + +youtubeVideo.story = { + name: 'youtube video', + + parameters: { + assets: ['https://www.youtube.com/embed/p-LFh5Y89eM'], + }, +}; + +export const multipleImages = () => ( +
This story should a multiple images in the assets panel
+); + +multipleImages.story = { + name: 'multiple images', + + parameters: { + assets: [ + 'https://via.placeholder.com/600/09f/fff.png', + 'https://via.placeholder.com/600/f90/fff.png', + ], + }, +}; + +export const namedAssets = () =>
This story should a single image in the assets panel
; + +namedAssets.story = { + name: 'named assets', + + parameters: { assets: [ { name: 'blue', @@ -38,11 +71,17 @@ storiesOf('Addons|Design assets', module) url: 'https://via.placeholder.com/300/f90/fff.png', }, ], - }) - .add( - 'url replacement', - () =>
This story should have a webpge, with within it's url the storyId
, - { - assets: ['https://via.placeholder.com/600.png?text={id}'], - } - ); + }, +}; + +export const urlReplacement = () => ( +
This story should have a webpge, with within it's url the storyId
+); + +urlReplacement.story = { + name: 'url replacement', + + parameters: { + assets: ['https://via.placeholder.com/600.png?text={id}'], + }, +}; diff --git a/examples/official-storybook/stories/addon-docs.stories.js b/examples/official-storybook/stories/addon-docs.stories.js index 5571d08c30c..163744b595a 100644 --- a/examples/official-storybook/stories/addon-docs.stories.js +++ b/examples/official-storybook/stories/addon-docs.stories.js @@ -1,8 +1,43 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; +import notes from './notes/notes.md'; +import mdxNotes from './notes/notes.mdx'; +import DocgenButton from '../components/DocgenButton'; -storiesOf('Addons|Docs', module) - .addParameters({ +export default { + title: 'Addons|Docs/stories', + parameters: { + component: DocgenButton, + }, +}; + +export const basic = () =>
Click docs tab to see basic docs
; + +export const withNotes = () =>
Click docs tab to see DocsPage docs
; +withNotes.story = { + name: 'with notes', + parameters: { notes }, +}; + +export const withInfo = () =>
Click docs tab to see DocsPage docs
; +withInfo.story = { + name: 'with info', + parameters: { + info: 'some user info string', + }, +}; + +export const mdxOverride = () =>
Click docs tab to see MDX-overridden docs
; +mdxOverride.story = { + name: 'mdx override', + parameters: { + docs: mdxNotes, + }, +}; + +export const jsxOverride = () =>
Click docs tab to see JSX-overridden docs
; +jsxOverride.story = { + name: 'jsx override', + parameters: { docs: () =>
Hello docs
, - }) - .add('default', () =>
Click the docs tab to see the docs
); + }, +}; diff --git a/examples/official-storybook/stories/addon-docs.stories.mdx b/examples/official-storybook/stories/addon-docs.stories.mdx new file mode 100644 index 00000000000..88dcf8a67b4 --- /dev/null +++ b/examples/official-storybook/stories/addon-docs.stories.mdx @@ -0,0 +1,88 @@ +import { + Story, + Preview, + Props, + Source, + Description, + ColorPalette, + ColorItem, + Meta, +} from '@storybook/addon-docs/blocks'; +import { action } from '@storybook/addon-actions'; +import { Button } from '@storybook/react/demo'; + +
{storyFn()}
]} + parameters={{ component: Button, notes: 'component notes' }} +/> + +# Selected + + + + + + + +## A random color ColorPalette + + + + + + + + +## Getting into details + + + +export const nonStory1 = 'foo'; // a non-story export + +export const nonStory2 = () => ; // another one + + + + + + + + + + + + + + + Plain text + + + + + + + + +## Configurable height + + + +## Description + + + + diff --git a/examples/official-storybook/stories/addon-events.stories.js b/examples/official-storybook/stories/addon-events.stories.js index 8c17d0a917a..7f280c366b0 100644 --- a/examples/official-storybook/stories/addon-events.stories.js +++ b/examples/official-storybook/stories/addon-events.stories.js @@ -1,6 +1,5 @@ import React from 'react'; import EventEmitter from 'eventemitter3'; -import { storiesOf } from '@storybook/react'; import withEvents from '@storybook/addon-events'; import Logger from './Logger'; @@ -67,25 +66,17 @@ const events = [ }, ]; -storiesOf('Addons|Events', module) - .addParameters({ +export default { + title: 'Addons|Events', + decorators: [withEvents({ emit, events })], + parameters: { options: { selectedPanel: 'storybook/events/panel', }, - }) - .addDecorator(withEvents({ emit, events })) - .add('Logger', () => ); + }, +}; -const WithEvents = withEvents; -storiesOf('Addons|Events.deprecated', module) - .addParameters({ - options: { - selectedPanel: 'storybook/events/panel', - }, - }) - .addDecorator(storyFn => ( - - {storyFn()} - - )) - .add('Logger', () => ); +export const logger = () => ; +logger.story = { + name: 'Logger', +}; diff --git a/examples/official-storybook/stories/addon-graphql.stories.js b/examples/official-storybook/stories/addon-graphql.stories.js index b10970c95c3..44187c83c6b 100644 --- a/examples/official-storybook/stories/addon-graphql.stories.js +++ b/examples/official-storybook/stories/addon-graphql.stories.js @@ -1,43 +1,47 @@ import React from 'react'; -import { storiesOf } from '@storybook/react'; -// import { setupGraphiQL } from '@storybook/addon-graphql'; -// const graphiql = setupGraphiQL({ -// url: 'https://graphql-pokemon.now.sh/?', -// }); +export default { + title: 'Addons|GraphQL', +}; -storiesOf('Addons|GraphQL', module).add('get Pickachu', () =>
hello
, { - graphiql: { - query: `{ - pokemon(name: "Pikachu") { - id - number - name - attacks { - special { - name - type - damage - } - } - evolutions { +export const getPickachu = () =>
hello
; + +getPickachu.story = { + name: 'get Pickachu', + + parameters: { + graphiql: { + query: `{ + pokemon(name: "Pikachu") { id number name - weight { - minimum - maximum - } attacks { - fast { + special { name type damage } } + evolutions { + id + number + name + weight { + minimum + maximum + } + attacks { + fast { + name + type + damage + } + } + } } - } - }`, - url: 'https://graphql-pokemon.now.sh/?', + }`, + url: 'https://graphql-pokemon.now.sh/?', + }, }, -}); +}; diff --git a/examples/official-storybook/stories/addon-info.stories.js b/examples/official-storybook/stories/addon-info.stories.js deleted file mode 100644 index fd7d686e19e..00000000000 --- a/examples/official-storybook/stories/addon-info.stories.js +++ /dev/null @@ -1,387 +0,0 @@ -import React from 'react'; -import { storiesOf } from '@storybook/react'; -import { withInfo } from '@storybook/addon-info'; -import { action } from '@storybook/addon-actions'; - -import DocgenButton from '../components/DocgenButton'; -import FlowTypeButton from '../components/FlowTypeButton'; -import BaseButton from '../components/BaseButton'; -import ForwardedRefButton from '../components/ForwardedRefButton'; -import ForwardedRefButtonWDisplayName from '../components/ForwardedRefButtonWDisplayName'; -import { NamedExportButton } from '../components/NamedExportButton'; -import TableComponent from '../components/TableComponent'; -import externalMdDocs from './addon-info-resources/EXAMPLE.md'; - -storiesOf('Addons|Info/React Docgen', module) - .addDecorator(withInfo) - .add( - 'Comments from PropType declarations', - () => ( - {}, - }} - arrayOf={[1, 2, 3]} - /> - ), - { - info: - 'Comments above the PropType declarations should be extracted from the React component file itself and rendered in the Info Addon prop table', - } - ) - .add( - 'Comments from Flow declarations', - () => , - { - info: - 'Comments above the Flow declarations should be extracted from the React component file itself and rendered in the Info Addon prop table', - } - ) - .add( - 'Comments from component declaration', - () => , - { - info: - 'Comments above the component declaration should be extracted from the React component file itself and rendered below the Info Addon heading', - } - ) - .add( - 'Comments from named export component declaration', - () => , - { - info: - 'Comments above the component declaration should be extracted from the React component file itself and rendered below the Info Addon heading', - } - ); - -const markdownDescription = ` -#### You can use markdown in your withInfo description. - -Sometimes you might want to manually include some \`code\` examples: - -~~~js -const Button = () =>