Skip to content

Commit

Permalink
feat(LoadingIndicator): extract and use SVG animation directly (#1540)
Browse files Browse the repository at this point in the history
- we only have one particular loading indicator we want to use at this time
- apply styles and parameters to match previous implementation's output
  • Loading branch information
booc0mtaco authored Mar 10, 2023
1 parent 8c8018b commit 6e315ea
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 52 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
"react-beautiful-dnd": "^13.1.1",
"react-children-by-type": "^1.1.0",
"react-focus-lock": "^2.9.4",
"react-loader-spinner": "^5.3.4",
"react-popper": "^2.3.0",
"react-portal": "^4.2.2"
},
Expand Down
6 changes: 6 additions & 0 deletions src/components/LoadingIndicator/LoadingIndicator.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
*/
.loading-indicator {
background-color: transparent;
padding: 3px; /* ported from react-loader-spinner */
display: flex;
}

.loading-indicator--invisible {
display: none;
}

/* override for `color` */
Expand Down
76 changes: 56 additions & 20 deletions src/components/LoadingIndicator/LoadingIndicator.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import clsx from 'clsx';
import React from 'react';

import { Oval } from 'react-loader-spinner';
import styles from './LoadingIndicator.module.css';

export type Props = {
Expand All @@ -18,17 +17,11 @@ export type Props = {

/**
* Aria label of the oval. Default is "loading". Will be overridden if ariaLabel is passed in props
* (Shadowed from OvalProps)
*
* See: https://mhnpd.github.io/react-loader-spinner/docs/components/oval
*/
ariaLabel?: string;

/**
* Whether the oval is visible. Default is true.
* (Shadowed from OvalProps)
*
* See: https://mhnpd.github.io/react-loader-spinner/docs/components/oval
*/
visible?: boolean;
};
Expand All @@ -47,14 +40,21 @@ const loaderStrokeSize = {
lg: 4,
};

// The viewport changes based on adjustments to handle the stroke width
const loaderViewportSize = {
sm: '-20 -20 42 42',
md: '-20.5 -20.5 43 43',
lg: '-21 -21 44 44',
};

/**
* BETA: This component is still a work in progress and is subject to change.
*
* `import {LoadingIndicator} from "@chanzuckerberg/eds";`
*
* Loading indicators inform users about the wait time, reason, and status of ongoing processes when the layout is unknown
*
* For screen readers, add an `aria-label` to describe what is loading.
* For screen readers, add a custom `aria-label` to describe what is loading.
*
*/
export const LoadingIndicator = ({
Expand All @@ -64,22 +64,58 @@ export const LoadingIndicator = ({
visible = true,
...other
}: Props) => {
const componentClassName = clsx(styles['loading-indicator'], className);
const componentClassName = clsx(
styles['loading-indicator'],
!visible && styles['loading-indicator--invisible'],
className,
);

// setting the colors to be transparent since we override in CSS
// (and have a lint rule prevent token variable use in components)
return (
<Oval
ariaLabel={ariaLabel}
color="transparent"
height={loaderSize[size]}
secondaryColor="transparent"
strokeWidth={loaderStrokeSize[size]}
strokeWidthSecondary={loaderStrokeSize[size]}
visible={visible}
width={loaderSize[size]}
wrapperClass={componentClassName}
<div
aria-busy="true"
aria-label={ariaLabel}
className={componentClassName}
data-testid="oval-loading"
role="status"
{...other}
/>
>
<svg
data-testid="oval-svg"
height={loaderSize[size]}
stroke="transparent"
viewBox={loaderViewportSize[size]}
width={loaderSize[size]}
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g
data-testid="oval-secondary-group"
strokeWidth={loaderStrokeSize[size]}
transform="translate(1 1)"
>
<circle
cx="0"
cy="0"
r="20"
stroke="transparent"
strokeOpacity=".5"
strokeWidth={loaderStrokeSize[size]}
></circle>
<path d="M20 0c0-9.94-8.06-20-20-20">
<animateTransform
attributeName="transform"
dur="1s"
from="0 0 0"
repeatCount="indefinite"
to="360 0 0"
type="rotate"
></animateTransform>
</path>
</g>
</g>
</svg>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ exports[`<LoadingIndicator /> Default story renders snapshot 1`] = `
class="loading-indicator"
data-testid="oval-loading"
role="status"
style="display: flex; padding: 3px;"
>
<svg
data-testid="oval-svg"
Expand Down Expand Up @@ -56,10 +55,9 @@ exports[`<LoadingIndicator /> Invisible story renders snapshot 1`] = `
<div
aria-busy="true"
aria-label="loading"
class="loading-indicator"
class="loading-indicator loading-indicator--invisible"
data-testid="oval-loading"
role="status"
style="display: none; padding: 3px;"
>
<svg
data-testid="oval-svg"
Expand Down Expand Up @@ -111,7 +109,6 @@ exports[`<LoadingIndicator /> Large story renders snapshot 1`] = `
class="loading-indicator"
data-testid="oval-loading"
role="status"
style="display: flex; padding: 3px;"
>
<svg
data-testid="oval-svg"
Expand Down Expand Up @@ -163,7 +160,6 @@ exports[`<LoadingIndicator /> Medium story renders snapshot 1`] = `
class="loading-indicator"
data-testid="oval-loading"
role="status"
style="display: flex; padding: 3px;"
>
<svg
data-testid="oval-svg"
Expand Down Expand Up @@ -215,7 +211,6 @@ exports[`<LoadingIndicator /> Small story renders snapshot 1`] = `
class="loading-indicator"
data-testid="oval-loading"
role="status"
style="display: flex; padding: 3px;"
>
<svg
data-testid="oval-svg"
Expand Down Expand Up @@ -267,7 +262,6 @@ exports[`<LoadingIndicator /> WithAriaLabel story renders snapshot 1`] = `
class="loading-indicator"
data-testid="oval-loading"
role="status"
style="display: flex; padding: 3px;"
>
<svg
data-testid="oval-svg"
Expand Down
26 changes: 2 additions & 24 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1715,7 +1715,6 @@ __metadata:
react-children-by-type: ^1.1.0
react-dom: ^18.2.0
react-focus-lock: ^2.9.4
react-loader-spinner: ^5.3.4
react-popper: ^2.3.0
react-portal: ^4.2.2
size-limit: ^8.2.4
Expand Down Expand Up @@ -17502,27 +17501,13 @@ __metadata:
languageName: node
linkType: hard

"react-is@npm:^18.0.0, react-is@npm:^18.2.0":
"react-is@npm:^18.0.0":
version: 18.2.0
resolution: "react-is@npm:18.2.0"
checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e
languageName: node
linkType: hard

"react-loader-spinner@npm:^5.3.4":
version: 5.3.4
resolution: "react-loader-spinner@npm:5.3.4"
dependencies:
react-is: ^18.2.0
styled-components: ^5.3.5
styled-tools: ^1.7.2
peerDependencies:
react: ^16.0.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0
checksum: 429ee74233b2a225164bd77cce94459c20443411248e00604a21752fabf31a36749cc4d52c2a2cf194b98b37c543e0cbb9b76a0e49188acd1f17087035544ca6
languageName: node
linkType: hard

"react-merge-refs@npm:^1.0.0":
version: 1.1.0
resolution: "react-merge-refs@npm:1.1.0"
Expand Down Expand Up @@ -19529,7 +19514,7 @@ __metadata:
languageName: node
linkType: hard

"styled-components@npm:^5.2.1, styled-components@npm:^5.3.5":
"styled-components@npm:^5.2.1":
version: 5.3.6
resolution: "styled-components@npm:5.3.6"
dependencies:
Expand All @@ -19551,13 +19536,6 @@ __metadata:
languageName: node
linkType: hard

"styled-tools@npm:^1.7.2":
version: 1.7.2
resolution: "styled-tools@npm:1.7.2"
checksum: 00cc1796085589b8d95d5a4183806d45b1d332fbc1dcf19922b01b81bd871c5a499fce64e82bb63bbead5bb8fe317f60a6e91c2fe01bf1ed79f5953977a05065
languageName: node
linkType: hard

"stylelint-config-recommended@npm:^10.0.1":
version: 10.0.1
resolution: "stylelint-config-recommended@npm:10.0.1"
Expand Down

0 comments on commit 6e315ea

Please sign in to comment.