new examples buttonModules & buttonEmotion + refac
This commit is contained in:
parent
d03e3d3928
commit
b53d4528fb
@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "stylelint-config-standard"
|
"extends": "stylelint-config-standard",
|
||||||
|
"rules": {
|
||||||
|
"declaration-empty-line-before": "never"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
platform/ui/gatsby-config.js
Normal file
3
platform/ui/gatsby-config.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: ['gatsby-plugin-sass'],
|
||||||
|
};
|
||||||
@ -18,6 +18,7 @@
|
|||||||
"README.md"
|
"README.md"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"start": "yarn run dev",
|
||||||
"dev": "concurrently \"npm run watch:css\" \"docz dev\"",
|
"dev": "concurrently \"npm run watch:css\" \"docz dev\"",
|
||||||
"build": "concurrently \"npm run build:css\" \"docz build\"",
|
"build": "concurrently \"npm run build:css\" \"docz build\"",
|
||||||
"serve": "docz serve",
|
"serve": "docz serve",
|
||||||
@ -25,8 +26,13 @@
|
|||||||
"watch:css": "postcss src/styles/tailwind.css -o src/gatsby-theme-docz/app.css -w"
|
"watch:css": "postcss src/styles/tailwind.css -o src/gatsby-theme-docz/app.css -w"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/core": "^10.0.27",
|
||||||
|
"@emotion/styled": "^10.0.27",
|
||||||
|
"classnames": "^2.2.6",
|
||||||
"concurrently": "^5.1.0",
|
"concurrently": "^5.1.0",
|
||||||
"docz": "latest",
|
"docz": "^2.2.0",
|
||||||
|
"gatsby-plugin-sass": "^2.1.28",
|
||||||
|
"node-sass": "^4.13.1",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^16.11.0",
|
"react": "^16.11.0",
|
||||||
"react-dom": "^16.11.0"
|
"react-dom": "^16.11.0"
|
||||||
|
|||||||
@ -1,79 +1,18 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
const Button = ({
|
|
||||||
children,
|
|
||||||
variant = defaults.variant,
|
|
||||||
color = defaults.color,
|
|
||||||
size = defaults.size,
|
|
||||||
radius = defaults.radius,
|
|
||||||
disabled = defaults.disabled,
|
|
||||||
elevation,
|
|
||||||
type = defaults.type,
|
|
||||||
startIcon: startIconProp,
|
|
||||||
endIcon: endIconProp,
|
|
||||||
className,
|
|
||||||
...rest
|
|
||||||
}) => {
|
|
||||||
const hasIcon = startIconProp || endIconProp;
|
|
||||||
const getClasses = () => {
|
|
||||||
const classes = [];
|
|
||||||
let buttonElevation;
|
|
||||||
|
|
||||||
if (variant === 'text') {
|
|
||||||
if (elevation) {
|
|
||||||
buttonElevation = elevation;
|
|
||||||
} else {
|
|
||||||
buttonElevation = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buttonElevation = defaults.elevation;
|
|
||||||
}
|
|
||||||
|
|
||||||
classes.push(variantClasses[variant][color]);
|
|
||||||
classes.push(radiusClasses[radius]);
|
|
||||||
classes.push(sizeClasses[size]);
|
|
||||||
classes.push(disabledClasses[disabled]);
|
|
||||||
classes.push(elevationClasses[buttonElevation]);
|
|
||||||
classes.push(className);
|
|
||||||
|
|
||||||
if (hasIcon) {
|
|
||||||
classes.push(baseIconClasses);
|
|
||||||
}
|
|
||||||
|
|
||||||
return classes.join(' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
const baseIconClasses = 'inline-flex items-center';
|
|
||||||
const baseClasses =
|
|
||||||
'outline-none transition duration-300 ease-in-out rounded font-bold focus:outline-none';
|
|
||||||
|
|
||||||
const startIcon = startIconProp && (
|
|
||||||
<div className="mr-2">{startIconProp}</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const endIcon = endIconProp && <div className="ml-2">{endIconProp}</div>;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button className={`${baseClasses} ${getClasses()}`} type={type} {...rest}>
|
|
||||||
{startIcon}
|
|
||||||
{children}
|
|
||||||
{endIcon}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
variant: 'outlined',
|
variant: 'contained',
|
||||||
color: 'default',
|
color: 'default',
|
||||||
size: 'medium',
|
size: 'medium',
|
||||||
radius: 'medium',
|
radius: 'medium',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
elevation: true,
|
|
||||||
type: 'button',
|
type: 'button',
|
||||||
};
|
};
|
||||||
|
|
||||||
const radiusClasses = {
|
const radiusClasses = {
|
||||||
|
none: '',
|
||||||
small: 'rounded-sm',
|
small: 'rounded-sm',
|
||||||
medium: 'rounded-md',
|
medium: 'rounded-md',
|
||||||
large: 'rounded-lg',
|
large: 'rounded-lg',
|
||||||
@ -85,11 +24,6 @@ const disabledClasses = {
|
|||||||
false: '',
|
false: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const elevationClasses = {
|
|
||||||
true: 'shadow',
|
|
||||||
false: 'shadow-none',
|
|
||||||
};
|
|
||||||
|
|
||||||
const variantClasses = {
|
const variantClasses = {
|
||||||
text: {
|
text: {
|
||||||
default: 'hover:bg-gray-200 text-black',
|
default: 'hover:bg-gray-200 text-black',
|
||||||
@ -114,14 +48,55 @@ const sizeClasses = {
|
|||||||
large: 'py-3 px-6 text-lg',
|
large: 'py-3 px-6 text-lg',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Button = ({
|
||||||
|
children,
|
||||||
|
variant = defaults.variant,
|
||||||
|
color = defaults.color,
|
||||||
|
size = defaults.size,
|
||||||
|
radius = defaults.radius,
|
||||||
|
disabled = defaults.disabled,
|
||||||
|
type = defaults.type,
|
||||||
|
startIcon: startIconProp,
|
||||||
|
endIcon: endIconProp,
|
||||||
|
className,
|
||||||
|
...rest
|
||||||
|
}) => {
|
||||||
|
const baseClasses =
|
||||||
|
'inline-flex items-center outline-none transition duration-300 ease-in-out font-bold focus:outline-none';
|
||||||
|
|
||||||
|
const startIcon = startIconProp && (
|
||||||
|
<div className="mr-2">{startIconProp}</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const endIcon = endIconProp && <div className="ml-2">{endIconProp}</div>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={classnames(
|
||||||
|
baseClasses,
|
||||||
|
variantClasses[variant][color],
|
||||||
|
radiusClasses[radius],
|
||||||
|
sizeClasses[size],
|
||||||
|
disabledClasses[disabled],
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
type={type}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{startIcon}
|
||||||
|
{children}
|
||||||
|
{endIcon}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Button.propTypes = {
|
Button.propTypes = {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
||||||
radius: PropTypes.oneOf(['small', 'medium', 'large', 'full']),
|
radius: PropTypes.oneOf(['none', 'small', 'medium', 'large', 'full']),
|
||||||
variant: PropTypes.oneOf(['text', 'outlined', 'contained']),
|
variant: PropTypes.oneOf(['text', 'outlined', 'contained']),
|
||||||
color: PropTypes.oneOf(['default', 'primary', 'secondary']),
|
color: PropTypes.oneOf(['default', 'primary', 'secondary']),
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
elevation: PropTypes.bool,
|
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
startIcon: PropTypes.node,
|
startIcon: PropTypes.node,
|
||||||
endIcon: PropTypes.node,
|
endIcon: PropTypes.node,
|
||||||
|
|||||||
318
platform/ui/src/components/ButtonEmotion/ButtonEmotion.jsx
Normal file
318
platform/ui/src/components/ButtonEmotion/ButtonEmotion.jsx
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
import { fade } from '../../utils/colorManipulator';
|
||||||
|
import capitalize from '../../utils/capitalize';
|
||||||
|
import theme from '../../styles/theme';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
'box-sizing': 'border-box',
|
||||||
|
'min-width': '64px',
|
||||||
|
padding: '6px 16px',
|
||||||
|
'border-radius': '20px',
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
transition: 'all 300ms ease',
|
||||||
|
'&:hover': {
|
||||||
|
'text-decoration': 'none',
|
||||||
|
'background-color': fade(
|
||||||
|
theme.palette.default.main,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'&:active': {
|
||||||
|
outline: 'none',
|
||||||
|
},
|
||||||
|
'&:focus': {
|
||||||
|
outline: 'none',
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
color: theme.palette.action.disabled,
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="text"`. */
|
||||||
|
text: {
|
||||||
|
padding: '6px 8px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="text"` and `color="primary"`. */
|
||||||
|
textPrimary: {
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
'&:hover': {
|
||||||
|
'background-color': fade(
|
||||||
|
theme.palette.primary.light,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="text"` and `color="secondary"`. */
|
||||||
|
textSecondary: {
|
||||||
|
color: theme.palette.secondary.main,
|
||||||
|
'&:hover': {
|
||||||
|
'background-color': fade(
|
||||||
|
theme.palette.secondary.light,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="outlined"`. */
|
||||||
|
outlined: {
|
||||||
|
padding: '5px 15px',
|
||||||
|
border: `1px solid ${
|
||||||
|
theme.palette.type === 'light'
|
||||||
|
? 'rgba(0, 0, 0, 0.23)'
|
||||||
|
: 'rgba(255, 255, 255, 0.23)'
|
||||||
|
}`,
|
||||||
|
'&:disabled': {
|
||||||
|
border: `1px solid ${theme.palette.default.main}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="outlined"` and `color="primary"`. */
|
||||||
|
outlinedPrimary: {
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
border: `1px solid ${fade(
|
||||||
|
theme.palette.primary.light,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
)}`,
|
||||||
|
'&:hover': {
|
||||||
|
border: `1px solid ${theme.palette.primary.main}`,
|
||||||
|
'background-color': fade(
|
||||||
|
theme.palette.primary.light,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="outlined"` and `color="secondary"`. */
|
||||||
|
outlinedSecondary: {
|
||||||
|
color: theme.palette.secondary.main,
|
||||||
|
border: `1px solid ${fade(
|
||||||
|
theme.palette.secondary.main,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
)}`,
|
||||||
|
'&:hover': {
|
||||||
|
border: `1px solid ${theme.palette.secondary.main}`,
|
||||||
|
'background-color': fade(
|
||||||
|
theme.palette.secondary.light,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'&$disabled': {
|
||||||
|
border: `1px solid ${theme.palette.action.disabled}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="contained"`. */
|
||||||
|
contained: {
|
||||||
|
color: '#000',
|
||||||
|
'background-color': theme.palette.default.light,
|
||||||
|
// 'box-shadow': theme.shadows[2],
|
||||||
|
'&:hover': {
|
||||||
|
'background-color': theme.palette.default.light,
|
||||||
|
// 'box-shadow': theme.shadows[4],
|
||||||
|
|
||||||
|
'&$disabled': {
|
||||||
|
'background-color': theme.palette.action.disabledBackground,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&:active': {
|
||||||
|
// 'box-shadow': typographyows[8],
|
||||||
|
},
|
||||||
|
'&$disabled': {
|
||||||
|
color: theme.palette.action.disabled,
|
||||||
|
// 'box-shadow': theme.shadows[0],
|
||||||
|
'background-color': theme.palette.action.disabledBackground,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="contained"` and `color="primary"`. */
|
||||||
|
containedPrimary: {
|
||||||
|
color: 'white',
|
||||||
|
'background-color': theme.palette.primary.main,
|
||||||
|
'&:hover': {
|
||||||
|
'background-color': fade(
|
||||||
|
theme.palette.primary.light,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `variant="contained"` and `color="secondary"`. */
|
||||||
|
containedSecondary: {
|
||||||
|
color: 'white',
|
||||||
|
'background-color': theme.palette.secondary.main,
|
||||||
|
'&:hover': {
|
||||||
|
'background-color': fade(
|
||||||
|
theme.palette.secondary.light,
|
||||||
|
theme.palette.action.hoverOpacity
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="small"` and `variant="text"`. */
|
||||||
|
textSizeSmall: {
|
||||||
|
padding: '4px 5px',
|
||||||
|
fontSize: '13px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="medium"` and `variant="text"`. */
|
||||||
|
textSizeMedium: {
|
||||||
|
padding: '6px 9px',
|
||||||
|
fontSize: '14px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="large"` and `variant="text"`. */
|
||||||
|
textSizeLarge: {
|
||||||
|
padding: '8px 11px',
|
||||||
|
fontSize: '15px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="small"` and `variant="outlined"`. */
|
||||||
|
outlinedSizeSmall: {
|
||||||
|
padding: '3px 9px',
|
||||||
|
fontSize: '13px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="medium"` and `variant="outlined"`. */
|
||||||
|
outlinedSizeMedium: {
|
||||||
|
padding: '5px 15px',
|
||||||
|
fontSize: '14px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="large"` and `variant="outlined"`. */
|
||||||
|
outlinedSizeLarge: {
|
||||||
|
padding: '7px 21px',
|
||||||
|
fontSize: '15px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="small"` and `variant="contained"`. */
|
||||||
|
containedSizeSmall: {
|
||||||
|
padding: '4px 10px',
|
||||||
|
fontSize: '13px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="medium"` and `variant="contained"`. */
|
||||||
|
containedSizeMedium: {
|
||||||
|
padding: '6px 16px',
|
||||||
|
fontSize: '13px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the root element if `size="large"` and `variant="contained"`. */
|
||||||
|
containedSizeLarge: {
|
||||||
|
padding: '8px 22px',
|
||||||
|
fontSize: '15px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the startIcon element if supplied. */
|
||||||
|
startIcon: {
|
||||||
|
display: 'inherit',
|
||||||
|
'margin-right': '8px',
|
||||||
|
'margin-left': '-4px',
|
||||||
|
},
|
||||||
|
/* Styles applied to the endIcon element if supplied. */
|
||||||
|
endIcon: {
|
||||||
|
display: 'inherit',
|
||||||
|
'margin-right': '-4px',
|
||||||
|
'margin-left': '8px',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const BaseButton = styled.button`
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
background-color: transparent;
|
||||||
|
outline: 0;
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonIcon = styled.div`
|
||||||
|
${props => ({
|
||||||
|
...styles[`${props.icon}`],
|
||||||
|
})}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonComponent = styled(BaseButton)`
|
||||||
|
/* base styles */
|
||||||
|
${props => ({
|
||||||
|
...styles.base,
|
||||||
|
})}
|
||||||
|
|
||||||
|
/* variant styles */
|
||||||
|
${props => ({
|
||||||
|
...styles[`${props.variant}`],
|
||||||
|
})}
|
||||||
|
|
||||||
|
/* color */
|
||||||
|
${props => ({
|
||||||
|
...styles[`${props.variant}${capitalize(props.color)}`],
|
||||||
|
})}
|
||||||
|
|
||||||
|
/* size styles */
|
||||||
|
${props => ({
|
||||||
|
...styles[`${props.variant}Size${capitalize(props.size)}`],
|
||||||
|
})}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Button = props => {
|
||||||
|
const {
|
||||||
|
children,
|
||||||
|
variant = defaults.variant,
|
||||||
|
color = defaults.color,
|
||||||
|
size = defaults.size,
|
||||||
|
radius = defaults.radius,
|
||||||
|
disabled = defaults.disabled,
|
||||||
|
elevation,
|
||||||
|
type = defaults.type,
|
||||||
|
startIcon: startIconProp,
|
||||||
|
endIcon: endIconProp,
|
||||||
|
className,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
const startIcon = startIconProp && (
|
||||||
|
<ButtonIcon icon="startIcon">{startIconProp}</ButtonIcon>
|
||||||
|
);
|
||||||
|
|
||||||
|
const endIcon = endIconProp && (
|
||||||
|
<ButtonIcon icon="endIcon">{endIconProp}</ButtonIcon>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonComponent
|
||||||
|
variant={variant}
|
||||||
|
color={color}
|
||||||
|
size={size}
|
||||||
|
radius={radius}
|
||||||
|
disabled={disabled}
|
||||||
|
type={type}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{startIcon}
|
||||||
|
{children}
|
||||||
|
{endIcon}
|
||||||
|
</ButtonComponent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
variant: 'outlined',
|
||||||
|
color: 'default',
|
||||||
|
size: 'large',
|
||||||
|
radius: 'medium',
|
||||||
|
disabled: false,
|
||||||
|
elevation: true,
|
||||||
|
type: 'button',
|
||||||
|
};
|
||||||
|
|
||||||
|
Button.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
||||||
|
radius: PropTypes.oneOf(['small', 'medium', 'large', 'full']),
|
||||||
|
variant: PropTypes.oneOf(['text', 'outlined', 'contained']),
|
||||||
|
color: PropTypes.oneOf(['default', 'primary', 'secondary']),
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
elevation: PropTypes.bool,
|
||||||
|
type: PropTypes.string,
|
||||||
|
startIcon: PropTypes.node,
|
||||||
|
endIcon: PropTypes.node,
|
||||||
|
className: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Button;
|
||||||
180
platform/ui/src/components/ButtonEmotion/ButtonEmotion.mdx
Normal file
180
platform/ui/src/components/ButtonEmotion/ButtonEmotion.mdx
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
---
|
||||||
|
name: ButtonEmotion
|
||||||
|
menu: Components
|
||||||
|
route: components/button-emotion
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Playground, Props } from 'docz';
|
||||||
|
import Button from './';
|
||||||
|
|
||||||
|
# ButtonEmotion
|
||||||
|
|
||||||
|
Buttons are used to execute actions when users interacts with them.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<Props of={Button} />
|
||||||
|
|
||||||
|
## Contained Buttons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<Button variant="contained" style={{ margin: 5 }}>
|
||||||
|
Default
|
||||||
|
</Button>
|
||||||
|
<Button variant="contained" color="primary" style={{ margin: 5 }}>
|
||||||
|
Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="contained" color="secondary" style={{ margin: 5 }}>
|
||||||
|
Secondary
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Outlined Buttons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<Button variant="outlined" style={{ margin: 5 }}>
|
||||||
|
Default
|
||||||
|
</Button>
|
||||||
|
<Button variant="outlined" color="primary" style={{ margin: 5 }}>
|
||||||
|
Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="outlined" color="secondary" style={{ margin: 5 }}>
|
||||||
|
Secondary
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Text Buttons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<Button variant="text" style={{ margin: 5 }}>
|
||||||
|
Default
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" color="primary" style={{ margin: 5 }}>
|
||||||
|
Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" color="secondary" style={{ margin: 5 }}>
|
||||||
|
Secondary
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Sizes
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<Button variant="text" size="small" style={{ margin: 5 }}>
|
||||||
|
Small
|
||||||
|
</Button>
|
||||||
|
<Button variant="contained" size="medium" style={{ margin: 5 }}>
|
||||||
|
Medium
|
||||||
|
</Button>
|
||||||
|
<Button variant="outlined" size="large" style={{ margin: 5 }}>
|
||||||
|
Large
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Small
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="medium"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Medium
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
size="large"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
large
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
color="secondary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Small
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="medium"
|
||||||
|
color="secondary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Medium
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
size="large"
|
||||||
|
color="secondary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Large
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</>
|
||||||
|
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Buttons with icons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
{() => {
|
||||||
|
return (
|
||||||
|
<div className="flex">
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
startIcon={
|
||||||
|
<svg
|
||||||
|
class="fill-current w-4 h-4"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path d="M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
endIcon={
|
||||||
|
<svg
|
||||||
|
class="fill-current w-4 h-4"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path d="M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
</Playground>
|
||||||
2
platform/ui/src/components/ButtonEmotion/index.js
Normal file
2
platform/ui/src/components/ButtonEmotion/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import ButtonEmotion from './ButtonEmotion';
|
||||||
|
export default ButtonEmotion;
|
||||||
68
platform/ui/src/components/ButtonModules/ButtonModules.jsx
Normal file
68
platform/ui/src/components/ButtonModules/ButtonModules.jsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import capitalize from '../../utils/capitalize';
|
||||||
|
import styles from './ButtonModules.module.scss';
|
||||||
|
|
||||||
|
const Button = props => {
|
||||||
|
const {
|
||||||
|
children,
|
||||||
|
variant = defaults.variant,
|
||||||
|
color = defaults.color,
|
||||||
|
size = defaults.size,
|
||||||
|
type = defaults.type,
|
||||||
|
startIcon: startIconProp,
|
||||||
|
endIcon: endIconProp,
|
||||||
|
className,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
const startIcon = startIconProp && (
|
||||||
|
<div className={styles.startIcon}>{startIconProp}</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const endIcon = endIconProp && (
|
||||||
|
<div className={styles.endIcon}>{endIconProp}</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={classnames(
|
||||||
|
styles.baseButton,
|
||||||
|
styles[variant],
|
||||||
|
styles[`${variant}${capitalize(color)}`],
|
||||||
|
styles[`${variant}Size${capitalize(size)}`],
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
type={type}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{startIcon}
|
||||||
|
{children}
|
||||||
|
{endIcon}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
variant: 'outlined',
|
||||||
|
color: 'default',
|
||||||
|
size: 'large',
|
||||||
|
radius: 'medium',
|
||||||
|
disabled: false,
|
||||||
|
type: 'button',
|
||||||
|
};
|
||||||
|
|
||||||
|
Button.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
||||||
|
radius: PropTypes.oneOf(['small', 'medium', 'large', 'full']),
|
||||||
|
variant: PropTypes.oneOf(['text', 'outlined', 'contained']),
|
||||||
|
color: PropTypes.oneOf(['default', 'primary', 'secondary']),
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
type: PropTypes.string,
|
||||||
|
startIcon: PropTypes.node,
|
||||||
|
endIcon: PropTypes.node,
|
||||||
|
className: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Button;
|
||||||
180
platform/ui/src/components/ButtonModules/ButtonModules.mdx
Normal file
180
platform/ui/src/components/ButtonModules/ButtonModules.mdx
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
---
|
||||||
|
name: ButtonModules
|
||||||
|
menu: Components
|
||||||
|
route: components/button-modules
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Playground, Props } from 'docz';
|
||||||
|
import Button from './';
|
||||||
|
|
||||||
|
# ButtonModules
|
||||||
|
|
||||||
|
Buttons are used to execute actions when users interacts with them.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<Props of={Button} />
|
||||||
|
|
||||||
|
## Contained Buttons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<Button variant="contained" style={{ margin: 5 }}>
|
||||||
|
Default
|
||||||
|
</Button>
|
||||||
|
<Button variant="contained" color="primary" style={{ margin: 5 }}>
|
||||||
|
Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="contained" color="secondary" style={{ margin: 5 }}>
|
||||||
|
Secondary
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Outlined Buttons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<Button variant="outlined" style={{ margin: 5 }}>
|
||||||
|
Default
|
||||||
|
</Button>
|
||||||
|
<Button variant="outlined" color="primary" style={{ margin: 5 }}>
|
||||||
|
Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="outlined" color="secondary" style={{ margin: 5 }}>
|
||||||
|
Secondary
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Text Buttons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<Button variant="text" style={{ margin: 5 }}>
|
||||||
|
Default
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" color="primary" style={{ margin: 5 }}>
|
||||||
|
Primary
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" color="secondary" style={{ margin: 5 }}>
|
||||||
|
Secondary
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Sizes
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<Button variant="text" size="small" style={{ margin: 5 }}>
|
||||||
|
Small
|
||||||
|
</Button>
|
||||||
|
<Button variant="contained" size="medium" style={{ margin: 5 }}>
|
||||||
|
Medium
|
||||||
|
</Button>
|
||||||
|
<Button variant="outlined" size="large" style={{ margin: 5 }}>
|
||||||
|
Large
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Small
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="medium"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Medium
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
size="large"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
large
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
size="small"
|
||||||
|
color="secondary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Small
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="medium"
|
||||||
|
color="secondary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Medium
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
size="large"
|
||||||
|
color="secondary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
>
|
||||||
|
Large
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</>
|
||||||
|
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Buttons with icons
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
{() => {
|
||||||
|
return (
|
||||||
|
<div className="flex">
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
startIcon={
|
||||||
|
<svg
|
||||||
|
className="fill-current w-4 h-4"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path d="M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
endIcon={
|
||||||
|
<svg
|
||||||
|
className="fill-current w-4 h-4"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path d="M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z" />
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
</Playground>
|
||||||
@ -0,0 +1,213 @@
|
|||||||
|
$default: #aaa;
|
||||||
|
$primary: #00a;
|
||||||
|
$secondary: #a00;
|
||||||
|
$hoverOpacity: 40%;
|
||||||
|
|
||||||
|
.baseButton {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
background-color: transparent;
|
||||||
|
outline: 0;
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
text-decoration: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-width: 64px;
|
||||||
|
padding: 6px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: inherit;
|
||||||
|
transition: all 300ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: lighten($default, $hoverOpacity / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active,
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
color: $default;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="text"`. */
|
||||||
|
.text {
|
||||||
|
padding: 6px 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: lighten($default, $hoverOpacity / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="text"` and `color="primary"`. */
|
||||||
|
.textPrimary {
|
||||||
|
color: $primary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: lighten($primary, $hoverOpacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="text"` and `color="secondary"`. */
|
||||||
|
.textSecondary {
|
||||||
|
color: $secondary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: lighten($secondary, $hoverOpacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="outlined"`. */
|
||||||
|
.outlined {
|
||||||
|
padding: 5px 15px;
|
||||||
|
border: 1px solid $default;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
border: 1px solid $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="outlined"` and `color="primary"`. */
|
||||||
|
.outlinedPrimary {
|
||||||
|
color: $primary;
|
||||||
|
border: 1px solid lighten($primary, $hoverOpacity);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid $primary;
|
||||||
|
background-color: lighten($primary, $hoverOpacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="outlined"` and `color="secondary"`. */
|
||||||
|
.outlinedSecondary {
|
||||||
|
color: $secondary;
|
||||||
|
border: 1px solid lighten($secondary, $hoverOpacity);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid $secondary;
|
||||||
|
background-color: lighten($secondary, $hoverOpacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
border: 1px solid $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="contained"`. */
|
||||||
|
.contained {
|
||||||
|
color: #fff;
|
||||||
|
background-color: $default;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
color: lighten($default, $hoverOpacity);
|
||||||
|
background-color: $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($default, $hoverOpacity / 2);
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
color: lighten($default, $hoverOpacity);
|
||||||
|
background-color: $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="contained"` and `color="primary"`. */
|
||||||
|
.containedPrimary {
|
||||||
|
color: white;
|
||||||
|
background-color: $primary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($primary, $hoverOpacity / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `variant="contained"` and `color="secondary"`. */
|
||||||
|
.containedSecondary {
|
||||||
|
color: white;
|
||||||
|
background-color: $secondary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($secondary, $hoverOpacity / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="small"` and `variant="text"`. */
|
||||||
|
.textSizeSmall {
|
||||||
|
padding: 4px 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="medium"` and `variant="text"`. */
|
||||||
|
.textSizeMedium {
|
||||||
|
padding: 6px 9px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="large"` and `variant="text"`. */
|
||||||
|
.textSizeLarge {
|
||||||
|
padding: 8px 11px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="small"` and `variant="outlined"`. */
|
||||||
|
.outlinedSizeSmall {
|
||||||
|
padding: 3px 9px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="medium"` and `variant="outlined"`. */
|
||||||
|
.outlinedSizeMedium {
|
||||||
|
padding: 5px 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="large"` and `variant="outlined"`. */
|
||||||
|
.outlinedSizeLarge {
|
||||||
|
padding: 7px 21px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="small"` and `variant="contained"`. */
|
||||||
|
.containedSizeSmall {
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="medium"` and `variant="contained"`. */
|
||||||
|
.containedSizeMedium {
|
||||||
|
padding: 6px 16px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the root element if `size="large"` and `variant="contained"`. */
|
||||||
|
.containedSizeLarge {
|
||||||
|
padding: 8px 22px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the startIcon element if supplied. */
|
||||||
|
.startIcon {
|
||||||
|
display: inherit;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-left: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles applied to the endIcon element if supplied. */
|
||||||
|
.endIcon {
|
||||||
|
display: inherit;
|
||||||
|
margin-right: -4px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
2
platform/ui/src/components/ButtonModules/index.js
Normal file
2
platform/ui/src/components/ButtonModules/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import ButtonModules from './ButtonModules';
|
||||||
|
export default ButtonModules;
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import t from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const Label = ({ children, spacing, className, text, ...rest }) => {
|
const Label = ({ children, spacing, className, text, ...rest }) => {
|
||||||
const baseClasses = 'flex flex-1 flex-col text-gray-700 text-sm font-bold';
|
const baseClasses = 'flex flex-1 flex-col text-gray-700 text-sm font-bold';
|
||||||
@ -12,7 +12,7 @@ const Label = ({ children, spacing, className, text, ...rest }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label className={getClasses()}>
|
<label className={getClasses()} {...rest}>
|
||||||
{text}
|
{text}
|
||||||
{children}
|
{children}
|
||||||
</label>
|
</label>
|
||||||
@ -27,6 +27,8 @@ const spacing = {
|
|||||||
|
|
||||||
Label.defaultProps = {};
|
Label.defaultProps = {};
|
||||||
|
|
||||||
Label.prototypes = {};
|
Label.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
export default Label;
|
export default Label;
|
||||||
|
|||||||
46
platform/ui/src/styles/theme.js
Normal file
46
platform/ui/src/styles/theme.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
const theme = {
|
||||||
|
palette: {
|
||||||
|
action: {
|
||||||
|
hoverOpacity: 0.4,
|
||||||
|
disabledBackground: '',
|
||||||
|
disabled: '',
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
light: '#eee',
|
||||||
|
main: '#ccc',
|
||||||
|
dark: '#aaa',
|
||||||
|
},
|
||||||
|
primary: {
|
||||||
|
light: '#0000ff',
|
||||||
|
main: '#0000aa',
|
||||||
|
dark: '#000099',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
light: '#ff0000',
|
||||||
|
main: '#aa0000',
|
||||||
|
dark: '#990000',
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
light: '',
|
||||||
|
main: '',
|
||||||
|
dark: '',
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
light: '',
|
||||||
|
main: '',
|
||||||
|
dark: '',
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
light: '',
|
||||||
|
main: '',
|
||||||
|
dark: '',
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
light: '',
|
||||||
|
main: '',
|
||||||
|
dark: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default theme;
|
||||||
3
platform/ui/src/utils/capitalize.js
Normal file
3
platform/ui/src/utils/capitalize.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default string => {
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
};
|
||||||
270
platform/ui/src/utils/colorManipulator.js
Normal file
270
platform/ui/src/utils/colorManipulator.js
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
/* eslint-disable no-use-before-define */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a number whose value is limited to the given range.
|
||||||
|
*
|
||||||
|
* @param {number} value The value to be clamped
|
||||||
|
* @param {number} min The lower boundary of the output range
|
||||||
|
* @param {number} max The upper boundary of the output range
|
||||||
|
* @returns {number} A number in the range [min, max]
|
||||||
|
*/
|
||||||
|
function clamp(value, min = 0, max = 1) {
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
if (value < min || value > max) {
|
||||||
|
console.error(
|
||||||
|
`@ohif/ui: the value provided ${value} is out of range [${min}, ${max}].`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.min(Math.max(min, value), max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a color from CSS hex format to CSS rgb format.
|
||||||
|
*
|
||||||
|
* @param {string} color - Hex color, i.e. #nnn or #nnnnnn
|
||||||
|
* @returns {string} A CSS rgb color string
|
||||||
|
*/
|
||||||
|
export function hexToRgb(color) {
|
||||||
|
color = color.substr(1);
|
||||||
|
|
||||||
|
const re = new RegExp(`.{1,${color.length / 3}}`, 'g');
|
||||||
|
let colors = color.match(re);
|
||||||
|
|
||||||
|
if (colors && colors[0].length === 1) {
|
||||||
|
colors = colors.map(n => n + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return colors ? `rgb(${colors.map(n => parseInt(n, 16)).join(', ')})` : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function intToHex(int) {
|
||||||
|
const hex = int.toString(16);
|
||||||
|
return hex.length === 1 ? `0${hex}` : hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a color from CSS rgb format to CSS hex format.
|
||||||
|
*
|
||||||
|
* @param {string} color - RGB color, i.e. rgb(n, n, n)
|
||||||
|
* @returns {string} A CSS rgb color string, i.e. #nnnnnn
|
||||||
|
*/
|
||||||
|
export function rgbToHex(color) {
|
||||||
|
// Idempotent
|
||||||
|
if (color.indexOf('#') === 0) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { values } = decomposeColor(color);
|
||||||
|
return `#${values.map(n => intToHex(n)).join('')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a color from hsl format to rgb format.
|
||||||
|
*
|
||||||
|
* @param {string} color - HSL color values
|
||||||
|
* @returns {string} rgb color values
|
||||||
|
*/
|
||||||
|
export function hslToRgb(color) {
|
||||||
|
color = decomposeColor(color);
|
||||||
|
const { values } = color;
|
||||||
|
const h = values[0];
|
||||||
|
const s = values[1] / 100;
|
||||||
|
const l = values[2] / 100;
|
||||||
|
const a = s * Math.min(l, 1 - l);
|
||||||
|
const f = (n, k = (n + h / 30) % 12) =>
|
||||||
|
l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
||||||
|
|
||||||
|
let type = 'rgb';
|
||||||
|
const rgb = [
|
||||||
|
Math.round(f(0) * 255),
|
||||||
|
Math.round(f(8) * 255),
|
||||||
|
Math.round(f(4) * 255),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (color.type === 'hsla') {
|
||||||
|
type += 'a';
|
||||||
|
rgb.push(values[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return recomposeColor({ type, values: rgb });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object with the type and values of a color.
|
||||||
|
*
|
||||||
|
* Note: Does not support rgb % values.
|
||||||
|
*
|
||||||
|
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @returns {object} - A MUI color object: {type: string, values: number[]}
|
||||||
|
*/
|
||||||
|
export function decomposeColor(color) {
|
||||||
|
// Idempotent
|
||||||
|
if (color.type) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color.charAt(0) === '#') {
|
||||||
|
return decomposeColor(hexToRgb(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
const marker = color.indexOf('(');
|
||||||
|
const type = color.substring(0, marker);
|
||||||
|
|
||||||
|
if (['rgb', 'rgba', 'hsl', 'hsla'].indexOf(type) === -1) {
|
||||||
|
throw new Error(
|
||||||
|
[
|
||||||
|
`@ohif/ui: unsupported \`${color}\` color.`,
|
||||||
|
'We support the following formats: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla().',
|
||||||
|
].join('\n')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let values = color.substring(marker + 1, color.length - 1).split(',');
|
||||||
|
values = values.map(value => parseFloat(value));
|
||||||
|
|
||||||
|
return { type, values };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a color object with type and values to a string.
|
||||||
|
*
|
||||||
|
* @param {object} color - Decomposed color
|
||||||
|
* @param {string} color.type - One of: 'rgb', 'rgba', 'hsl', 'hsla'
|
||||||
|
* @param {array} color.values - [n,n,n] or [n,n,n,n]
|
||||||
|
* @returns {string} A CSS color string
|
||||||
|
*/
|
||||||
|
export function recomposeColor(color) {
|
||||||
|
const { type } = color;
|
||||||
|
let { values } = color;
|
||||||
|
|
||||||
|
if (type.indexOf('rgb') !== -1) {
|
||||||
|
// Only convert the first 3 values to int (i.e. not alpha)
|
||||||
|
values = values.map((n, i) => (i < 3 ? parseInt(n, 10) : n));
|
||||||
|
} else if (type.indexOf('hsl') !== -1) {
|
||||||
|
values[1] = `${values[1]}%`;
|
||||||
|
values[2] = `${values[2]}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${type}(${values.join(', ')})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the contrast ratio between two colors.
|
||||||
|
*
|
||||||
|
* Formula: https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
|
||||||
|
*
|
||||||
|
* @param {string} foreground - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @param {string} background - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @returns {number} A contrast ratio value in the range 0 - 21.
|
||||||
|
*/
|
||||||
|
export function getContrastRatio(foreground, background) {
|
||||||
|
const lumA = getLuminance(foreground);
|
||||||
|
const lumB = getLuminance(background);
|
||||||
|
return (Math.max(lumA, lumB) + 0.05) / (Math.min(lumA, lumB) + 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The relative brightness of any point in a color space,
|
||||||
|
* normalized to 0 for darkest black and 1 for lightest white.
|
||||||
|
*
|
||||||
|
* Formula: https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
|
||||||
|
*
|
||||||
|
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @returns {number} The relative brightness of the color in the range 0 - 1
|
||||||
|
*/
|
||||||
|
export function getLuminance(color) {
|
||||||
|
color = decomposeColor(color);
|
||||||
|
|
||||||
|
let rgb =
|
||||||
|
color.type === 'hsl'
|
||||||
|
? decomposeColor(hslToRgb(color)).values
|
||||||
|
: color.values;
|
||||||
|
rgb = rgb.map(val => {
|
||||||
|
val /= 255; // normalized
|
||||||
|
return val <= 0.03928 ? val / 12.92 : ((val + 0.055) / 1.055) ** 2.4;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Truncate at 3 digits
|
||||||
|
return Number(
|
||||||
|
(0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]).toFixed(3)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Darken or lighten a color, depending on its luminance.
|
||||||
|
* Light colors are darkened, dark colors are lightened.
|
||||||
|
*
|
||||||
|
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @param {number} coefficient=0.15 - multiplier in the range 0 - 1
|
||||||
|
* @returns {string} A CSS color string. Hex input values are returned as rgb
|
||||||
|
*/
|
||||||
|
export function emphasize(color, coefficient = 0.15) {
|
||||||
|
return getLuminance(color) > 0.5
|
||||||
|
? darken(color, coefficient)
|
||||||
|
: lighten(color, coefficient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the absolute transparency of a color.
|
||||||
|
* Any existing alpha values are overwritten.
|
||||||
|
*
|
||||||
|
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @param {number} value - value to set the alpha channel to in the range 0 -1
|
||||||
|
* @returns {string} A CSS color string. Hex input values are returned as rgb
|
||||||
|
*/
|
||||||
|
export function fade(color, value) {
|
||||||
|
color = decomposeColor(color);
|
||||||
|
value = clamp(value);
|
||||||
|
|
||||||
|
if (color.type === 'rgb' || color.type === 'hsl') {
|
||||||
|
color.type += 'a';
|
||||||
|
}
|
||||||
|
color.values[3] = value;
|
||||||
|
|
||||||
|
return recomposeColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Darkens a color.
|
||||||
|
*
|
||||||
|
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @param {number} coefficient - multiplier in the range 0 - 1
|
||||||
|
* @returns {string} A CSS color string. Hex input values are returned as rgb
|
||||||
|
*/
|
||||||
|
export function darken(color, coefficient) {
|
||||||
|
color = decomposeColor(color);
|
||||||
|
coefficient = clamp(coefficient);
|
||||||
|
|
||||||
|
if (color.type.indexOf('hsl') !== -1) {
|
||||||
|
color.values[2] *= 1 - coefficient;
|
||||||
|
} else if (color.type.indexOf('rgb') !== -1) {
|
||||||
|
for (let i = 0; i < 3; i += 1) {
|
||||||
|
color.values[i] *= 1 - coefficient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return recomposeColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lightens a color.
|
||||||
|
*
|
||||||
|
* @param {string} color - CSS color, i.e. one of: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla()
|
||||||
|
* @param {number} coefficient - multiplier in the range 0 - 1
|
||||||
|
* @returns {string} A CSS color string. Hex input values are returned as rgb
|
||||||
|
*/
|
||||||
|
export function lighten(color, coefficient) {
|
||||||
|
color = decomposeColor(color);
|
||||||
|
coefficient = clamp(coefficient);
|
||||||
|
|
||||||
|
if (color.type.indexOf('hsl') !== -1) {
|
||||||
|
color.values[2] += (100 - color.values[2]) * coefficient;
|
||||||
|
} else if (color.type.indexOf('rgb') !== -1) {
|
||||||
|
for (let i = 0; i < 3; i += 1) {
|
||||||
|
color.values[i] += (255 - color.values[i]) * coefficient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return recomposeColor(color);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user