Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tools): create ui-components package and setup Storybook #41920

Merged
merged 6 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions client/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.js'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-postcss'
thecodingaviator marked this conversation as resolved.
Show resolved Hide resolved
]
};
6 changes: 6 additions & 0 deletions client/.storybook/manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { addons } from '@storybook/addons';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file wasn't generated by the script. I created it as part of the custom theming.

Ref: https://storybook.js.org/docs/react/configure/theming#create-a-theme-quickstart

import theme from './theme';

addons.setConfig({
theme
});
9 changes: 9 additions & 0 deletions client/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/
}
}
};
8 changes: 8 additions & 0 deletions client/.storybook/theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { create } from '@storybook/theming';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file wasn't generated by the script. I created it as part of the custom theming.

Ref: https://storybook.js.org/docs/react/configure/theming#create-a-theme-quickstart


export default create({
base: 'light',
brandTitle: 'freeCodeCamp.org',
brandImage:
'https://cdn.freecodecamp.org/platform/universal/fcc_secondary.svg'
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I browsed the cdn repo but couldn't find a logo file that has both text and gray90 background color. I resorted to the secondary logo as the text of the primary one is not readable on Storybook's default background.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have png assets with set backgrounds on the design style guide. https://github.com/freeCodeCamp/design-style-guide/blob/master/downloads/fcc_primary_large.png but they are not on the CDN.

We could default to the gray85 for the background and use the primary SVG down the road.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried it out and the PNG doesn't seem to have a background either

Screen Shot 2021-05-11 at 14 05 12


Storybook has very limited theming options. In order to have a dark background for the primary logo, I would need to set gray85 to the entire sidebar and change the text color; but it affects the Controls panel, which doesn't have dedicated styling options.

So I think we would still need an image file with a set background on CDN if we want to use the primary logo.

Screen Shot 2021-05-11 at 13 50 49

8,056 changes: 7,931 additions & 125 deletions client/package-lock.json

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
"prestand-alone": "npm run prebuild",
"stand-alone": "gatsby develop",
"test": "jest",
"validate-keys": "node ./i18n/validate-keys.js"
"validate-keys": "node ./i18n/validate-keys.js",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were added by the Storybook script.

},
"dependencies": {
"@babel/plugin-proposal-export-default-from": "7.12.13",
Expand Down Expand Up @@ -121,12 +123,21 @@
"validator": "13.6.0"
},
"devDependencies": {
"@babel/core": "^7.13.16",
"@storybook/addon-actions": "^6.2.9",
"@storybook/addon-essentials": "^6.2.9",
"@storybook/addon-links": "^6.2.9",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/react": "^6.2.9",
"@testing-library/jest-dom": "5.12.0",
"@testing-library/react": "11.2.6",
"autoprefixer": "9.8.6",
"babel-loader": "^8.2.2",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the new dependencies were added automatically by Storybook, except for @storybook/addon-postcss.

"babel-plugin-transform-imports": "1.5.1",
"chokidar": "3.5.1",
"copy-webpack-plugin": "5.1.2",
"dotenv-webpack": "^7.0.2",
"html-webpack-plugin": "^5.3.1",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand storybookjs/storybook#14403 correctly, Storybook is using a very old version of these libraries. They are hoisted and get picked up by Webpack, but error thrown because they are not compatible with Webpack 5.

Apparently Storybook team fixed it but then reverted the PR due to it being backward incompatible (storybookjs/storybook#14403 (comment)). I followed storybookjs/storybook#14497 (comment) and added these packages to our dev dependency list as a workaround.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Storybook team recommends using Yarn's resolutions to workaround this issue. It is not applicable to us, but I'm just posting the link here for future reference: https://gist.github.com/shilman/8856ea1786dcd247139b47b270912324#yarn-resolutions

"jest": "26.6.3",
"jest-json-schema-extended": "0.3.0",
"monaco-editor-webpack-plugin": "3.0.0",
Expand Down
38 changes: 38 additions & 0 deletions client/src/stories/Button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import PropTypes from 'prop-types';

import './button.css';

/**
* Primary UI component for user interaction
*/
export const Button = ({
primary = false,
size = 'medium',
backgroundColor,
label,
...props
}) => {
const mode = primary
? 'storybook-button--primary'
: 'storybook-button--secondary';
return (
<button
className={['storybook-button', `storybook-button--${size}`, mode].join(
' '
)}
style={{ backgroundColor }}
type='button'
{...props}
>
{label}
</button>
);
};

Button.propTypes = {
backgroundColor: PropTypes.string,
label: PropTypes.string,
primary: PropTypes.bool,
size: PropTypes.string
};
38 changes: 38 additions & 0 deletions client/src/stories/Button.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import { Button } from './Button';

const story = {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' }
}
};

const Template = args => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button'
};

export const Secondary = Template.bind({});
Secondary.args = {
label: 'Button'
};

export const Large = Template.bind({});
Large.args = {
size: 'large',
label: 'Button'
};

export const Small = Template.bind({});
Small.args = {
size: 'small',
label: 'Button'
};

export default story;
211 changes: 211 additions & 0 deletions client/src/stories/Introduction.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { Meta } from '@storybook/addon-docs/blocks';
import Code from './assets/code-brackets.svg';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is generated by Storybook, along with a bunch of svg files. It has links to the official document pages, which I think might come in handy especially when we don't have documentation on our side yet.

I decided to keep this one, and we can delete it once our component library is more mature.

import Colors from './assets/colors.svg';
import Comments from './assets/comments.svg';
import Direction from './assets/direction.svg';
import Flow from './assets/flow.svg';
import Plugin from './assets/plugin.svg';
import Repo from './assets/repo.svg';
import StackAlt from './assets/stackalt.svg';

<Meta title="Example/Introduction" />

<style>{`
.subheading {
--mediumdark: '#999999';
font-weight: 900;
font-size: 13px;
color: #999;
letter-spacing: 6px;
line-height: 24px;
text-transform: uppercase;
margin-bottom: 12px;
margin-top: 40px;
}

.link-list {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
row-gap: 10px;
}

@media (min-width: 620px) {
.link-list {
row-gap: 20px;
column-gap: 20px;
grid-template-columns: 1fr 1fr;
}
}

@media all and (-ms-high-contrast:none) {
.link-list {
display: -ms-grid;
-ms-grid-columns: 1fr 1fr;
-ms-grid-rows: 1fr 1fr;
}
}

.link-item {
display: block;
padding: 20px 30px 20px 15px;
border: 1px solid #00000010;
border-radius: 5px;
transition: background 150ms ease-out, border 150ms ease-out, transform 150ms ease-out;
color: #333333;
display: flex;
align-items: flex-start;
}

.link-item:hover {
border-color: #1EA7FD50;
transform: translate3d(0, -3px, 0);
box-shadow: rgba(0, 0, 0, 0.08) 0 3px 10px 0;
}

.link-item:active {
border-color: #1EA7FD;
transform: translate3d(0, 0, 0);
}

.link-item strong {
font-weight: 700;
display: block;
margin-bottom: 2px;
}

.link-item img {
height: 40px;
width: 40px;
margin-right: 15px;
flex: none;
}

.link-item span {
font-size: 14px;
line-height: 20px;
}

.tip {
display: inline-block;
border-radius: 1em;
font-size: 11px;
line-height: 12px;
font-weight: 700;
background: #E7FDD8;
color: #66BF3C;
padding: 4px 12px;
margin-right: 10px;
vertical-align: top;
}

.tip-wrapper {
font-size: 13px;
line-height: 20px;
margin-top: 40px;
margin-bottom: 40px;
}

.tip-wrapper code {
font-size: 12px;
display: inline-block;
}


`}</style>

# Welcome to Storybook

Storybook helps you build UI components in isolation from your app's business logic, data, and context.
That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA.

Browse example stories now by navigating to them in the sidebar.
View their code in the `src/stories` directory to learn how they work.
We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages.

<div className="subheading">Configure</div>

<div className="link-list">
<a
className="link-item"
href="https://storybook.js.org/docs/react/addons/addon-types"
target="_blank"
>
<img src={Plugin} alt="plugin" />
<span>
<strong>Presets for popular tools</strong>
Easy setup for TypeScript, SCSS and more.
</span>
</a>
<a
className="link-item"
href="https://storybook.js.org/docs/react/configure/webpack"
target="_blank"
>
<img src={StackAlt} alt="Build" />
<span>
<strong>Build configuration</strong>
How to customize webpack and Babel
</span>
</a>
<a
className="link-item"
href="https://storybook.js.org/docs/react/configure/styling-and-css"
target="_blank"
>
<img src={Colors} alt="colors" />
<span>
<strong>Styling</strong>
How to load and configure CSS libraries
</span>
</a>
<a
className="link-item"
href="https://storybook.js.org/docs/react/get-started/setup#configure-storybook-for-your-stack"
target="_blank"
>
<img src={Flow} alt="flow" />
<span>
<strong>Data</strong>
Providers and mocking for data libraries
</span>
</a>
</div>

<div className="subheading">Learn</div>

<div className="link-list">
<a className="link-item" href="https://storybook.js.org/docs" target="_blank">
<img src={Repo} alt="repo" />
<span>
<strong>Storybook documentation</strong>
Configure, customize, and extend
</span>
</a>
<a className="link-item" href="https://storybook.js.org/tutorials/" target="_blank">
<img src={Direction} alt="direction" />
<span>
<strong>In-depth guides</strong>
Best practices from leading teams
</span>
</a>
<a className="link-item" href="https://github.com/storybookjs/storybook" target="_blank">
<img src={Code} alt="code" />
<span>
<strong>GitHub project</strong>
View the source and add issues
</span>
</a>
<a className="link-item" href="https://discord.gg/storybook" target="_blank">
<img src={Comments} alt="comments" />
<span>
<strong>Discord chat</strong>
Chat with maintainers and the community
</span>
</a>
</div>

<div className="tip-wrapper">
<span className="tip">Tip</span>Edit the Markdown in{' '}
<code>src/stories/Introduction.stories.mdx</code>
</div>
1 change: 1 addition & 0 deletions client/src/stories/assets/code-brackets.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions client/src/stories/assets/colors.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.