-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(LoadingIndicator)!: introduce 2.0 component (#1963)
- add tests and snapshots - update API and component documentation - update token usages
- Loading branch information
1 parent
675ad5f
commit 26faab7
Showing
7 changed files
with
577 additions
and
0 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
src/components/LoadingIndicator/LoadingIndicator-v2.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/*------------------------------------*\ | ||
# LOADINGINDICATOR | ||
\*------------------------------------*/ | ||
|
||
/** | ||
* LoadingIndicator | ||
*/ | ||
.loading-indicator { | ||
background-color: transparent; | ||
padding: 3px; /* ported from react-loader-spinner */ | ||
display: flex; | ||
} | ||
|
||
.loading-indicator--invisible { | ||
display: none; | ||
} | ||
|
||
/* override for `color` */ | ||
.loading-indicator > svg path { | ||
stroke: var(--eds-theme-color-border-utility-informational); | ||
} | ||
|
||
/* override for `secondaryColor` */ | ||
.loading-indicator > svg circle { | ||
stroke: var(--eds-theme-color-border-utility-default-low-emphasis); | ||
stroke-opacity: 1; | ||
} | ||
|
||
@media screen and (prefers-reduced-motion: reduce) { | ||
/* if reducing motion, don't show the moving portion */ | ||
.loading-indicator > svg path { | ||
stroke: none; | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
src/components/LoadingIndicator/LoadingIndicator-v2.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import type { StoryObj, Meta } from '@storybook/react'; | ||
import type React from 'react'; | ||
|
||
import { LoadingIndicator } from './LoadingIndicator-v2'; | ||
|
||
export default { | ||
title: 'Components/V2/LoadingIndicator', | ||
component: LoadingIndicator, | ||
parameters: { | ||
layout: 'centered', | ||
badges: ['intro-1.2', 'current-2.0'], | ||
}, | ||
} as Meta<Args>; | ||
|
||
type Args = React.ComponentProps<typeof LoadingIndicator>; | ||
|
||
export const Default: StoryObj<Args> = {}; | ||
|
||
export const ExtraSmall: StoryObj<Args> = { | ||
args: { | ||
size: 'xs', | ||
}, | ||
}; | ||
|
||
export const Small: StoryObj<Args> = { | ||
args: { | ||
size: 'sm', | ||
}, | ||
}; | ||
|
||
export const Medium: StoryObj<Args> = { | ||
args: { | ||
size: 'md', | ||
}, | ||
}; | ||
|
||
export const Large: StoryObj<Args> = { | ||
args: { | ||
size: 'lg', | ||
}, | ||
}; | ||
|
||
export const Invisible: StoryObj<Args> = { | ||
args: { | ||
isVisible: false, | ||
}, | ||
}; | ||
|
||
export const WithAriaLabel: StoryObj<Args> = { | ||
args: { | ||
ariaLabel: 'Loading, Please Wait', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { generateSnapshots } from '@chanzuckerberg/story-utils'; | ||
import * as stories from './LoadingIndicator-v2.stories'; | ||
|
||
describe('<LoadingIndicator /> (v2)', () => { | ||
generateSnapshots(stories); | ||
}); |
124 changes: 124 additions & 0 deletions
124
src/components/LoadingIndicator/LoadingIndicator-v2.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import clsx from 'clsx'; | ||
import React from 'react'; | ||
|
||
import type { Size } from '../../util/variant-types'; | ||
|
||
import styles from './LoadingIndicator-v2.module.css'; | ||
|
||
export type LoadingIndicatorProps = { | ||
// Component API | ||
/** | ||
* CSS class names that can be appended to the component. | ||
*/ | ||
className?: string; | ||
/** | ||
* Aria label of the oval. Default is "loading". Will be overridden if ariaLabel is passed in props | ||
*/ | ||
ariaLabel?: string; | ||
// Design API | ||
/** | ||
* Layout size of the loader. This affects the overall size and associated | ||
* stroke width. | ||
*/ | ||
size?: Extract<Size, 'xs' | 'sm' | 'md' | 'lg'>; | ||
/** | ||
* Whether the oval is visible. Default is true. | ||
*/ | ||
isVisible?: boolean; | ||
}; | ||
|
||
// Pixel sizes corresponding to EDS size units | ||
const loaderSize = { | ||
xs: 16, // --eds-size-1 | ||
sm: 24, // --eds-size-2-and-half | ||
md: 40, // --eds-size-5 | ||
lg: 56, // --eds-size-7 | ||
}; | ||
|
||
// Given a loader size, the stroke widths can change | ||
const loaderStrokeSize = { | ||
xs: 2, | ||
sm: 2, | ||
md: 3, | ||
lg: 4, | ||
}; | ||
|
||
// The viewport changes based on adjustments to handle the stroke width | ||
const loaderViewportSize = { | ||
xs: '-20 -20 42 42', | ||
sm: '-20 -20 42 42', | ||
md: '-20.5 -20.5 43 43', | ||
lg: '-21 -21 44 44', | ||
}; | ||
|
||
/** | ||
* `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 a custom `aria-label` to describe what is loading. | ||
*/ | ||
export const LoadingIndicator = ({ | ||
ariaLabel = 'loading', | ||
className, | ||
size = 'md', | ||
isVisible: visible = true, | ||
...other | ||
}: LoadingIndicatorProps) => { | ||
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 ( | ||
<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> | ||
); | ||
}; | ||
|
||
LoadingIndicator.displayName = 'LoadingIndicator'; |
Oops, something went wrong.