Skip to content

Commit

Permalink
Merge pull request #32 from reactioncommerce/docs-16-button
Browse files Browse the repository at this point in the history
fix(button): add muitheme to button; add Error button; add reactestlib; fix all tests
  • Loading branch information
mikemurray authored Jul 26, 2019
2 parents 0dec0e3 + 6ed7c84 commit f77e015
Show file tree
Hide file tree
Showing 15 changed files with 493 additions and 385 deletions.
2 changes: 1 addition & 1 deletion .reaction/scripts/templates/Component.js.template
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import PropTypes from "prop-types";
import withStyles from "@material-ui/core/styles";
import { withStyles, createMuiTheme } from '@material-ui/core/styles';

const styles = (theme) => {
root: {
Expand Down
11 changes: 4 additions & 7 deletions .reaction/scripts/templates/Component.test.js.template
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import React from "react";
import renderer from "react-test-renderer";
import { shallow } from "enzyme";
import { render } from "../../tests/index.js";
import COMPONENT from "./COMPONENT";

test("basic snapshot", () => {
const component = renderer.create(<COMPONENT />);

const tree = component.toJSON();
expect(tree).toMatchSnapshot();
test("basic snapshot - only default props", () => {
const { asFragment } = render(<COMPONENT></COMPONENT>);
expect(asFragment()).toMatchSnapshot();
});
1 change: 1 addition & 0 deletions config/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module.exports = {
appIndexJs: resolveApp('src/index.js'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
tests: resolveApp('src/tests/index.js'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveApp('src/setupTests.js'),
appNodeModules: resolveApp('node_modules'),
Expand Down
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@
"rules": {
"node/no-unsupported-features/es-syntax": "off",
"node/no-unpublished-require": "off",
"prefer-arrow-callback": [ "error", { "allowNamedFunctions": true } ]
"prefer-arrow-callback": [
"error",
{
"allowNamedFunctions": true
}
]
}
},
"eslintIgnore": [
Expand Down Expand Up @@ -121,6 +126,8 @@
"@commitlint/cli": "~7.0.0",
"@commitlint/config-conventional": "~7.0.1",
"@reactioncommerce/eslint-config": "~2.0.0",
"@testing-library/jest-dom": "^4.0.0",
"@testing-library/react": "^8.0.6",
"adr": "~1.1.1",
"autoprefixer": "~7.1.6",
"babel-core": "~7.0.0-bridge.0",
Expand All @@ -136,8 +143,6 @@
"css-loader": "~0.28.11",
"dotenv": "~4.0.0",
"dotenv-expand": "~4.0.1",
"enzyme": "~3.8.0",
"enzyme-adapter-react-16": "~1.8.0",
"eslint": "~5.12.1",
"eslint-loader": "~1.9.0",
"eslint-plugin-babel": "~5.3.0",
Expand All @@ -162,7 +167,6 @@
"raf": "~3.4.1",
"react-dev-utils": "~7.0.1",
"react-styleguidist": "^9.1.11",
"react-test-renderer": "~16.8.6",
"replace-in-files": "~1.1.4",
"rimraf": "~2.6.3",
"semantic-release": "~15.13.3",
Expand Down
69 changes: 33 additions & 36 deletions package/src/components/Button/Button.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from "react";
import PropTypes from "prop-types";
// import withStyles from "@material-ui/core/styles/withStyles";
import CircularProgress from "@material-ui/core/CircularProgress";
import MuiButton from "@material-ui/core/Button";
// import CircularProgress from "@material-ui/core/CircularProgress";
// import MuiButton from "@material-ui/core/Button";
// import makeStyles from "@material-ui/core/styles/makeStyles";
import { CircularProgress, Button as MuiButton, makeStyles } from "@material-ui/core";

/*
const styles = (theme) => ({
const useStyles = makeStyles((theme) => ({
buttonProgress: {
marginLeft: theme.spacing.unit
marginLeft: theme.spacing()
},
containedPrimary: {
"color": theme.palette.primary.contrastText,
Expand All @@ -32,25 +32,18 @@ const styles = (theme) => ({
}
}
}
});
*/
}));

/**
* @name Button
* @param {Object} props Component props
* @returns {React.Component} returns a React component
* @returns {React.Component} A React component
*/
function Button(props) {
const {
children,
classes,
color,
disabled,
isWaiting,
...otherProps
} = props;
const Button = React.forwardRef(function Button(props, ref) {
const { children, color, disabled, isWaiting, ...otherProps } = props;
const classes = useStyles();

if (color === "danger") {
if (color === "error") {
return (
<MuiButton
classes={{
Expand All @@ -59,6 +52,7 @@ function Button(props) {
}}
color="primary"
disabled={disabled || isWaiting}
ref={ref}
{...otherProps}
>
{children}
Expand All @@ -71,37 +65,40 @@ function Button(props) {
<MuiButton
color={color}
disabled={disabled || isWaiting}
ref={ref}
{...otherProps}
>
{children}
{isWaiting && <CircularProgress size={16} className={classes.buttonProgress} />}
</MuiButton>
);
}

Button.defaultProps = {
color: "default",
component: "button",
disabled: false,
disableFocusRipple: false,
disableRipple: false,
fullWidth: false,
href: null,
mini: false,
size: "medium",
variant: "text"
};
});

Button.propTypes = {
/**
* The content of the Button
*/
children: PropTypes.node,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
/**
* Options: `default` | `inherit` | `primary` | `secondary` | `danger`
*/
color: PropTypes.string,
/**
* If `true`, the button will be disabled.
*/
disabled: PropTypes.bool, // eslint-disable-line
/**
* If `true`, the CircularProgress will be displayed and the button will be disabled.
*/
isWaiting: PropTypes.bool,
/**
* onClick callback
*/
onClick: PropTypes.func
};

// withStyles() will work after 'theme' is defined in this context
// export default withStyles(styles, { name: "RuiButton" })(Button);
export default Button;

80 changes: 72 additions & 8 deletions package/src/components/Button/Button.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,85 @@
### Overview

Buttons are used to enable a user to take an action. Buttons should clearly and simply communicate the action that will happen when they are pressed.
The Catalyst Button inherits from the Material-UI [Button component](https://material-ui.com/components/buttons/). Refer to the Material-UI [Button API docs](https://material-ui.com/api/button/) for more information.

### Usage

There are four types of buttons you can choose from, and which one you choose should be based on which type of action it causes.

1. **Solid button**: The solid button is used for a primary action in a modal, card, large view and generally throughout.
1. **Outline button**: The outline button is used for a secondary or dismissive action. The outline button should be paired with the solid button in cases such as dismissing a modal or canceling an action.
1. **Danger button**: The danger button is used for a destructive action that is difficult to recover from such as deleting information. The danger button should be used at the point that the destructive action actually takes place. For example, you can have a delete button as a secondary action on a page and in this case you would use a an outline button, the outline button would then trigger a modal confirmation, which is where you would use the danger button.
1. **Important button**: The important button is used when there needs to be particular importance put on an action or in a view where there are multiple actions and more emphasis needs to be drawn to specific or most common action in a view.
#### Default Catalyst button

```jsx noeditor
This is what a button with all the default prop options looks like:

```jsx
<div style={{ display: "flex" }}>
<div style={{ marginRight: "1rem" }}>
<Button>Text-only</Button>
</div>
</div>
```

It's a button with `variant` set to `text`, `size` set to `medium`, `color` set to `default`.

#### Material UI options

- **Solid (Contained) button**: The solid button is used for a primary action in a modal, card, large view and generally throughout.
- **Outline button**: The outline button is used for a secondary or dismissive action. The outline button should be paired with the solid button in cases such as dismissing a modal or canceling an action.

```jsx
<div style={{ display: "flex" }}>
<div style={{ marginRight: "1rem" }}>
<Button>Text-only</Button>
</div>
<div style={{ marginRight: "1rem" }}>
<Button variant="contained">Solid</Button>
</div>
<div style={{ marginRight: "1rem" }}>
<Button variant="outlined">Outlined</Button>
</div>
</div>
```

- **Disabled**:

```jsx
<div style={{ display: "flex" }}>
<div style={{ marginRight: "1rem" }}>
<Button title="Default" className="myBtn">Default</Button>
<Button variant="contained" disabled>Disabled</Button>
</div>
</div>
```

- **Full Width**:

```jsx
<div style={{ display: "block" }}>
<Button variant="contained" fullWidth>FullWidth</Button>
</div>
```

#### Catalyst-custom buttons

- **Error button**: The error button is used for a destructive action that is difficult to recover from such as deleting information. The error button should be used at the point that the destructive action actually takes place. For example, you can have a delete button as a secondary action on a page and in this case you would use a an outline button, the outline button would then trigger a modal confirmation, which is where you would use the error button.

```jsx
<div style={{ display: "flex" }}>
<div style={{ marginRight: "1rem" }}>
<Button variant="contained" color="error">Error - Contained</Button>
</div>
<div style={{ marginRight: "1rem" }}>
<Button variant="outlined" color="error">Error - Outlined</Button>
</div>
</div>
```

- **isWaiting**: The `isWaiting` prop combines `disabled` with a CircularProgress animation.

```jsx
<div style={{ display: "flex" }}>
<div style={{ marginRight: "1rem" }}>
<Button variant="contained" isWaiting>isWaiting - Contained</Button>
</div>
<div style={{ marginRight: "1rem" }}>
<Button variant="outlined" isWaiting>isWaiting - Outlined</Button>
</div>
</div>
```
24 changes: 18 additions & 6 deletions package/src/components/Button/Button.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import React from "react";
import renderer from "react-test-renderer";
import mockComponents from "../../tests/mockComponents";
import { render } from "../../tests/index.js";
import Button from "./Button";

test("basic snapshot", () => {
const component = renderer.create(<Button components={mockComponents} title="title" className="a b">Submit</Button>);
test("basic snapshot - only default props", () => {
const { asFragment } = render(<Button className="myBtn">Submit</Button>);
expect(asFragment()).toMatchSnapshot();
});

test("error button snapshot", () => {
const { asFragment } = render(<Button className="myBtn" color="error" variant="contained">Delete</Button>);
expect(asFragment()).toMatchSnapshot();
});

const tree = component.toJSON();
expect(tree).toMatchSnapshot();
test("error button snapshot", () => {
const { asFragment } = render(<Button className="myBtn" color="error" variant="outlined">Delete</Button>);
expect(asFragment()).toMatchSnapshot();
});

test("isWaiting button snapshot", () => {
const { asFragment, getByText } = render(<Button className="myBtn" isWaiting>Upload</Button>);
expect(getByText("Upload")).toBeDisabled();
expect(asFragment()).toMatchSnapshot();
});
Loading

0 comments on commit f77e015

Please sign in to comment.