Implement new button api

This commit is contained in:
Chi Vinh Le
2018-07-19 19:47:01 -03:00
parent d31d8d94e2
commit 05605d6d50
20 changed files with 452 additions and 166 deletions
+215 -60
View File
@@ -1,16 +1,17 @@
.root {
composes: button from "talk-ui/shared/typography.css";
padding: 5px 15px;
border-radius: var(--round-corners);
background-color: transparent;
position: relative;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
border: 1px solid transparent;
& > * {
margin: 0 calc(0.5 * var(--spacing-unit)) 0 0;
/* convince safari */
align-self: center;
}
& > *:last-child {
margin: 0;
@@ -28,80 +29,234 @@
box-sizing: border-box;
}
.regular:not(.disabled) {
&.mouseHover {
color: var(--palette-secondary-light);
.sizeSmall {
composes: button from "talk-ui/shared/typography.css";
padding: 4px 10px;
}
.sizeRegular {
composes: button from "talk-ui/shared/typography.css";
padding: 8px 15px;
}
.sizeLarge {
composes: buttonLarge from "talk-ui/shared/typography.css";
padding: 10px 15px;
}
.variantRegular {
&.colorRegular {
color: var(--palette-secondary-main);
}
&:active {
color: var(--palette-secondary-lighter);
&.colorPrimary {
color: var(--palette-primary-main);
}
&.colorError {
color: var(--palette-error-main);
}
&.colorSuccess {
color: var(--palette-success-main);
}
&:not(.disabled) {
&.colorRegular {
&.mouseHover {
color: var(--palette-secondary-light);
}
&:active {
color: var(--palette-secondary-lighter);
}
}
&.colorPrimary {
&.mouseHover {
color: var(--palette-primary-light);
}
&:active {
color: var(--palette-primary-lighter);
}
}
&.colorError {
&.mouseHover {
color: var(--palette-error-light);
}
&:active {
color: var(--palette-error-lighter);
}
}
&.colorSuccess {
&.mouseHover {
color: var(--palette-success-light);
}
&:active {
color: var(--palette-success-lighter);
}
}
}
}
.primary,
.primary:not(.disabled) {
background-color: var(--palette-primary-main);
color: #fff;
}
.primary:not(.disabled) {
&.mouseHover {
background-color: var(--palette-primary-light);
.variantFilled {
color: var(--palette-common-white);
&.colorRegular {
background-color: var(--palette-secondary-main);
}
&.colorPrimary {
background-color: var(--palette-primary-main);
}
&.colorError {
background-color: var(--palette-error-main);
}
&.colorSuccess {
background-color: var(--palette-success-main);
}
&:active {
background-color: var(--palette-primary-lighter);
&:not(.disabled) {
&.colorRegular {
&.mouseHover {
background-color: var(--palette-secondary-light);
}
&:active {
background-color: var(--palette-secondary-lighter);
}
}
&.colorPrimary {
&.mouseHover {
background-color: var(--palette-primary-light);
}
&:active {
background-color: var(--palette-primary-lighter);
}
}
&.colorError {
&.mouseHover {
background-color: var(--palette-error-light);
}
&:active {
background-color: var(--palette-error-lighter);
}
}
&.colorSuccess {
&.mouseHover {
background-color: var(--palette-success-light);
}
&:active {
background-color: var(--palette-success-lighter);
}
}
}
}
.primary.invert,
.primary.invert:not(.disabled) {
background-color: transparent;
border: 1px solid var(--palette-primary-main);
color: var(--palette-primary-main);
}
.primary.invert:not(.disabled) {
&.mouseHover {
border-color: var(--palette-primary-light);
color: var(--palette-primary-light);
.variantOutlined {
&.colorRegular {
color: var(--palette-secondary-main);
border: 1px solid currentColor;
}
&.colorPrimary {
color: var(--palette-primary-main);
border: 1px solid currentColor;
}
&.colorError {
color: var(--palette-error-main);
border: 1px solid currentColor;
}
&.colorSuccess {
color: var(--palette-success-main);
border: 1px solid currentColor;
}
&:active {
border-color: var(--palette-primary-lighter);
color: var(--palette-primary-lighter);
&:not(.disabled) {
&.colorRegular {
&.mouseHover {
color: var(--palette-secondary-light);
border: 1px solid currentColor;
}
&:active {
color: var(--palette-secondary-lighter);
border: 1px solid currentColor;
}
}
&.colorPrimary {
&.mouseHover {
color: var(--palette-primary-light);
border: 1px solid currentColor;
}
&:active {
color: var(--palette-primary-lighter);
border: 1px solid currentColor;
}
}
&.colorError {
&.mouseHover {
color: var(--palette-error-light);
border: 1px solid currentColor;
}
&:active {
color: var(--palette-error-lighter);
border: 1px solid currentColor;
}
}
&.colorSuccess {
&.mouseHover {
color: var(--palette-success-light);
border: 1px solid currentColor;
}
&:active {
color: var(--palette-success-lighter);
border: 1px solid currentColor;
}
}
}
}
.secondary,
.secondary:not(.disabled) {
background-color: var(--palette-secondary-main);
color: #fff;
}
.secondary:not(.disabled) {
&.mouseHover {
background-color: var(--palette-secondary-light);
.variantGhost {
&.colorRegular {
color: var(--palette-secondary-main);
}
&:active {
background-color: var(--palette-secondary-lighter);
&.colorPrimary {
color: var(--palette-primary-main);
}
}
.secondary.invert,
.secondary:not(.disabled).invert {
background-color: transparent;
border: 1px solid var(--palette-secondary-main);
color: var(--palette-secondary-main);
}
.secondary:not(.disabled).invert {
&.mouseHover {
border-color: var(--palette-secondary-light);
color: var(--palette-secondary-light);
&.colorError {
color: var(--palette-error-main);
}
&.colorSuccess {
color: var(--palette-success-main);
}
&:active {
border-color: var(--palette-secondary-lighter);
color: var(--palette-secondary-lighter);
&:not(.disabled) {
&.colorRegular {
&.mouseHover {
border: 1px solid currentColor;
}
&:active {
color: var(--palette-common-white);
background-color: var(--palette-secondary-main);
}
}
&.colorPrimary {
&.mouseHover {
border: 1px solid currentColor;
}
&:active {
color: var(--palette-common-white);
background-color: var(--palette-primary-main);
}
}
&.colorError {
&.mouseHover {
border: 1px solid currentColor;
}
&:active {
color: var(--palette-common-white);
background-color: var(--palette-error-main);
}
}
&.colorSuccess {
&.mouseHover {
border: 1px solid currentColor;
}
&:active {
color: var(--palette-common-white);
background-color: var(--palette-success-main);
}
}
}
}
+50 -21
View File
@@ -10,33 +10,62 @@ import Flex from '../Flex'
# Button
## Basic usage
## Regular Button
<Playground>
<Flex itemGutter wrap>
<Button>Push Me</Button>
<Button size="small">Push Me</Button>
<Button size="large">Push Me</Button>
<Button color="primary">Push Me</Button>
<Button color="error">Push Me</Button>
<Button color="success">Push Me</Button>
<Button disabled>Push Me</Button>
<Button anchor>I'm an Anchor Tag</Button>
<Button primary>Primary</Button>
<Button primary disabled>Primary</Button>
<Button secondary>Secondary</Button>
<Button secondary disabled>Secondary</Button>
<Button primary invert>Primary</Button>
<Button primary invert disabled>Primary</Button>
<Button secondary invert>Secondary</Button>
<Button secondary invert disabled>Secondary</Button>
<Button primary fullWidth>Full Width</Button>
<Button primary invert fullWidth>Full Width Invert</Button>
</Flex>
</Playground>
## Button with Icon
<Playground>
<Flex itemGutter>
<Button><Icon>face</Icon><span>Push Me</span></Button>
<Button primary><Icon>bookmark</Icon><span>Push Me</span></Button>
<Button primary><span>Push Me</span><Icon>build</Icon></Button>
<Button fullWidth>Push Me</Button>
</Flex>
</Playground>
## Filled Button
<Playground>
<Flex itemGutter wrap>
<Button variant="filled">Push Me</Button>
<Button variant="filled" size="small">Push Me</Button>
<Button variant="filled" size="large">Push Me</Button>
<Button variant="filled" color="primary">Push Me</Button>
<Button variant="filled" color="error">Push Me</Button>
<Button variant="filled" color="success">Push Me</Button>
<Button variant="filled" disabled>Push Me</Button>
<Button variant="filled"><Icon>face</Icon><span>Push Me</span></Button>
<Button variant="filled" fullWidth>Push Me</Button>
</Flex>
</Playground>
## Outlined Button
<Playground>
<Flex itemGutter wrap>
<Button variant="outlined">Push Me</Button>
<Button variant="outlined" size="small">Push Me</Button>
<Button variant="outlined" size="large">Push Me</Button>
<Button variant="outlined" color="primary">Push Me</Button>
<Button variant="outlined" color="error">Push Me</Button>
<Button variant="outlined" color="success">Push Me</Button>
<Button variant="outlined" disabled>Push Me</Button>
<Button variant="outlined"><Icon>face</Icon><span>Push Me</span></Button>
<Button variant="outlined" fullWidth>Push Me</Button>
</Flex>
</Playground>
## Ghost Button
<Playground>
<Flex itemGutter wrap>
<Button variant="ghost">Push Me</Button>
<Button variant="ghost" size="small">Push Me</Button>
<Button variant="ghost" size="large">Push Me</Button>
<Button variant="ghost" color="primary">Push Me</Button>
<Button variant="ghost" color="error">Push Me</Button>
<Button variant="ghost" color="success">Push Me</Button>
<Button variant="ghost" disabled>Push Me</Button>
<Button variant="ghost"><Icon>face</Icon><span>Push Me</span></Button>
<Button variant="ghost" fullWidth>Push Me</Button>
</Flex>
</Playground>
@@ -0,0 +1,49 @@
import React from "react";
import ShallowRenderer from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
import { Button } from "./Button";
it("renders correctly", () => {
const props: PropTypesOf<typeof Button> = {
classes: {
mouseHover: "mouseHover",
keyboardFocus: "keyboardFocus",
} as any,
children: "Push me",
};
const renderer = ShallowRenderer.createRenderer();
renderer.render(<Button {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("forwards ref", () => {
const props: PropTypesOf<typeof Button> = {
// tslint:disable-next-line:no-empty
forwardRef: () => {},
classes: {} as any,
children: "Push me",
};
const renderer = ShallowRenderer.createRenderer();
renderer.render(<Button {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders a regular sized, primary colored ghost button with fullWidth", () => {
const props: PropTypesOf<typeof Button> = {
color: "primary",
variant: "ghost",
fullWidth: true,
classes: {
colorPrimary: "colorPrimary",
variantGhost: "variantGhost",
sizeRegular: "sizeRegular",
fullWidth: "fullWidth",
} as any,
children: "Push me",
};
const renderer = ShallowRenderer.createRenderer();
renderer.render(<Button {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
+29 -20
View File
@@ -17,45 +17,54 @@ interface InnerProps extends ButtonHTMLAttributes<HTMLButtonElement> {
*/
classes: typeof styles & Partial<BaseButtonProps["classes"]>;
/** Size of the button */
size?: "small" | "regular" | "large";
/** Color of the button */
color?: "regular" | "primary" | "error" | "success";
/** Variant of the button */
variant?: "regular" | "filled" | "outlined" | "ghost";
/** If set renders a full width button */
fullWidth?: boolean;
/** If set renders a button with inverted borders */
invert?: boolean;
/** If set renders a button with primary colors */
primary?: boolean;
/** If set renders a button with secondary colors */
secondary?: boolean;
/** ref to the HTMLButtonElement */
ref?: Ref<HTMLButtonElement>;
/** Internal: Forwarded Ref */
forwardRef?: Ref<HTMLButtonElement>;
}
class Button extends React.Component<InnerProps> {
export class Button extends React.Component<InnerProps> {
public static defaultProps: Partial<InnerProps> = {
size: "regular",
variant: "regular",
color: "regular",
};
public render() {
const {
classes,
color,
className,
size,
fullWidth,
invert,
primary,
secondary,
disabled,
forwardRef,
variant,
...rest
} = this.props;
const rootClassName = cn(classes.root, className, {
[classes.invert]: invert,
[classes.sizeRegular]: size === "regular",
[classes.sizeSmall]: size === "small",
[classes.sizeLarge]: size === "large",
[classes.colorRegular]: color === "regular",
[classes.colorPrimary]: color === "primary",
[classes.colorError]: color === "error",
[classes.colorSuccess]: color === "success",
[classes.variantRegular]: variant === "regular",
[classes.variantFilled]: variant === "filled",
[classes.variantOutlined]: variant === "outlined",
[classes.variantGhost]: variant === "ghost",
[classes.fullWidth]: fullWidth,
[classes.primary]: primary,
[classes.secondary]: secondary,
[classes.regular]: !primary && !secondary,
[classes.disabled]: disabled,
});
@@ -0,0 +1,43 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`forwards ref 1`] = `
<withPropsOnChange(WithMouseHover)
className=""
classes={Object {}}
forwardRef={[Function]}
>
Push me
</withPropsOnChange(WithMouseHover)>
`;
exports[`renders a primary colored ghost button with fullWidth 1`] = `
<withPropsOnChange(WithMouseHover)
className=""
classes={Object {}}
>
Push me
</withPropsOnChange(WithMouseHover)>
`;
exports[`renders a regular sized, primary colored ghost button with fullWidth 1`] = `
<withPropsOnChange(WithMouseHover)
className="sizeRegular colorPrimary variantGhost fullWidth"
classes={Object {}}
>
Push me
</withPropsOnChange(WithMouseHover)>
`;
exports[`renders correctly 1`] = `
<withPropsOnChange(WithMouseHover)
className=""
classes={
Object {
"keyboardFocus": "keyboardFocus",
"mouseHover": "mouseHover",
}
}
>
Push me
</withPropsOnChange(WithMouseHover)>
`;
@@ -1,2 +1 @@
export * from "./Button";
export { default } from "./Button";
export { default, ButtonProps } from "./Button";