-
Notifications
You must be signed in to change notification settings - Fork 535
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Convey Spinner to assistive technologies (#4140)
* updates Spinner to accept screen reader text * restricts props, updates prop docs deprecates aria-label prop * adds stories and tests * adds changeset * updates prop docs * fixes visual regressions * improve Storybook examples for announcing compoleted loading * uses live regions, adapts SelectPanel.Loading * attempt to resolve circular dependency * updates Spinner example stories to use live-region-element via Status component * updates Spinner example stories to use live-region-element via Status component * removes live region * updates Storybook imports
- Loading branch information
Showing
11 changed files
with
2,834 additions
and
1,744 deletions.
There are no files selected for viewing
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,7 @@ | ||
--- | ||
'@primer/react': minor | ||
--- | ||
|
||
Adds a prop, `srText`, to the Spinner component to convey a loading message to assistive technologies such as screen readers. | ||
|
||
<!-- Changed components: Spinner --> |
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
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,96 @@ | ||
import React from 'react' | ||
import type {Meta} from '@storybook/react' | ||
import Spinner from './Spinner' | ||
import {Box, Button} from '..' | ||
import {VisuallyHidden} from '../internal/components/VisuallyHidden' | ||
import {Status} from '../internal/components/Status' | ||
|
||
export default { | ||
title: 'Components/Spinner/Examples', | ||
component: Spinner, | ||
} as Meta<typeof Spinner> | ||
|
||
type LoadingState = 'initial' | 'loading' | 'done' | ||
|
||
async function wait(ms: number) { | ||
return new Promise(resolve => setTimeout(resolve, ms)) | ||
} | ||
|
||
// There should be an announcement when loading is completed or if there was an error loading | ||
export const FullLifecycle = () => { | ||
const [isLoading, setIsLoading] = React.useState(false) | ||
const [loadedContent, setLoadedContent] = React.useState('') | ||
let state: LoadingState = 'initial' | ||
|
||
if (isLoading) { | ||
state = 'loading' | ||
} else if (loadedContent) { | ||
state = 'done' | ||
} | ||
|
||
const initiateLoading = async () => { | ||
if (state === 'done') { | ||
return | ||
} | ||
|
||
setIsLoading(true) | ||
await wait(1000) | ||
setLoadedContent('Some content that had to be loaded.') | ||
setIsLoading(false) | ||
} | ||
|
||
return ( | ||
<> | ||
<Button onClick={initiateLoading} sx={{mb: '1em'}}> | ||
Load content | ||
</Button> | ||
{state === 'loading' && <Spinner />} | ||
<p>{loadedContent}</p> | ||
<VisuallyHidden> | ||
<Status>{state === 'done' && 'Content finished loading'}</Status> | ||
</VisuallyHidden> | ||
</> | ||
) | ||
} | ||
|
||
// We should avoid duplicate loading announcements | ||
export const FullLifecycleVisibleLoadingText = () => { | ||
const [isLoading, setIsLoading] = React.useState(false) | ||
const [loadedContent, setLoadedContent] = React.useState('') | ||
let state: LoadingState = 'initial' | ||
|
||
if (isLoading) { | ||
state = 'loading' | ||
} else if (loadedContent) { | ||
state = 'done' | ||
} | ||
|
||
const initiateLoading = async () => { | ||
if (state === 'done') { | ||
return | ||
} | ||
|
||
setIsLoading(true) | ||
await wait(1000) | ||
setLoadedContent('Some content that had to be loaded.') | ||
setIsLoading(false) | ||
} | ||
|
||
return ( | ||
<Box sx={{display: 'flex', alignItems: 'flex-start', flexDirection: 'column', gap: '0.5em'}}> | ||
<Button onClick={initiateLoading} sx={{mb: '1em'}}> | ||
Load content | ||
</Button> | ||
{state !== 'done' && ( | ||
<Box sx={{alignItems: 'center', display: 'flex', gap: '0.25rem'}}> | ||
{state === 'loading' && <Spinner size="small" srText={null} />} | ||
<Status>{state === 'loading' ? 'Content is loading...' : ''}</Status> | ||
</Box> | ||
)} | ||
<p>{loadedContent}</p> | ||
<VisuallyHidden> | ||
<Status>{state === 'done' && 'Content finished loading'}</Status> | ||
</VisuallyHidden> | ||
</Box> | ||
) | ||
} |
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
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
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
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
Oops, something went wrong.