зеркало из https://github.com/mozilla/hubs.git
Start redesign and add StorybookJS
This commit is contained in:
Родитель
4c9f884208
Коммит
ec304298b7
2
.babelrc
2
.babelrc
|
@ -28,7 +28,7 @@
|
|||
"plugins": [
|
||||
[ "react-intl", { "messagesDir": "./public/messages", "enforceDescriptions": false } ],
|
||||
"transform-react-jsx-img-import",
|
||||
"@babel/proposal-class-properties",
|
||||
["@babel/proposal-class-properties", { "loose": true }],
|
||||
"@babel/proposal-object-rest-spread",
|
||||
// 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.
|
||||
|
|
|
@ -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">
|
|
@ -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>
|
||||
)
|
||||
];
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
11
package.json
11
package.json
|
@ -32,7 +32,8 @@
|
|||
"stats": "rimraf ./dist && webpack --mode=production --json",
|
||||
"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-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": {
|
||||
"files": [
|
||||
|
@ -62,6 +63,7 @@
|
|||
"classnames": "^2.2.5",
|
||||
"color": "^3.1.2",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"core-js": "^3.6.5",
|
||||
"dashjs": "^3.1.0",
|
||||
"dayjs-ext": "^2.2.0",
|
||||
"deepmerge": "^2.1.1",
|
||||
|
@ -88,6 +90,7 @@
|
|||
"networked-aframe": "github:mozillareality/networked-aframe#master",
|
||||
"nipplejs": "github:mozillareality/nipplejs#mr-social-client/master",
|
||||
"node-ensure": "0.0.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pdfjs-dist": "^2.1.266",
|
||||
"phoenix": "github:gfodor/phoenix-js#master",
|
||||
"prop-types": "^15.7.2",
|
||||
|
@ -121,6 +124,10 @@
|
|||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"@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",
|
||||
"ava": "^1.4.1",
|
||||
"babel-eslint": "^10.0.1",
|
||||
|
@ -153,6 +160,7 @@
|
|||
"prettier": "^1.7.0",
|
||||
"protoo-client": "^4.0.4",
|
||||
"raw-loader": "^0.5.1",
|
||||
"react-is": "^16.13.1",
|
||||
"request": "^2.88.2",
|
||||
"rimraf": "^2.6.2",
|
||||
"sass": "^1.26.10",
|
||||
|
@ -160,6 +168,7 @@
|
|||
"selfsigned": "^1.10.2",
|
||||
"shelljs": "^0.8.1",
|
||||
"spritesheet-js": "github:mozillareality/spritesheet.js#hubs/master",
|
||||
"storybook-addon-designs": "^5.4.1",
|
||||
"style-loader": "^0.20.2",
|
||||
"stylelint": "^9.10.1",
|
||||
"stylelint-config-recommended-scss": "^3.2.0",
|
||||
|
|
|
@ -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 { FormattedMessage } from "react-intl";
|
||||
import { createAndRedirectToNewHub } from "../../utils/phoenix-utils";
|
||||
import { Button } from "../input/Button";
|
||||
import { Button } from "./Button";
|
||||
|
||||
export function CreateRoomButton() {
|
||||
return (
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from "react";
|
|||
import { FormattedMessage } from "react-intl";
|
||||
import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button } from "../input/Button";
|
||||
import { Button } from "./Button";
|
||||
import checkIsMobile from "../../utils/is-mobile";
|
||||
import { useInstallPWA } from "./useInstallPWA";
|
||||
|
||||
|
|
|
@ -1,25 +1,15 @@
|
|||
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
|
||||
});
|
||||
|
||||
export function Button({ preset, className, children, ...rest }) {
|
||||
return (
|
||||
<button className={className} {...rest}>
|
||||
<button className={classNames(styles.button, styles[preset], className)} {...rest}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
Button.propTypes = {
|
||||
primary: PropTypes.bool,
|
||||
secondary: PropTypes.bool,
|
||||
cta: PropTypes.bool,
|
||||
children: PropTypes.node
|
||||
Button.defaultProps = {
|
||||
preset: "basic"
|
||||
};
|
||||
|
|
|
@ -1,31 +1,88 @@
|
|||
@import '../styles/theme';
|
||||
|
||||
@import '../../assets/stylesheets/root-vars';
|
||||
@import '../../assets/stylesheets/shared';
|
||||
|
||||
:local(.primary-button) {
|
||||
@extend %big-action-button;
|
||||
:local(.button) {
|
||||
height: 48px;
|
||||
min-width: 156px;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
border-radius: 8px;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
:local(.cta-button) {
|
||||
font-size: 14pt;
|
||||
width: 19em;
|
||||
margin-right: 1em;
|
||||
:local(.basic) {
|
||||
color: $darkgrey;
|
||||
border: 1px solid $darkgrey;
|
||||
|
||||
@media (max-width: 380px) {
|
||||
width: 18em;
|
||||
&:hover {
|
||||
background-color: $white-hover;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $white-pressed;
|
||||
}
|
||||
}
|
||||
|
||||
:local(.secondary-button) {
|
||||
@extend %action-button-secondary;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 250px;
|
||||
margin-top: 18px;
|
||||
margin-bottom: 18px;
|
||||
padding-right: 20px;
|
||||
:local(.accept) {
|
||||
color: $white;
|
||||
background-color: $green;
|
||||
|
||||
i {
|
||||
margin-right: 16px;
|
||||
&:hover {
|
||||
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"
|
||||
}
|
||||
};
|
|
@ -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;
|
Загрузка…
Ссылка в новой задаче