Browse Source

Make various buttons across the UI accessible for screen reader users

There are 2 types of buttons:

1. Buttons with purely iconic labels
2. Buttons that have a label that displays on hover

The tooltip component from rsuite doesn't implement the aria tooltip
pattern,
hence I added labels to the triggering control instead as a workaround
master
Dickson 3 years ago
committed by Jeff
parent
commit
3a35d29c25
  1. 6
      src/components/card/Card.tsx
  2. 16
      src/components/layout/Layout.tsx
  3. 2
      src/components/library/ArtistView.tsx
  4. 32
      src/components/player/PlayerBar.tsx
  5. 2
      src/components/scrollingmenu/ScrollingMenu.tsx
  6. 1
      src/components/search/SearchBar.tsx
  7. 1
      src/components/selectionbar/SelectionButtons.tsx
  8. 48
      src/components/shared/ToolbarButtons.tsx

6
src/components/card/Card.tsx

@ -306,6 +306,7 @@ const Card = ({
<CustomTooltip text={t('Add to queue (later)')} delay={1000}>
<AppendOverlayButton
aria-label={t('Add to queue (later)')}
onClick={() => handlePlayAppend('later')}
size={size <= 160 ? 'xs' : 'sm'}
icon={<Icon icon="plus" />}
@ -314,6 +315,7 @@ const Card = ({
<CustomTooltip text={t('Add to queue (next)')} delay={1000}>
<AppendNextOverlayButton
aria-label={t('Add to queue (next)')}
onClick={() => handlePlayAppend('next')}
size={size <= 160 ? 'xs' : 'sm'}
icon={<Icon icon="plus-circle" />}
@ -323,6 +325,9 @@ const Card = ({
{playClick.type !== 'playlist' && (
<CustomTooltip text={t('Toggle favorite')} delay={1000}>
<FavoriteOverlayButton
aria-label={
rest.details.starred ? t('Remove from favorites') : t('Add to favorites')
}
onClick={() => handleFavorite(rest.details)}
size={size <= 160 ? 'xs' : 'sm'}
icon={<Icon icon={rest.details.starred ? 'heart' : 'heart-o'} />}
@ -332,6 +337,7 @@ const Card = ({
{!rest.isModal && !noModalButton && (
<CustomTooltip text={t('View in modal')} delay={1000}>
<ModalViewOverlayButton
aria-label={t('View in modal')}
size={size <= 160 ? 'xs' : 'sm'}
icon={<Icon icon="external-link" />}
onClick={handleOpenModal}

16
src/components/layout/Layout.tsx

@ -145,10 +145,20 @@ const Layout = ({ footer, children, disableSidebar, font }: any) => {
>
<FlexboxGrid.Item>
<ButtonToolbar>
<StyledButton appearance="subtle" size="sm" onClick={() => history.goBack()}>
<StyledButton
aria-label="back"
appearance="subtle"
size="sm"
onClick={() => history.goBack()}
>
<Icon icon="arrow-left-line" />
</StyledButton>
<StyledButton appearance="subtle" size="sm" onClick={() => history.goForward()}>
<StyledButton
aria-label="next"
appearance="subtle"
size="sm"
onClick={() => history.goForward()}
>
<Icon icon="arrow-right-line" />
</StyledButton>
</ButtonToolbar>
@ -200,7 +210,7 @@ const Layout = ({ footer, children, disableSidebar, font }: any) => {
placement="bottomEnd"
preventOverflow
>
<StyledButton appearance="subtle">
<StyledButton aria-label="settings" appearance="subtle">
<Icon icon="cog" />
</StyledButton>
</Whisper>

2
src/components/library/ArtistView.tsx

@ -738,7 +738,7 @@ const ArtistView = ({ ...rest }: any) => {
}
>
<CustomTooltip text={t('Info')}>
<StyledButton appearance="subtle" size="lg">
<StyledButton aria-label={t('Info')} appearance="subtle" size="lg">
<Icon icon="info-circle" />
</StyledButton>
</CustomTooltip>

32
src/components/player/PlayerBar.tsx

@ -381,6 +381,7 @@ const PlayerBar = () => {
style={{ cursor: 'pointer' }}
/>
<StyledButton
aria-label="show cover art"
size="xs"
onClick={() => {
dispatch(setSidebar({ coverArt: true }));
@ -531,6 +532,8 @@ const PlayerBar = () => {
{/* Seek Backward Button */}
<CustomTooltip text={t('Seek backward')} delay={1000}>
<PlayerControlIcon
aria-label={t('Seek backward')}
role="button"
tabIndex={0}
icon="backward"
size="lg"
@ -546,6 +549,8 @@ const PlayerBar = () => {
{/* Previous Song Button */}
<CustomTooltip text={t('Previous Track')} delay={1000}>
<PlayerControlIcon
aria-label={t('Previous Track')}
role="button"
tabIndex={0}
icon="step-backward"
size="lg"
@ -561,6 +566,9 @@ const PlayerBar = () => {
{/* Play/Pause Button */}
<CustomTooltip text={t('Play/Pause')} delay={1000}>
<PlayerControlIcon
aria-label={t('Play')}
aria-pressed={player.status === 'PLAYING'}
role="button"
tabIndex={0}
icon={player.status === 'PLAYING' ? 'pause-circle' : 'play-circle'}
size="3x"
@ -575,6 +583,8 @@ const PlayerBar = () => {
{/* Next Song Button */}
<CustomTooltip text={t('Next Track')} delay={1000}>
<PlayerControlIcon
aria-label={t('Next Track')}
role="button"
tabIndex={0}
icon="step-forward"
size="lg"
@ -590,6 +600,8 @@ const PlayerBar = () => {
{/* Seek Forward Button */}
<CustomTooltip text={t('Seek forward')} delay={1000}>
<PlayerControlIcon
aria-label={t('Seek forward')}
role="button"
tabIndex={0}
icon="forward"
size="lg"
@ -700,6 +712,9 @@ const PlayerBar = () => {
{/* Favorite Button */}
<CustomTooltip text={t('Favorite')}>
<PlayerControlIcon
aria-label={t('Favorite')}
aria-pressed={!!playQueue[currentEntryList][playQueue.currentIndex]?.starred}
role="button"
tabIndex={0}
icon={
playQueue[currentEntryList][playQueue.currentIndex]?.starred
@ -733,6 +748,17 @@ const PlayerBar = () => {
}
>
<PlayerControlIcon
aria-label={
playQueue.repeat === 'all'
? t('Repeat all')
: playQueue.repeat === 'one'
? t('Repeat one')
: t('Repeat')
}
aria-pressed={
playQueue.repeat === 'all' || playQueue.repeat === 'one' ? 'true' : 'false'
}
role="button"
tabIndex={0}
icon="refresh"
size="lg"
@ -752,6 +778,9 @@ const PlayerBar = () => {
{/* Shuffle Button */}
<CustomTooltip text={t('Shuffle')}>
<PlayerControlIcon
aria-label={t('Shuffle')}
aria-pressed={playQueue.shuffle ? 'true' : 'false'}
role="button"
tabIndex={0}
icon="random"
size="lg"
@ -769,6 +798,9 @@ const PlayerBar = () => {
{/* Display Queue Button */}
<CustomTooltip text={t('Mini')}>
<PlayerControlIcon
aria-label="show play queue"
aria-pressed={playQueue.displayQueue ? 'true' : 'false'}
role="button"
tabIndex={0}
icon="tasks"
size="lg"

2
src/components/scrollingmenu/ScrollingMenu.tsx

@ -60,6 +60,7 @@ const ScrollingMenu = ({
<ButtonToolbar>
<ButtonGroup>
<StyledButton
aria-label="scroll left"
size="sm"
appearance="subtle"
onClick={() => {
@ -75,6 +76,7 @@ const ScrollingMenu = ({
<Icon icon="arrow-left" />
</StyledButton>
<StyledButton
aria-label="scroll right"
size="sm"
appearance="subtle"
onClick={() => {

1
src/components/search/SearchBar.tsx

@ -709,6 +709,7 @@ const SearchBar = () => {
>
<span style={{ display: 'inline-block' }}>
<StyledButton
aria-label="search"
onClick={() => {
setOpenSearch(true);
setTimeout(() => {

1
src/components/selectionbar/SelectionButtons.tsx

@ -11,6 +11,7 @@ const CustomIconButton = ({ tooltipText, icon, handleClick, ...rest }: any) => {
{tooltipText ? (
<CustomTooltip text={tooltipText}>
<IconButton
aria-label={tooltipText}
size="xs"
{...rest}
icon={<Icon icon={icon} {...rest} />}

48
src/components/shared/ToolbarButtons.tsx

@ -7,7 +7,7 @@ import { StyledButton } from './styled';
export const PlayButton = ({ text, ...rest }: any) => {
return (
<CustomTooltip text={text || i18n.t('Play')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={text || i18n.t('Play')} {...rest} tabIndex={0}>
<Icon icon="play" />
</StyledButton>
</CustomTooltip>
@ -17,7 +17,7 @@ export const PlayButton = ({ text, ...rest }: any) => {
export const PlayAppendButton = ({ text, ...rest }: any) => {
return (
<CustomTooltip text={text || i18n.t('Add to queue (later)')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={text || i18n.t('Add to queue (later)')} {...rest} tabIndex={0}>
<Icon icon="plus" />
</StyledButton>
</CustomTooltip>
@ -27,7 +27,7 @@ export const PlayAppendButton = ({ text, ...rest }: any) => {
export const PlayAppendNextButton = ({ text, ...rest }: any) => {
return (
<CustomTooltip text={text || i18n.t('Add to queue (next)')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={text || i18n.t('Add to queue (next)')} {...rest} tabIndex={0}>
<Icon icon="plus-circle" />
</StyledButton>
</CustomTooltip>
@ -37,7 +37,7 @@ export const PlayAppendNextButton = ({ text, ...rest }: any) => {
export const PlayShuffleAppendButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Add shuffled to queue')} onClick={rest.onClick}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Add shuffled to queue')} {...rest} tabIndex={0}>
<Icon icon="plus-square" />
</StyledButton>
</CustomTooltip>
@ -47,7 +47,7 @@ export const PlayShuffleAppendButton = ({ ...rest }) => {
export const SaveButton = ({ text, ...rest }: any) => {
return (
<CustomTooltip text={text || i18n.t('Save')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={text || i18n.t('Save')} {...rest} tabIndex={0}>
<Icon icon="save" />
</StyledButton>
</CustomTooltip>
@ -57,7 +57,7 @@ export const SaveButton = ({ text, ...rest }: any) => {
export const EditButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Edit')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Edit')} {...rest} tabIndex={0}>
<Icon icon="edit2" />
</StyledButton>
</CustomTooltip>
@ -67,7 +67,7 @@ export const EditButton = ({ ...rest }) => {
export const UndoButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Reset')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Reset')} {...rest} tabIndex={0}>
<Icon icon="undo" />
</StyledButton>
</CustomTooltip>
@ -77,7 +77,7 @@ export const UndoButton = ({ ...rest }) => {
export const DeleteButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Delete')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Delete')} {...rest} tabIndex={0}>
<Icon icon="trash" />
</StyledButton>
</CustomTooltip>
@ -87,7 +87,11 @@ export const DeleteButton = ({ ...rest }) => {
export const FavoriteButton = ({ isFavorite, ...rest }: any) => {
return (
<CustomTooltip text={i18n.t('Toggle favorite')}>
<StyledButton tabIndex={0} {...rest}>
<StyledButton
aria-label={isFavorite ? i18n.t('Remove from favorites') : i18n.t('Add to favorites')}
tabIndex={0}
{...rest}
>
<Icon icon={isFavorite ? 'heart' : 'heart-o'} />
</StyledButton>
</CustomTooltip>
@ -101,7 +105,15 @@ export const DownloadButton = ({ downloadSize, ...rest }: any) => {
downloadSize ? i18n.t('Download ({{downloadSize}})', { downloadSize }) : i18n.t('Download')
}
>
<StyledButton {...rest} tabIndex={0}>
<StyledButton
aria-label={
downloadSize
? i18n.t('Download ({{downloadSize}})', { downloadSize })
: i18n.t('Download')
}
{...rest}
tabIndex={0}
>
<Icon icon="download" />
</StyledButton>
</CustomTooltip>
@ -111,7 +123,7 @@ export const DownloadButton = ({ downloadSize, ...rest }: any) => {
export const ShuffleButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Shuffle queue')}>
<StyledButton tabIndex={0} {...rest}>
<StyledButton aria-label={i18n.t('Shuffle queue')} tabIndex={0} {...rest}>
<Icon icon="random" />
</StyledButton>
</CustomTooltip>
@ -121,7 +133,7 @@ export const ShuffleButton = ({ ...rest }) => {
export const ClearQueueButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Clear queue')}>
<StyledButton tabIndex={0} {...rest}>
<StyledButton aria-label={i18n.t('Clear queue')} tabIndex={0} {...rest}>
<Icon icon="trash2" />
</StyledButton>
</CustomTooltip>
@ -158,7 +170,7 @@ export const FilterButton = ({ ...rest }) => {
export const AutoPlaylistButton = ({ noText, ...rest }: any) => {
return (
<CustomTooltip text={i18n.t('Auto playlist')}>
<StyledButton tabIndex={0} {...rest}>
<StyledButton aria-label={i18n.t('Auto playlist')} tabIndex={0} {...rest}>
<Icon icon="plus-square" style={{ marginRight: noText ? '0px' : '10px' }} />
{!noText && i18n.t('Auto playlist')}
</StyledButton>
@ -169,7 +181,7 @@ export const AutoPlaylistButton = ({ noText, ...rest }: any) => {
export const MoveUpButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Move selected up')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Move selected up')} {...rest} tabIndex={0}>
<Icon icon="angle-up" />
</StyledButton>
</CustomTooltip>
@ -179,7 +191,7 @@ export const MoveUpButton = ({ ...rest }) => {
export const MoveDownButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Move selected down')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Move selected down')} {...rest} tabIndex={0}>
<Icon icon="angle-down" />
</StyledButton>
</CustomTooltip>
@ -189,7 +201,7 @@ export const MoveDownButton = ({ ...rest }) => {
export const MoveTopButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Move selected to top')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Move selected to top')} {...rest} tabIndex={0}>
<Icon icon="arrow-up2" />
</StyledButton>
</CustomTooltip>
@ -199,7 +211,7 @@ export const MoveTopButton = ({ ...rest }) => {
export const MoveBottomButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Move selected to bottom')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Move selected to bottom')} {...rest} tabIndex={0}>
<Icon icon="arrow-down2" />
</StyledButton>
</CustomTooltip>
@ -209,7 +221,7 @@ export const MoveBottomButton = ({ ...rest }) => {
export const RemoveSelectedButton = ({ ...rest }) => {
return (
<CustomTooltip text={i18n.t('Remove selected')}>
<StyledButton {...rest} tabIndex={0}>
<StyledButton aria-label={i18n.t('Remove selected')} {...rest} tabIndex={0}>
<Icon icon="close" />
</StyledButton>
</CustomTooltip>

Loading…
Cancel
Save