Skip to content
This repository has been archived by the owner on Jun 5, 2023. It is now read-only.

Commit

Permalink
feat: add button loading state and right arrow icon, #163 (#200)
Browse files Browse the repository at this point in the history
* feat: add right arrow icon, #163

* feat: add button loading state, #163

* feat: add button loading state examples, #163

* fix: making suggested changes, #163

* fix: making suggested changes, #163
  • Loading branch information
SarahHouben authored May 3, 2022
1 parent 110a07c commit 3dc590a
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 93 deletions.
3 changes: 3 additions & 0 deletions src-icons/svg/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions src/Button/README.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ Basic button types and sizes:
<Button isActive size="medium">
Done
</Button>
<Button iconRight icon="arrow-right" isActive size="medium">
Let's go
</Button>
</InlineList>
</Canvas>

Expand All @@ -95,6 +98,37 @@ Disabled:
<Button isDisabled isActive size="medium">
Done
</Button>
<Button isDisabled iconRight icon="arrow-right" isActive size="medium">
Let's go
</Button>
</InlineList>
</Canvas>

Loading:

<Canvas>
<InlineList spacing="s">
<Button isLoading color="primary" icon="ok">
Save
</Button>
<Button isLoading> Cancel</Button>
<Button isLoading size="medium" color="important">
Delete
</Button>
<Button isLoading size="medium" icon="send">
Share
</Button>
<Button isLoading icon="tools" size="medium" color="shaded" />
<Button isLoading size="small" color="transparent">
Forgot password?
</Button>
<Button isLoading round icon="plus" color="important" />
<Button isLoading isActive size="medium">
Done
</Button>
<Button isLoading iconRight icon="arrow-right" isActive size="medium">
Let's go
</Button>
</InlineList>
</Canvas>

Expand Down Expand Up @@ -137,6 +171,32 @@ Change the props in the table below to adjust the Button to your needs.
</Story>
</Canvas>

Test the button loading state.

<Canvas>
<Story name="Loading example">
{() => {
const [isLoading, setIsLoading] = React.useState(false);
const buttonClick = () => {
setIsLoading(true);
setTimeout(() => {
setIsLoading(false);
}, "3000")
};
return (
<Button
iconRight
icon="arrow-right"
onClick={buttonClick}
isLoading={isLoading}
>
Next
</Button>
);
}}
</Story>
</Canvas>

## Props

<ArgsTable story="Button" />
69 changes: 59 additions & 10 deletions src/Button/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {forwardRef} from 'react';
import PropTypes from 'prop-types';
import styled, {css} from 'styled-components';
import styled, {css, keyframes} from 'styled-components';

import {alpha, mix, getSolidBackgroundShade, isDark} from '../utils/colors';
import {pxToRem} from '../utils/units';
Expand Down Expand Up @@ -42,6 +42,7 @@ const shouldForwardProp = getPropFilter([
'round',
'square',
'fullWidth',
'isLoading',
'color',
'size',
'align',
Expand Down Expand Up @@ -169,7 +170,7 @@ const Wrapper = styled(ButtonCore).withConfig({
}
}}
cursor: not-allowed;
cursor: ${p => (p.isLoading ? 'wait' : 'not-allowed')};
${p =>
(p.color === 'transparent' || p.color === 'shaded') &&
Expand Down Expand Up @@ -269,6 +270,26 @@ const ButtonText = styled.span.withConfig({
${p => (p.textOverflow === 'ellipsis' ? ellipsis : overflowWrap)}
`;

const spin = keyframes`
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
`;

const SpinningIcon = styled(Icon)`
animation: ${spin} 0.6s infinite linear both;
`;

const SpinnerDot = () => (
<SpinningIcon name="spinnerdot" disablePointerEvents />
);

const IconButton = ({isLoading, name}) =>
isLoading ? <SpinnerDot /> : <Icon disablePointerEvents name={name} />;

const Button = forwardRef((props, ref) => {
const {
iconOnly,
Expand All @@ -281,6 +302,9 @@ const Button = forwardRef((props, ref) => {
fullWidth,
title,
textOverflow,
isLoading,
isDisabled,
loadingLabel,
...otherProps
} = props;

Expand All @@ -296,24 +320,40 @@ const Button = forwardRef((props, ref) => {
align={align}
fullWidth={fullWidth || textOverflow === 'ellipsis'}
{...otherProps}
aria-live={isLoading !== undefined ? 'polite' : undefined}
isDisabled={isDisabled || isLoading}
isLoading={isLoading}
>
<HoverShade />
<FocusRing color={color} />
<Content align={align}>
{icon && iconRight !== true && (
<Icon disablePointerEvents name={icon} />
<IconButton
isLoading={isLoading && (!iconRight || iconOnly)}
name={icon}
/>
)}
{children &&
(iconOnly ? (
<VisuallyHidden>{children}</VisuallyHidden>
) : (
<ButtonText textOverflow={textOverflow}>
<VisuallyHidden>
{children}
</ButtonText>
{isLoading && loadingLabel}
</VisuallyHidden>
) : (
<>
<ButtonText textOverflow={textOverflow}>
{children}
</ButtonText>
{isLoading && (
<VisuallyHidden>{loadingLabel}</VisuallyHidden>
)}
{!icon && isLoading && <SpinnerDot />}
</>
))}
{iconRight && (
<Icon
disablePointerEvents

{!iconOnly && iconRight && (
<IconButton
isLoading={isLoading}
name={hasSeparateRightIcon ? iconRight : icon}
/>
)}
Expand All @@ -327,6 +367,7 @@ Button.displayName = 'Button';
Button.defaultProps = {
color: 'default',
textOverflow: 'wrap',
loadingLabel: 'Loading…',
};

Button.propTypes = {
Expand All @@ -345,6 +386,14 @@ Button.propTypes = {
* can still be read out by screen readers.
*/
isDisabled: PropTypes.bool,
/**
* Renders the button in its loading state.
*/
isLoading: PropTypes.bool,
/**
* Renders the hidden loading label for the button in its loading state.
*/
loadingLabel: PropTypes.string,
/**
* Choose an icon to display next to the button's label
*/
Expand Down
2 changes: 2 additions & 0 deletions src/Icon/iconMap.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const iconMap = {
arrow: require('../icons/Arrow').default,
'arrow-left': require('../icons/Arrow').default,
'arrow-right': require('../icons/ArrowRight').default,
asset: require('../icons/AssetDefault').default,
'asset-activity': require('../icons/AssetActivity').default,
'asset-audio': require('../icons/AssetAudio').default,
Expand Down
1 change: 1 addition & 0 deletions src/docs/3-icons.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Icon from '../Icon';

<Canvas>
<Icon name="arrow" />
<Icon name="arrow-right" />
<Icon name="asset" />
<Icon name="asset-activity" />
<Icon name="asset-audio" />
Expand Down
39 changes: 39 additions & 0 deletions src/icons/ArrowRight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, {forwardRef} from 'react';

import Svg from './BaseSvg';
import { SVGRProps } from './util';

const ArrowRightIcon = forwardRef<SVGSVGElement, SVGRProps>((props, ref) => {
const {size, color, ...otherProps} = props;

// Unless the icon has an explicit ARIA label, we'll hide it visually
const ariaHidden =
!(otherProps['aria-label'] || otherProps['aria-labelledby']) ||
undefined;

return (
<Svg
{...otherProps}
ref={ref}
viewBox="0 0 18 18"
width={size}
height={size}
fill={color}
fillRule="evenodd"
clipRule="evenodd"
focusable="false"
aria-hidden={ariaHidden}
>
<path d="M15.703 9.71098L11.414 14C11.024 14.39 10.39 14.39 10 14C9.61001 13.61 9.61001 12.976 10 12.586L12.586 9.99998L3.00001 9.99998C2.44501 9.99698 2.00001 9.54998 2.00001 8.99998C2.00001 8.44998 2.44501 8.00298 3.00001 7.99998L12.586 7.99998L9.98001 5.39398C9.58901 5.00398 9.58901 4.36998 9.98001 3.97998C10.37 3.58898 11.004 3.58898 11.394 3.97998L15.703 8.28898L15.707 8.29298C15.774 8.35898 15.829 8.43298 15.873 8.51398L15.879 8.52398L15.88 8.52498L15.886 8.53498L15.912 8.59198L15.921 8.61098L15.923 8.61398L15.927 8.62298L15.945 8.67598L15.955 8.70298L15.956 8.70798L15.959 8.71498L15.971 8.76498L15.98 8.79898V8.80298L15.982 8.80898L15.983 8.81698L15.995 8.89798L16 8.99998L15.995 9.10198L15.983 9.18298L15.982 9.19098L15.98 9.19698V9.20098L15.971 9.23498L15.959 9.28498L15.956 9.29198L15.955 9.29698L15.945 9.32398L15.927 9.37698L15.923 9.38598L15.921 9.38898L15.912 9.40798L15.886 9.46498L15.88 9.47498L15.879 9.47598L15.873 9.48598C15.829 9.56698 15.774 9.64098 15.707 9.70698L15.703 9.71098V9.71098Z" />
</Svg>
);
});

ArrowRightIcon.displayName = 'ArrowRightIcon';

ArrowRightIcon.defaultProps = {
size: 18,
color: 'currentcolor',
};

export default ArrowRightIcon;
Loading

0 comments on commit 3dc590a

Please sign in to comment.