Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LoadingButton] Introduce new component #21389

Merged
merged 38 commits into from Jun 15, 2020
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8361424
wip
mnajdova Jun 10, 2020
1e1de47
wip
mnajdova Jun 10, 2020
ec083e3
added position
mnajdova Jun 10, 2020
d9bea4c
renamed to LoadingButton
mnajdova Jun 10, 2020
6071393
fixed children
mnajdova Jun 10, 2020
fa7701d
fix width change when changing state
mnajdova Jun 10, 2020
375cf71
renamed props and component
mnajdova Jun 12, 2020
276167c
Update packages/material-ui/src/BusyButton/BusyButton.js
mnajdova Jun 12, 2020
e6f5a86
Update docs/src/pages/components/buttons/BusyButtons.js
mnajdova Jun 12, 2020
bc84de4
Update docs/src/pages/components/buttons/BusyButtons.js
mnajdova Jun 12, 2020
f8d4eb4
Update packages/material-ui/src/BusyButton/BusyButton.d.ts
mnajdova Jun 12, 2020
2ea5ad0
addressing comments
mnajdova Jun 12, 2020
a0a2370
fixed position
mnajdova Jun 12, 2020
e877474
comments
mnajdova Jun 12, 2020
5cf4b74
proptypes
mnajdova Jun 12, 2020
e1f983a
proptypes
mnajdova Jun 12, 2020
09c5321
fixed
mnajdova Jun 12, 2020
bc6edf8
Merge branch 'master' into feat/loading-button
mnajdova Jun 12, 2020
b4ff58c
Update docs/src/pages/components/buttons/buttons.md
oliviertassinari Jun 12, 2020
4b58e57
comments
mnajdova Jun 13, 2020
0a866c2
Merge branch 'feat/loading-button' of https://github.com/mnajdova/mat…
mnajdova Jun 13, 2020
7885994
Update packages/material-ui/src/BusyButton/BusyButton.js
mnajdova Jun 13, 2020
5e161ea
Update packages/material-ui/src/BusyButton/BusyButton.js
mnajdova Jun 13, 2020
a531d8c
proptypes
mnajdova Jun 13, 2020
b526739
prettier + docs:api
mnajdova Jun 13, 2020
ae84a9a
yarn proptypes --disable-cache
oliviertassinari Jun 13, 2020
0a8847d
switch label
oliviertassinari Jun 13, 2020
de31d86
Update packages/material-ui/src/BusyButton/BusyButton.js
mnajdova Jun 13, 2020
2e9162d
Update packages/material-ui/src/BusyButton/BusyButton.js
oliviertassinari Jun 13, 2020
22dc72c
comments
mnajdova Jun 13, 2020
f855cd2
empty commit to run argos twice and compare diff
oliviertassinari Jun 13, 2020
916d6a0
moved BusyButton to lab
mnajdova Jun 14, 2020
fc1e8ba
Merge branch 'feat/loading-button' of https://github.com/mnajdova/mat…
mnajdova Jun 14, 2020
6b259c8
docs:api
mnajdova Jun 14, 2020
60d7f8b
fixed description
mnajdova Jun 14, 2020
fde687e
renamed BusyButton to LoadingButton
mnajdova Jun 15, 2020
364b265
docs:api
mnajdova Jun 15, 2020
98b6c6c
added classes keys
mnajdova Jun 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/pages/api-docs/busy-button.js
@@ -0,0 +1,15 @@
import React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import { prepareMarkdown } from 'docs/src/modules/utils/parseMarkdown';

const pageFilename = 'api/busy-button';
const requireRaw = require.context('!raw-loader!./', false, /\/busy-button\.md$/);

export default function Page({ docs }) {
return <MarkdownDocs docs={docs} />;
}

Page.getInitialProps = () => {
const { demos, docs } = prepareMarkdown({ pageFilename, requireRaw });
return { demos, docs };
};
72 changes: 72 additions & 0 deletions docs/pages/api-docs/busy-button.md
@@ -0,0 +1,72 @@
---
filename: /packages/material-ui/src/BusyButton/BusyButton.js
---

<!--- This documentation is automatically generated, do not try to edit it. -->

# BusyButton API

<p class="description">The API documentation of the BusyButton React component. Learn more about the props and the CSS customization points.</p>

## Import

```js
import BusyButton from '@material-ui/core/BusyButton';
// or
import { BusyButton } from '@material-ui/core';
```

You can learn more about the difference by [reading this guide](/guides/minimizing-bundle-size/).



## Component name

The `MuiBusyButton` name can be used for providing [default props](/customization/globals/#default-props) or [style overrides](/customization/globals/#css) at the theme level.

## Props

| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| <span class="prop-name">children</span> | <span class="prop-type">node</span> | | The content of the button. |
| <span class="prop-name">classes</span> | <span class="prop-type">object</span> | | Override or extend the styles applied to the component. See [CSS API](#css) below for more details. |
| <span class="prop-name">disabled</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the button will be disabled. |
| <span class="prop-name">pending</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | The content of the button. |
| <span class="prop-name">pendingIndicator</span> | <span class="prop-type">node</span> | <span class="prop-default">&lt;CircularProgress color="inherit" size={16} /></span> | Element placed before the children if the button is in pending state. |
| <span class="prop-name">pendingPosition</span> | <span class="prop-type">'start'<br>&#124;&nbsp;'end'<br>&#124;&nbsp;'center'</span> | <span class="prop-default">'center'</span> | The pending indicator can be positioned on the start, end, or the center of the button. |

The `ref` is forwarded to the root element.

Any other props supplied will be provided to the root element ([Button](/api/button/)).

## CSS

| Rule name | Global class | Description |
|:-----|:-------------|:------------|
| <span class="prop-name">root</span> | <span class="prop-name">.MuiBusyButton-root</span> | Styles applied to the root element.
| <span class="prop-name">pending</span> | <span class="prop-name">.MuiBusyButton-pending</span> | Styles applied to the root element if `pending={true}`.
| <span class="prop-name">pendingIndicator</span> | <span class="prop-name">.MuiBusyButton-pendingIndicator</span> | Styles applied to the pendingIndicator element.
| <span class="prop-name">pendingIndicatorCenter</span> | <span class="prop-name">.MuiBusyButton-pendingIndicatorCenter</span> | Styles applied to the pendingIndicator element if `pendingPosition="center"`.
| <span class="prop-name">pendingIndicatorStart</span> | <span class="prop-name">.MuiBusyButton-pendingIndicatorStart</span> | Styles applied to the pendingIndicator element if `pendingPosition="start"`.
| <span class="prop-name">pendingIndicatorEnd</span> | <span class="prop-name">.MuiBusyButton-pendingIndicatorEnd</span> | Styles applied to the pendingIndicator element if `pendingPosition="end"`.
| <span class="prop-name">endIconLoadingEnd</span> | <span class="prop-name">.MuiBusyButton-endIconLoadingEnd</span> | Styles applied to the endIcon element if `pending={true}` and `pendingPosition="end"`.
| <span class="prop-name">startIconLoadingStart</span> | <span class="prop-name">.MuiBusyButton-startIconLoadingStart</span> | Styles applied to the startIcon element if `pending={true}` and `pendingPosition="start"`.
| <span class="prop-name">labelLoadingCenter</span> | <span class="prop-name">.MuiBusyButton-labelLoadingCenter</span> | Styles applied to the label element if `pending={true}` and `pendingPosition="center"`.

You can override the style of the component thanks to one of these customization points:

- With a rule name of the [`classes` object prop](/customization/components/#overriding-styles-with-classes).
- With a [global class name](/customization/components/#overriding-styles-with-global-class-names).
- With a theme and an [`overrides` property](/customization/globals/#css).

If that's not sufficient, you can check the [implementation of the component](https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/BusyButton/BusyButton.js) for more detail.

## Inheritance

The props of the [Button](/api/button/) component are also available.
You can take advantage of this behavior to [target nested components](/guides/api/#spread).

## Demos

- [Buttons](/components/buttons/)

30 changes: 30 additions & 0 deletions docs/src/pages/components/buttons/BusyButtons.js
@@ -0,0 +1,30 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import BusyButton from '@material-ui/core/BusyButton';
import SaveIcon from '@material-ui/icons/Save';

const useStyles = makeStyles((theme) => ({
root: {
'& button': {
margin: theme.spacing(1),
},
},
}));

export default function BusyButtons() {
const classes = useStyles();

return (
<div className={classes.root}>
<BusyButton variant="outlined" pending>
Submit
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
</BusyButton>
<BusyButton variant="outlined" pending pendingIndicator="Loading...">
Fetch data
</BusyButton>
<BusyButton variant="outlined" pending pendingPosition="start" startIcon={<SaveIcon />}>
Save
</BusyButton>
</div>
);
}
30 changes: 30 additions & 0 deletions docs/src/pages/components/buttons/BusyButtons.tsx
@@ -0,0 +1,30 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import BusyButton from '@material-ui/core/BusyButton';
import SaveIcon from '@material-ui/icons/Save';

const useStyles = makeStyles((theme) => ({
root: {
'& button': {
margin: theme.spacing(1),
},
},
}));

export default function BusyButtons() {
const classes = useStyles();

return (
<div className={classes.root}>
<BusyButton variant="outlined" pending>
Submit
</BusyButton>
<BusyButton variant="outlined" pending pendingIndicator="Loading...">
Fetch data
</BusyButton>
<BusyButton variant="outlined" pending pendingPosition="start" startIcon={<SaveIcon />}>
Save
</BusyButton>
</div>
);
}
64 changes: 64 additions & 0 deletions docs/src/pages/components/buttons/BusyButtonsTransition.js
@@ -0,0 +1,64 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import BusyButton from '@material-ui/core/BusyButton';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Switch from '@material-ui/core/Switch';
import SaveIcon from '@material-ui/icons/Save';
import SendIcon from '@material-ui/icons/Send';

const useStyles = makeStyles((theme) => ({
root: {
'& button': {
margin: theme.spacing(1),
},
},
switch: {
display: 'block',
},
}));

export default function BusyButtonsTransition() {
const classes = useStyles();
const [pending, setPending] = React.useState(false);

return (
<div className={classes.root}>
<FormControlLabel
control={
<Switch
checked={pending}
onChange={() => setPending(!pending)}
name="pending"
color="primary"
/>
}
className={classes.switch}
label="Pending"
/>
<BusyButton variant="outlined" pending={pending}>
Submit
</BusyButton>
<BusyButton variant="outlined" pending={pending} pendingIndicator="Loading...">
Fetch data
</BusyButton>
<BusyButton
variant="contained"
color="primary"
pending={pending}
pendingPosition="end"
endIcon={<SendIcon />}
>
Send
</BusyButton>
<BusyButton
variant="contained"
color="secondary"
pending={pending}
pendingPosition="start"
startIcon={<SaveIcon />}
>
Save
</BusyButton>
</div>
);
}
64 changes: 64 additions & 0 deletions docs/src/pages/components/buttons/BusyButtonsTransition.tsx
@@ -0,0 +1,64 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import BusyButton from '@material-ui/core/BusyButton';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Switch from '@material-ui/core/Switch';
import SaveIcon from '@material-ui/icons/Save';
import SendIcon from '@material-ui/icons/Send';

const useStyles = makeStyles((theme) => ({
root: {
'& button': {
margin: theme.spacing(1),
},
},
switch: {
display: 'block',
},
}));

export default function BusyButtonsTransition() {
const classes = useStyles();
const [pending, setPending] = React.useState(false);

return (
<div className={classes.root}>
<FormControlLabel
control={
<Switch
checked={pending}
onChange={() => setPending(!pending)}
name="pending"
color="primary"
/>
}
className={classes.switch}
label="Pending"
/>
<BusyButton variant="outlined" pending={pending}>
Submit
</BusyButton>
<BusyButton variant="outlined" pending={pending} pendingIndicator="Loading...">
Fetch data
</BusyButton>
<BusyButton
variant="contained"
color="primary"
pending={pending}
pendingPosition="end"
endIcon={<SendIcon />}
>
Send
</BusyButton>
<BusyButton
variant="contained"
color="secondary"
pending={pending}
pendingPosition="start"
startIcon={<SaveIcon />}
>
Save
</BusyButton>
</div>
);
}
12 changes: 11 additions & 1 deletion docs/src/pages/components/buttons/buttons.md
@@ -1,6 +1,6 @@
---
title: Button React component
components: Button, IconButton, ButtonBase
components: Button, IconButton, ButtonBase, BusyButton
---

# Button
Expand Down Expand Up @@ -94,6 +94,16 @@ Here are some examples of customizing the component. You can learn more about th

🎨 If you are looking for inspiration, you can check [MUI Treasury's customization examples](https://mui-treasury.com/styles/button).

## Busy buttons

The busy buttons can show pending state and disable interactions.

{{"demo": "pages/components/buttons/BusyButtons.js"}}
mnajdova marked this conversation as resolved.
Show resolved Hide resolved

Toggle the switch to see the transition between the different states.

{{"demo": "pages/components/buttons/BusyButtonsTransition.js"}}

## Complex Buttons

The Text Buttons, Contained Buttons, Floating Action Buttons and Icon Buttons are built on top of the same component: the `ButtonBase`.
Expand Down
46 changes: 46 additions & 0 deletions packages/material-ui/src/BusyButton/BusyButton.d.ts
@@ -0,0 +1,46 @@
import { ExtendButton, ExtendButtonTypeMap } from '../Button';
import { OverrideProps } from '../OverridableComponent';

export type BusyButtonTypeMap<
P = {},
D extends React.ElementType = 'button'
> = ExtendButtonTypeMap<{
props: P & {
/**
* The content of the button.
*/
pending?: boolean;
/**
* Element placed before the children if the button is in pending state.
*/
pendingIndicator?: React.ReactNode;
/**
* The pending indicator can be positioned on the start, end, or the center of the button.
*/
pendingPosition?: 'start' | 'end' | 'center';
};
defaultComponent: D;
classKey: BusyButtonClassKey;
}>;

/**
*
* Demos:
*
* - [Buttons](https://material-ui.com/components/buttons/)
*
* API:
*
* - [BusyButton API](https://material-ui.com/api/busy-button/)
* - inherits [Button API](https://material-ui.com/api/button/)
*/
declare const BusyButton: ExtendButton<BusyButtonTypeMap>;

export type BusyButtonProps<
D extends React.ElementType = BusyButtonTypeMap['defaultComponent'],
P = {}
> = OverrideProps<BusyButtonTypeMap<P, D>, D>;

export type BusyButtonClassKey = 'root' | 'pending';

export default BusyButton;