Start redesign and add StorybookJS

This commit is contained in:
Robert Long 2020-08-17 11:19:02 -07:00
Родитель 4c9f884208
Коммит ec304298b7
16 изменённых файлов: 16067 добавлений и 56 удалений

Просмотреть файл

@ -28,7 +28,7 @@
"plugins": [ "plugins": [
[ "react-intl", { "messagesDir": "./public/messages", "enforceDescriptions": false } ], [ "react-intl", { "messagesDir": "./public/messages", "enforceDescriptions": false } ],
"transform-react-jsx-img-import", "transform-react-jsx-img-import",
"@babel/proposal-class-properties", ["@babel/proposal-class-properties", { "loose": true }],
"@babel/proposal-object-rest-spread", "@babel/proposal-object-rest-spread",
// Samsung Internet on the Oculus Go version is stuck at version 5.2, which is a // Samsung Internet on the Oculus Go version is stuck at version 5.2, which is a
// Chromium 51, as of this writing. It needs babel to transpile async/await. // Chromium 51, as of this writing. It needs babel to transpile async/await.

15
.storybook/main.js Normal file
Просмотреть файл

@ -0,0 +1,15 @@
const path = require("path");
module.exports = {
stories: ["../src/react-components/**/*.stories.mdx", "../src/react-components/**/*.stories.js"],
addons: ["@storybook/addon-links", "@storybook/addon-essentials", "storybook-addon-designs"],
webpackFinal: async config => {
config.module.rules.push({
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
include: path.resolve(__dirname, "..", "src")
});
return config;
}
};

Просмотреть файл

@ -0,0 +1,2 @@
<!-- Add extra elements to the head of the preview iframe here. -->
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,500;0,700;1,400&display=swap" rel="stylesheet">

16
.storybook/preview.js Normal file
Просмотреть файл

@ -0,0 +1,16 @@
import React from "react";
import { useAccessibleOutlineStyle } from "../src/react-components/input/useAccessibleOutlineStyle";
import "../src/react-components/styles/global.scss";
const Layout = ({ children }) => {
useAccessibleOutlineStyle();
return <>{children}</>;
};
export const decorators = [
Story => (
<Layout>
<Story />
</Layout>
)
];

15607
package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -32,7 +32,8 @@
"stats": "rimraf ./dist && webpack --mode=production --json", "stats": "rimraf ./dist && webpack --mode=production --json",
"spritesheet": "npm run spritesheet:system-action && npm run spritesheet:system-notice", "spritesheet": "npm run spritesheet:system-action && npm run spritesheet:system-notice",
"spritesheet:system-action": "spritesheet-js -f json -p src/assets/images/spritesheets/ --padding 8 --divisibleByTwo -n sprite-system-action-spritesheet --powerOfTwo src/assets/images/sprites/action/*", "spritesheet:system-action": "spritesheet-js -f json -p src/assets/images/spritesheets/ --padding 8 --divisibleByTwo -n sprite-system-action-spritesheet --powerOfTwo src/assets/images/sprites/action/*",
"spritesheet:system-notice": "spritesheet-js -f json -p src/assets/images/spritesheets/ --padding 8 --divisibleByTwo -n sprite-system-notice-spritesheet --powerOfTwo src/assets/images/sprites/notice/*" "spritesheet:system-notice": "spritesheet-js -f json -p src/assets/images/spritesheets/ --padding 8 --divisibleByTwo -n sprite-system-notice-spritesheet --powerOfTwo src/assets/images/sprites/notice/*",
"storybook": "start-storybook -p 6006"
}, },
"ava": { "ava": {
"files": [ "files": [
@ -62,6 +63,7 @@
"classnames": "^2.2.5", "classnames": "^2.2.5",
"color": "^3.1.2", "color": "^3.1.2",
"copy-to-clipboard": "^3.0.8", "copy-to-clipboard": "^3.0.8",
"core-js": "^3.6.5",
"dashjs": "^3.1.0", "dashjs": "^3.1.0",
"dayjs-ext": "^2.2.0", "dayjs-ext": "^2.2.0",
"deepmerge": "^2.1.1", "deepmerge": "^2.1.1",
@ -88,6 +90,7 @@
"networked-aframe": "github:mozillareality/networked-aframe#master", "networked-aframe": "github:mozillareality/networked-aframe#master",
"nipplejs": "github:mozillareality/nipplejs#mr-social-client/master", "nipplejs": "github:mozillareality/nipplejs#mr-social-client/master",
"node-ensure": "0.0.0", "node-ensure": "0.0.0",
"normalize.css": "^8.0.1",
"pdfjs-dist": "^2.1.266", "pdfjs-dist": "^2.1.266",
"phoenix": "github:gfodor/phoenix-js#master", "phoenix": "github:gfodor/phoenix-js#master",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
@ -121,6 +124,10 @@
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@babel/register": "^7.0.0", "@babel/register": "^7.0.0",
"@iarna/toml": "^2.2.3", "@iarna/toml": "^2.2.3",
"@storybook/addon-actions": "^6.0.12",
"@storybook/addon-essentials": "^6.0.12",
"@storybook/addon-links": "^6.0.12",
"@storybook/react": "^6.0.12",
"acorn": "^6.4.1", "acorn": "^6.4.1",
"ava": "^1.4.1", "ava": "^1.4.1",
"babel-eslint": "^10.0.1", "babel-eslint": "^10.0.1",
@ -153,6 +160,7 @@
"prettier": "^1.7.0", "prettier": "^1.7.0",
"protoo-client": "^4.0.4", "protoo-client": "^4.0.4",
"raw-loader": "^0.5.1", "raw-loader": "^0.5.1",
"react-is": "^16.13.1",
"request": "^2.88.2", "request": "^2.88.2",
"rimraf": "^2.6.2", "rimraf": "^2.6.2",
"sass": "^1.26.10", "sass": "^1.26.10",
@ -160,6 +168,7 @@
"selfsigned": "^1.10.2", "selfsigned": "^1.10.2",
"shelljs": "^0.8.1", "shelljs": "^0.8.1",
"spritesheet-js": "github:mozillareality/spritesheet.js#hubs/master", "spritesheet-js": "github:mozillareality/spritesheet.js#hubs/master",
"storybook-addon-designs": "^5.4.1",
"style-loader": "^0.20.2", "style-loader": "^0.20.2",
"stylelint": "^9.10.1", "stylelint": "^9.10.1",
"stylelint-config-recommended-scss": "^3.2.0", "stylelint-config-recommended-scss": "^3.2.0",

25
src/react-components/home/Button.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
import React from "react";
import PropTypes from "prop-types";
import classNames from "classnames";
import styles from "./Button.scss";
export function Button({ primary, secondary, cta, children, ...rest }) {
const className = classNames({
[styles.primaryButton]: primary,
[styles.secondaryButton]: secondary,
[styles.ctaButton]: cta
});
return (
<button className={className} {...rest}>
{children}
</button>
);
}
Button.propTypes = {
primary: PropTypes.bool,
secondary: PropTypes.bool,
cta: PropTypes.bool,
children: PropTypes.node
};

Просмотреть файл

@ -0,0 +1,31 @@
@import '../../assets/stylesheets/root-vars';
@import '../../assets/stylesheets/shared';
:local(.primary-button) {
@extend %big-action-button;
}
:local(.cta-button) {
font-size: 14pt;
width: 19em;
margin-right: 1em;
@media (max-width: 380px) {
width: 18em;
}
}
:local(.secondary-button) {
@extend %action-button-secondary;
display: flex;
flex-direction: row;
width: 250px;
margin-top: 18px;
margin-bottom: 18px;
padding-right: 20px;
i {
margin-right: 16px;
}
}

Просмотреть файл

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { createAndRedirectToNewHub } from "../../utils/phoenix-utils"; import { createAndRedirectToNewHub } from "../../utils/phoenix-utils";
import { Button } from "../input/Button"; import { Button } from "./Button";
export function CreateRoomButton() { export function CreateRoomButton() {
return ( return (

2
src/react-components/home/PWAButton.js поставляемый
Просмотреть файл

@ -2,7 +2,7 @@ import React from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus"; import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button } from "../input/Button"; import { Button } from "./Button";
import checkIsMobile from "../../utils/is-mobile"; import checkIsMobile from "../../utils/is-mobile";
import { useInstallPWA } from "./useInstallPWA"; import { useInstallPWA } from "./useInstallPWA";

18
src/react-components/input/Button.js поставляемый
Просмотреть файл

@ -1,25 +1,15 @@
import React from "react"; import React from "react";
import PropTypes from "prop-types";
import classNames from "classnames"; import classNames from "classnames";
import styles from "./Button.scss"; import styles from "./Button.scss";
export function Button({ primary, secondary, cta, children, ...rest }) { export function Button({ preset, className, children, ...rest }) {
const className = classNames({
[styles.primaryButton]: primary,
[styles.secondaryButton]: secondary,
[styles.ctaButton]: cta
});
return ( return (
<button className={className} {...rest}> <button className={classNames(styles.button, styles[preset], className)} {...rest}>
{children} {children}
</button> </button>
); );
} }
Button.propTypes = { Button.defaultProps = {
primary: PropTypes.bool, preset: "basic"
secondary: PropTypes.bool,
cta: PropTypes.bool,
children: PropTypes.node
}; };

Просмотреть файл

@ -1,31 +1,88 @@
@import '../styles/theme';
@import '../../assets/stylesheets/root-vars'; :local(.button) {
@import '../../assets/stylesheets/shared'; height: 48px;
min-width: 156px;
:local(.primary-button) { font-weight: 700;
@extend %big-action-button; font-size: 12px;
border-radius: 8px;
border-width: 0;
} }
:local(.cta-button) { :local(.basic) {
font-size: 14pt; color: $darkgrey;
width: 19em; border: 1px solid $darkgrey;
margin-right: 1em;
@media (max-width: 380px) { &:hover {
width: 18em; background-color: $white-hover;
}
&:active {
background-color: $white-pressed;
} }
} }
:local(.secondary-button) { :local(.accept) {
@extend %action-button-secondary; color: $white;
display: flex; background-color: $green;
flex-direction: row;
width: 250px;
margin-top: 18px;
margin-bottom: 18px;
padding-right: 20px;
i { &:hover {
margin-right: 16px; background-color: $green-hover;
}
&:active {
background-color: $green-pressed;
}
}
:local(.cancel) {
color: $white;
background-color: $red;
&:hover {
background-color: $red-hover;
}
&:active {
background-color: $red-pressed;
}
}
:local(.blue) {
color: $white;
background-color: $blue;
&:hover {
background-color: $blue-hover;
}
&:active {
background-color: $blue-pressed;
}
}
:local(.orange) {
color: $white;
background-color: $orange;
&:hover {
background-color: $orange-hover;
}
&:active {
background-color: $orange-pressed;
}
}
:local(.purple) {
color: $white;
background-color: $purple;
&:hover {
background-color: $purple-hover;
}
&:active {
background-color: $purple-pressed;
} }
} }

Просмотреть файл

@ -0,0 +1,62 @@
import React from "react";
import { withDesign } from "storybook-addon-designs";
import { Button } from "./Button";
export default {
title: "Button",
decorators: [withDesign]
};
export const Basic = () => <Button>Text</Button>;
Basic.parameters = {
design: {
type: "figma",
url: "https://www.figma.com/file/Xag5qaEgYs3KzXvoxx5m8y/Hubs-Redesign?node-id=70%3A2186"
}
};
export const Accept = () => <Button preset="accept">Accept</Button>;
Accept.parameters = {
design: {
type: "figma",
url: "https://www.figma.com/file/Xag5qaEgYs3KzXvoxx5m8y/Hubs-Redesign?node-id=69%3A4742"
}
};
export const Cancel = () => <Button preset="cancel">Cancel</Button>;
Cancel.parameters = {
design: {
type: "figma",
url: "https://www.figma.com/file/Xag5qaEgYs3KzXvoxx5m8y/Hubs-Redesign?node-id=70%3A2134"
}
};
export const Blue = () => <Button preset="blue">Blue</Button>;
Blue.parameters = {
design: {
type: "figma",
url: "https://www.figma.com/file/Xag5qaEgYs3KzXvoxx5m8y/Hubs-Redesign?node-id=70%3A2134"
}
};
export const Orange = () => <Button preset="orange">Orange</Button>;
Orange.parameters = {
design: {
type: "figma",
url: "https://www.figma.com/file/Xag5qaEgYs3KzXvoxx5m8y/Hubs-Redesign?node-id=70%3A2134"
}
};
export const Purple = () => <Button preset="purple">Purple</Button>;
Purple.parameters = {
design: {
type: "figma",
url: "https://www.figma.com/file/Xag5qaEgYs3KzXvoxx5m8y/Hubs-Redesign?node-id=70%3A2134"
}
};

27
src/react-components/input/useAccessibleOutlineStyle.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
import { useEffect, useCallback } from "react";
// The page is styled by default not to have any outlines on selected input elements.
// When the user presses the tab key the keyboardUserClass is added to the body and all outlines are re-enabled.
// This lets us provide a clean look for mouse users, while still maintaining accessibility for keyboard users.
export function useAccessibleOutlineStyle(keyboardUserClass = "keyboard-user") {
const onFirstTab = useCallback(
e => {
if (e.key === "Tab") {
document.body.classList.add(keyboardUserClass);
window.removeEventListener("keydown", handleFirstTab);
}
},
[keyboardUserClass]
);
useEffect(
() => {
window.addEventListener("keydown", onFirstTab);
return () => {
window.removeEventListener("keydown", onFirstTab);
};
},
[onFirstTab]
);
}

Просмотреть файл

@ -0,0 +1,161 @@
@import "~normalize.css";
/**
* https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/
*/
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
/**
* Forked from Tailwind CSS
*/
/**
* Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
ol,
ul {
list-style: none;
margin: 0;
padding: 0;
}
/**
* https://css-tricks.com/snippets/css/system-font-stack/
*/
html {
font-family: 'Poppins', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"
}
/*
* Ensure horizontal rules are visible by default
*/
hr {
border-top-width: 1px;
}
textarea {
resize: vertical;
}
button,
[role="button"] {
cursor: pointer;
}
table {
border-collapse: collapse;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/**
* Reset links to optimize for opt-in styling instead of
* opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/**
* Reset form element properties that are easy to forget to
* style explicitly so you don't inadvertently introduce
* styles that deviate from your design system. These styles
* supplement a partial reset that is already applied by
* normalize.css.
*/
button,
input,
optgroup,
select,
textarea {
padding: 0;
line-height: inherit;
color: inherit;
}
/**
* Monospace font stack: https://css-tricks.com/snippets/css/font-stacks/
*/
pre,
code,
kbd,
samp {
font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace;
}
/**
* Make replaced elements `display: block` by default as that's
* the behavior you want almost all of the time. Inspired by
* CSS Remedy, with `svg` added as well.
*
* https://github.com/mozdevs/cssremedy/issues/14
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
vertical-align: middle;
}
/**
* Constrain images and videos to the parent width and preserve
* their instrinsic aspect ratio.
*
* https://github.com/mozdevs/cssremedy/issues/14
*/
img,
video {
max-width: 100%;
height: auto;
}

Просмотреть файл

@ -0,0 +1,43 @@
$transparent: transparent;
$transparent-hover: rgba(0, 0, 0, 0.08);
$transparent-pressed: rgba(0, 0, 0, 0.12);
$white: #FFFFFF;
$white-hover: #E7E7E7;
$white-pressed: #DBDBDB;
$lightgrey: #E7E7E7;
$lightgrey-hover: #F5F5F5;
$lightgrey-pressed: #DBDBDB;
$grey: #BBBBBB;
$grey-hover: #C7C7C7;
$grey-pressed: #ADADAD;
$darkgrey: #868686;
$darkgrey-hover: #949494;
$darkgrey-pressed: #7A7A7A;
$black: #000000;
$black-hover: #404040;
$black-pressed: #7A7A7A;
$red: #F5325C;
$red-hover: #F64B70;
$red-pressed: #F41A49;
$orange: #FF8500;
$orange-hover: #FF911A;
$orange-pressed: #E67800;
$green: #7ED320;
$green-hover: #8CDF2F;
$green-pressed: #72BE1D;
$blue: #12A4ED;
$blue-hover: #2AADEF;
$blue-pressed: #1094D5;
$purple: #7854F6;
$purple-hover: #8C6EF7;
$purple-pressed: #663DF5;