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

add loading state to Button #833

Merged
merged 3 commits into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions spec/__snapshots__/Storyshots.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2833,6 +2833,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-google btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -2883,6 +2884,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-google btn-md"
disabled={true}
type="button"
Expand Down Expand Up @@ -2939,6 +2941,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-facebook btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -2989,6 +2992,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-facebook btn-md"
disabled={true}
type="button"
Expand Down Expand Up @@ -3046,6 +3050,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-linkedin btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -3096,6 +3101,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-linkedin btn-md"
disabled={true}
type="button"
Expand Down Expand Up @@ -3152,6 +3158,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-twitter btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -3202,6 +3209,7 @@ exports[`Storyshots Components/Button Brands 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-brand-twitter btn-md"
disabled={true}
type="button"
Expand Down Expand Up @@ -3321,6 +3329,7 @@ exports[`Storyshots Components/Button Danger 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-danger btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -3447,6 +3456,7 @@ exports[`Storyshots Components/Button Danger 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-danger btn-md"
disabled={true}
type="button"
Expand Down Expand Up @@ -3532,6 +3542,7 @@ exports[`Storyshots Components/Button Link 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-link btn-sm"
disabled={true}
type="button"
Expand All @@ -3541,6 +3552,120 @@ exports[`Storyshots Components/Button Link 1`] = `
</div>
`;

exports[`Storyshots Components/Button Loading 1`] = `
<div
style={
Object {
"padding": "1rem",
}
}
>
<button
aria-disabled={true}
className="Button btn btn-primary btn-sm"
disabled={true}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-spinner-third fa-w-16 icon-left btn-loading-spin"
data-icon="spinner-third"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z"
fill="currentColor"
style={Object {}}
/>
</svg>
Loading...
</button>

<button
aria-disabled={true}
className="Button btn btn-outline-primary btn-sm"
disabled={true}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-spinner-third fa-w-16 icon-left btn-loading-spin"
data-icon="spinner-third"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z"
fill="currentColor"
style={Object {}}
/>
</svg>
Loading...
</button>

<button
aria-disabled={true}
className="Button btn btn-primary btn-md"
disabled={true}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-spinner-third fa-w-16 icon-left btn-loading-spin"
data-icon="spinner-third"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z"
fill="currentColor"
style={Object {}}
/>
</svg>
Loading...
</button>

<button
aria-disabled={true}
className="Button btn btn-outline-primary btn-md"
disabled={true}
type="button"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-spinner-third fa-w-16 icon-left btn-loading-spin"
data-icon="spinner-third"
data-prefix="far"
focusable="false"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z"
fill="currentColor"
style={Object {}}
/>
</svg>
Loading...
</button>
</div>
`;

exports[`Storyshots Components/Button Primary 1`] = `
<div
style={
Expand Down Expand Up @@ -3634,6 +3759,7 @@ exports[`Storyshots Components/Button Primary 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-primary btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -3760,6 +3886,7 @@ exports[`Storyshots Components/Button Primary 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-primary btn-md"
disabled={true}
type="button"
Expand Down Expand Up @@ -3896,6 +4023,7 @@ exports[`Storyshots Components/Button Transparent 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-transparent btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -4022,6 +4150,7 @@ exports[`Storyshots Components/Button Transparent 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-transparent btn-md"
disabled={true}
type="button"
Expand Down Expand Up @@ -4158,6 +4287,7 @@ exports[`Storyshots Components/Button Warning 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-warning btn-sm"
disabled={true}
type="button"
Expand Down Expand Up @@ -4284,6 +4414,7 @@ exports[`Storyshots Components/Button Warning 1`] = `
</button>

<button
aria-disabled={true}
className="Button btn btn-warning btn-md"
disabled={true}
type="button"
Expand Down
27 changes: 24 additions & 3 deletions src/Button/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { forwardRef } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSpinnerThird } from '@fortawesome/pro-regular-svg-icons';

import { Button as RBButton } from 'react-bootstrap';

Expand All @@ -10,32 +11,52 @@ import './Button.scss';
const Button = forwardRef(({
children,
className,
disabled,
isLoading,
leadingIcon,
loadingText,
trailingIcon,
...props
}, ref) => (
<RBButton
aria-disabled={disabled || isLoading}
className={classNames('Button', className)}
disabled={disabled || isLoading}
ref={ref}
{...props}
>
{ leadingIcon && (<FontAwesomeIcon className="icon-left" icon={leadingIcon} />)}
{ children }
{ trailingIcon && (<FontAwesomeIcon className="icon-right" icon={trailingIcon} />)}
{ !isLoading ? (
<>
{ leadingIcon && (<FontAwesomeIcon className="icon-left" icon={leadingIcon} />)}
{ children }
{ trailingIcon && (<FontAwesomeIcon className="icon-right" icon={trailingIcon} />)}
</>
) : (
<>
<FontAwesomeIcon className="icon-left btn-loading-spin" icon={faSpinnerThird} />
{loadingText}
</>
)}
</RBButton>
));

Button.propTypes = {
children: PropTypes.any,
className: PropTypes.string,
disabled: PropTypes.bool,
isLoading: PropTypes.bool,
leadingIcon: PropTypes.object,
loadingText: PropTypes.string,
trailingIcon: PropTypes.object,
};

Button.defaultProps = {
children: undefined,
className: undefined,
disabled: false,
isLoading: undefined,
leadingIcon: undefined,
loadingText: 'Loading...',
trailingIcon: undefined,
};
export default Button;
15 changes: 15 additions & 0 deletions src/Button/Button.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ArgsTable, Story, Canvas } from '@storybook/addon-docs/blocks';
import { Button } from 'src/Button';

# Button

Expand All @@ -12,6 +13,10 @@ import { ArgsTable, Story, Canvas } from '@storybook/addon-docs/blocks';
<Story id="components-button--primary" />
</Canvas>

## Props

<ArgsTable of={Button} />

## Anatomy:
- **Leading icon (optional):** Should be included when the button has a clear action verb (e.g. Edit, Save, Delete)
- **Label:** Utilizes sentence-casing (e.g. “New project”)
Expand Down Expand Up @@ -94,3 +99,13 @@ import { ArgsTable, Story, Canvas } from '@storybook/addon-docs/blocks';
<Story id="components-button--brands" />
</Preview>

### Loading
- The loading state is displayed when an action has been initiated and the system is processing it.
For instance, when a page is being saved or a file is uploading, the button typically transforms into a loading state with altered
loading text and a spinner. This is accompanied by a disabled state to prevent duplicated actions.

<Preview>
<Story id="components-button--loading" />
</Preview>


13 changes: 13 additions & 0 deletions src/Button/Button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@
}
}

.btn-loading-spin {
animation: spin infinite 0.6s linear;
}

@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

&.btn-sm {
border-radius: $ux-border-radius;
}
Expand Down
Loading