Skip to content

Commit

Permalink
Mayflower v10: Storybook 6.0 Upgrade (#1162)
Browse files Browse the repository at this point in the history
* Initial stable upgrade to storybook 6.0.

* WIP.

* Wraps up converting atoms.

* WIP: Upgrades molecules to use controls.

* WIP: Adds organisms, templates, pages CSF stories.

* WIP: Adds misc stories to CSF/MDX format.

* WIP: Misc bug fixes, adds HTML display on doc pages.

* WIP: Fixes backstop.

* Code cleanup, removes acorns dev dependencies, updates storybook.

* Updates circle to run storybook extract.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* Fixes circleci.

* WIP: Fixes circleci react testing.

* WIP: Fixes circleci react testing.

* WIP: Fixes circleci react testing.

* WIP: Updates eslint rules to ignore auto generated icons.

* WIP: Changes backstop settings, fixes component docs.

* WIP: Puts back backstop config for async capture limit.

* Updates ButtonCopy logic, excludes it from backstop tests.

* Updates title for Docs to component name, fixes ButtonWithIcon story.

* Updates component propTypes comment structure, misc bug fixes for stories.

* WIP.

* WIP: Updates typography story name.

* Round 2 code review fixes.

* Updates form stories to work with CSF format and storybook docs.

* Update react/src/components/forms/DateRange/DateRange.stories.js

Co-authored-by: Minghua Sun <[email protected]>

* Removes un-needed portion of typography story.

* Adds updated backstop screens.

* Updates typograph story to remove story component.

* Adds changelog.

* Adds updated backstop files.

Co-authored-by: Minghua Sun <[email protected]>
  • Loading branch information
smurrayatwork and clairesunstudio authored Sep 29, 2020
1 parent b36a91f commit 677b95c
Show file tree
Hide file tree
Showing 390 changed files with 17,933 additions and 15,787 deletions.
19 changes: 11 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

version: 2

version: 2.1
references:
configure_npm: &configure_npm
run: { name: 'Configure NPM', command: 'echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc'}
Expand All @@ -12,7 +12,7 @@ references:
react_defaults: &react_defaults
working_directory: ~/repo
docker:
- image: circleci/node:12.18.0
- image: circleci/node:12.18.0-browsers
patternlab_defaults: &patternlab_defaults
working_directory: /var/www/code
docker:
Expand Down Expand Up @@ -164,21 +164,24 @@ jobs:
- checkout
- restore_cache:
keys:
- mfr-dependencies-{{ checksum "react/package.json" }}-0
- mfr-dependencies-{{ checksum "react/package.json" }}-4
- run: cd react && npm install
- save_cache:
paths:
- react/node_modules
key: mfr-dependencies-{{ checksum "react/package.json" }}-0
key: mfr-dependencies-{{ checksum "react/package.json" }}-4
- run:
name: Mayflower React Build
command: cd react && npm run build
- run:
name: Mayflower React Linter
command: cd react && npm run lint
- run:
name: Mayflower React Build Storybook
command: cd react && npm run build-storybook
- run:
name: Mayflower React Storybook Extract
command: cd react && npm run storybook:extract
- run:
name: Mayflower React Linter
command: cd react && npm run lint
- persist_to_workspace:
root: ~/repo
paths: ["*"]
Expand Down
17 changes: 17 additions & 0 deletions changelogs/storybook-6.0.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Changed:
- project: React
component: Storybook
description: Adds support for Storybook Controls and removes the usage of knobs.
impact: Major
- project: React
component: Storybook
description: Replaces the use of addon-info with Storybook Docs.
impact: Major
- project: React
component: Storybook
description: Displays story only pages with .mdx files.
impact: Major
- project: React
component: Storybook
description: Transfers all storiesOf usage to CSF storybook format.
impact: Major
4 changes: 4 additions & 0 deletions react/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ src/**/*.stories.js
src/**/*.knob*
gulpfile.js
icon-template.js
src/components/base/Icon/**
!src/components/base/Icon/IconDisplay.js
!src/components/base/Icon/_icon-display.scss

1 change: 1 addition & 0 deletions react/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"import/resolver": {
"babel-module": {
"alias": {
"StorybookConfig": "./.storybook",
"MayflowerReactComponents": "./src/components",
"MayflowerReactAtoms": "./src/components/atoms",
"MayflowerReactAnimations": "./src/components/animations",
Expand Down
29 changes: 21 additions & 8 deletions react/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,34 @@ const assets = require('@massds/mayflower-assets');
const iconPath = path.resolve(__dirname, '../src/components/base/Icon/assets');

module.exports = {
stories: ['../src/**/*.stories.js'],
stories: ['../src/**/*.stories.@(js|mdx)'],
addons: [
{
name: '@storybook/addon-docs',
options: {
transcludeMarkdown: true
}
},
'@storybook/addon-controls',
'@storybook/addon-actions',
'@storybook/addon-links',
'@storybook/addon-knobs',
'@storybook/addon-viewport',
'@storybook/addon-storysource',
{
name: '@storybook/addon-storysource',
options: {
rule: {
enforce: 'pre',
}
}
},
'@storybook/addon-a11y',
{
name: '@storybook/preset-scss',
options: {
cssLoaderOptions: {
sourceMap: true
},
sassLoaderOptions: {
sourceMap: true,
implementation: require('sass'),
Expand All @@ -32,12 +49,7 @@ module.exports = {
// modify storybook's file-loader rule to avoid conflicts with svgr
const fileLoaderRule = config.module.rules.find(rule => rule.test.test && rule.test.test('.svg'));
fileLoaderRule.exclude = iconPath;
// Configure the storysource plugin.
config.module.rules.push({
test: /\.stories\.js?$/,
loader: require.resolve('@storybook/addon-storysource/loader'),
enforce: 'pre',
});


config.module.rules.unshift({
test: /\.svg$/,
Expand All @@ -57,6 +69,7 @@ module.exports = {
...config.resolve,
alias: {
...config.resolve.alias,
StorybookConfig: path.resolve(__dirname, './'),
MayflowerReactComponents: path.resolve(__dirname, '../src/components'),
MayflowerReactAtoms: path.resolve(__dirname, '../src/components/atoms'),
MayflowerReactAnimations: path.resolve(__dirname, '../src/components/animations'),
Expand Down
124 changes: 79 additions & 45 deletions react/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,92 @@
import { addDecorator, addParameters } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';
import { withInfo } from '@storybook/addon-info';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import {
Title,
Subtitle,
Primary,
ArgsTable,
Heading,
ComponentsTable,
Stories,
PRIMARY_STORY,
CURRENT_SELECTION,
SourceState,
DocsContext,
Canvas, Story
} from '@storybook/addon-docs/blocks';
import { ActionBar, Source } from '@storybook/components';
import prettier from 'prettier/standalone';
import parserHtml from 'prettier/parser-html';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { okaidia } from 'react-syntax-highlighter/dist/esm/styles/prism';
import '../src/index.scss';

const storyKindOrder = [
'about', // storyKindOrder.indexOf -1 follow alphabetical order
'brand', // storyKindOrder.indexOf -1 follow alphabetical order
'dataviz', // storyKindOrder.indexOf -1 follow alphabetical order
'forms|atoms',
'forms|molecules',
'forms|organisms',
'forms|context',
'forms',
'atoms',
'molecules',
'organisms',
'templates',
'pages'
'others/templates',
'others/pages'
];

addParameters({
options: {
storySort: (a, b) => {
const aKind = a[1].kind.split('/')[0];
const bKind = b[1].kind.split('/')[0];
return (storyKindOrder.indexOf(aKind) - storyKindOrder.indexOf(bKind)) || a[1].id.toLowerCase().localeCompare(b[1].id.toLowerCase(), undefined, { numeric: true });
}
}
});

addDecorator(
withInfo({
styles: {
button: {
base: {
fontFamily: 'sans-serif',
fontSize: '14px',
fontWeight: '500',
display: 'block',
position: 'fixed',
border: 'none',
background: '#14558f',
color: '#fff',
padding: '5px 15px',
cursor: 'pointer',
},
topRight: {
bottom: 0,
right: 0,
top: 'unset',
borderRadius: '5px 0 0 0',
}
export const StoryPage = ({ StoryComponent = null, showStories = false, Description }) => {
const docsContext = React.useContext(DocsContext);
const [showHTML, setShowHTML] = React.useState(true);
const { id, name, parameters = {}, args } = docsContext;
const { component } = parameters;
const HtmlComponent = StoryComponent || component;
let html = null;
if (HtmlComponent) {
html = prettier.format(ReactDOMServer
.renderToStaticMarkup(
(
<HtmlComponent {...args} />
)),
{
htmlWhitespaceSensitivity: 'ignore',
endOfLine: 'auto',
parser: 'html',
plugins: [parserHtml]
}
}
})
);
);
}
const actionItem = {
title: showHTML ? 'Hide HTML' : 'Show HTML?',
onClick: () => setShowHTML((prev) => !prev)
};
return(
<>
<Title>{component.displayName}</Title>
<Subtitle />
{ Description && <Description />}
<Primary name={name} />
<ArgsTable story={CURRENT_SELECTION}/>
{html && (
<Heading>
HTML
<ActionBar actionItems={[actionItem]} />
</Heading>
)}
{!showHTML && <Source storyId={id} error="Click Show HTML above to view markup source." />}
{html && showHTML && <Source storyId={id} language="html" code={html} dark />}
{ showStories && <Stories />}
</>
);
}

addDecorator(withA11y);
export const parameters = {
options: {
storySort: {
order: storyKindOrder
},
},
controls: {
expanded: true,
hideNoControlsWarning: true
},
layout: 'padding'
};
33 changes: 11 additions & 22 deletions react/backstop/backstop.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
const path = require('path');
// This file is generated by `npx sb extract` command.
const stories = require('../storybook-static/stories.json');

const listDirs = require('./listDirs.js');
const storyBookBackstop = require('./storyBookBackstop');

const debug = (process.argv.indexOf('--debug') > -1);
const mapComponents = require('./storybook');

const debug = false;
// Default viewport values.
const viewports = [
{ label: 'small_atom', width: 400, height: 250 },
{ label: 'phone', width: 320, height: 480 },
{ label: 'tablet', width: 1024, height: 768 }
];

// Scan for component names and set up viewports.
const componentsPath = path.resolve(__dirname, '../src/components/');
const dirList = listDirs(componentsPath)
// Do not test animations.
.filter((filePath) => (filePath.indexOf('/animations') === -1))
// Do not test styles.
.filter((filePath) => (filePath.indexOf('/styles') === -1));
const testComponents = storyBookBackstop.listComponents(dirList);

// Map discovered Component dirs to Backstop scenarios.
const scenarios = storyBookBackstop.mapComponents(testComponents, debug);

const scenarios = mapComponents(stories.stories, debug);
module.exports = {
id: 'vrt',
viewports,
Expand All @@ -37,18 +28,16 @@ module.exports = {
html_report: path.resolve(__dirname, './data/html_report'),
ci_report: path.resolve(__dirname, './data/ci_report')
},
// Use 'storyRendered' being printed to the console as the trigger to start
// taking the snapshot. This is something Storybook prints on its own. This
// prevents us from having to add a manual delay to compensate for Storybook's
// slow boot time.
readyEvent: 'storyRendered',
report: ['browser', 'CI'],
engine: 'puppeteer',
engineOptions: {
args: ['--no-sandbox']
args: [
'--no-sandbox'
],
devtools: false
},
asyncCaptureLimit: 3,
asyncCompareLimit: 20,
debug: false,
debugWindow: false
debug,
debugWindow: debug
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 0 additions & 23 deletions react/backstop/listDirs.js

This file was deleted.

10 changes: 5 additions & 5 deletions react/backstop/scripts/onBefore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
module.exports = async (page, scenario, vp) => {
await page.setRequestInterception(true);
page.on('request', interceptRequest);
}
};

function escapeRegexp(string) {
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
Expand Down Expand Up @@ -33,13 +33,13 @@ async function interceptRequest(request) {
request.respond({
status: 301,
headers: {"Location": `https://via.placeholder.com/${urlMatch[1]}/B2DEA2.png?text=Static%20Map`}
})
return
});
return;
}
// Conditionally block requests if they match our regex.
if(bannedRE.test(request.url())) {
request.abort()
request.abort();
} else {
request.continue()
request.continue();
}
}
Loading

0 comments on commit 677b95c

Please sign in to comment.