Skip to content

Commit

Permalink
fix(Dropdown): Hide SVGs from screen readers by adding `aria-hidden="…
Browse files Browse the repository at this point in the history
…true"` to the `svg` elements. (#1515)

Co-authored-by: Nikita Orliak <[email protected]>
  • Loading branch information
nikitaorliak-cengage and Nikita Orliak authored Oct 25, 2024
1 parent 662a951 commit acbec5c
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/a11y-dropdown-hide-svg-from-screen-readers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'react-magma-dom': patch
---

fix(Dropdown): Hide SVGs from screen readers by adding `aria-hidden="true"` to the `svg` elements.
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ exports[`Alert Dismissible should render a dismissible icon button with the warn
id="ignoreSvg"
>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="20"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,7 @@ exports[`ButtonGroup With dropdowns Snapshot: Horizontal & center alignment 1`]
Dropdown 2
</span>
<svg
aria-hidden="true"
class="icon"
data-testid="caretDown"
fill="currentColor"
Expand Down Expand Up @@ -1439,6 +1440,7 @@ exports[`ButtonGroup With dropdowns Snapshot: Horizontal & center alignment 1`]
Dropdown 3
</span>
<svg
aria-hidden="true"
class="icon"
data-testid="caretDown"
fill="currentColor"
Expand Down Expand Up @@ -2126,6 +2128,7 @@ exports[`ButtonGroup With dropdowns Snapshot: Vertical & fill alignment 1`] = `
Dropdown 2
</span>
<svg
aria-hidden="true"
class="icon"
data-testid="caretDown"
fill="currentColor"
Expand Down Expand Up @@ -2188,6 +2191,7 @@ exports[`ButtonGroup With dropdowns Snapshot: Vertical & fill alignment 1`] = `
Dropdown 3
</span>
<svg
aria-hidden="true"
class="icon"
data-testid="caretDown"
fill="currentColor"
Expand Down Expand Up @@ -2953,6 +2957,7 @@ exports[`ButtonGroup With dropdowns Snapshot: noSpace 1`] = `
Dropdown 2
</span>
<svg
aria-hidden="true"
class="icon"
data-testid="caretDown"
fill="currentColor"
Expand Down Expand Up @@ -3015,6 +3020,7 @@ exports[`ButtonGroup With dropdowns Snapshot: noSpace 1`] = `
Dropdown 3
</span>
<svg
aria-hidden="true"
class="icon"
data-testid="caretDown"
fill="currentColor"
Expand Down
41 changes: 37 additions & 4 deletions packages/react-magma-dom/src/components/Dropdown/Dropdown.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,36 @@ describe('Dropdown', () => {
expect(getByText('FAQ')).toBeInTheDocument();
});

it('should render the dropdown component with aria-hidden', () => {
const { container } = render(
<Dropdown>
<DropdownButton>Toggle me</DropdownButton>
<DropdownContent />
</Dropdown>
);

const svg = container.querySelector('svg');

expect(svg).toHaveAttribute('aria-hidden', 'true');
});

it('should render a dropup', () => {
const { getByTestId } = render(
const { getByTestId, container } = render(
<Dropdown dropDirection="up">
<DropdownButton>Toggle me</DropdownButton>
<DropdownContent />
</Dropdown>
);

expect(getByTestId('caretUp')).toBeInTheDocument();

const svg = container.querySelector('svg');

expect(svg).toHaveAttribute('aria-hidden', 'true');
});

it('should render a dropleft', () => {
const { getByTestId } = render(
const { getByTestId, container } = render(
<Dropdown dropDirection="left">
<DropdownButton testId="dropdownButton">Toggle me</DropdownButton>
<DropdownContent />
Expand All @@ -97,10 +114,14 @@ describe('Dropdown', () => {
'padding-left',
magma.spaceScale.spacing03
);

const svg = container.querySelector('svg');

expect(svg).toHaveAttribute('aria-hidden', 'true');
});

it('should render a dropright', () => {
const { getByTestId } = render(
const { getByTestId, container } = render(
<Dropdown dropDirection="right">
<DropdownButton testId="dropdownButton">Toggle me</DropdownButton>
<DropdownContent />
Expand All @@ -112,6 +133,10 @@ describe('Dropdown', () => {
'padding-right',
magma.spaceScale.spacing03
);

const svg = container.querySelector('svg');

expect(svg).toHaveAttribute('aria-hidden', 'true');
});

it('should render a dropdown with a small button', () => {
Expand Down Expand Up @@ -156,6 +181,10 @@ describe('Dropdown', () => {

expect(getByTestId('caretDown')).toBeInTheDocument();
expect(container.querySelectorAll('button').length).toBe(2);

const svg = container.querySelector('svg');

expect(svg).toHaveAttribute('aria-hidden', 'true');
});

it('should render a split dropdown with custom label', () => {
Expand Down Expand Up @@ -210,7 +239,7 @@ describe('Dropdown', () => {
});

it('should render a button with custom icon', () => {
const { queryByTestId, getByText } = render(
const { queryByTestId, getByText, container } = render(
<Dropdown>
<DropdownButton icon={<AsteriskIcon />}>Toggle me</DropdownButton>
<DropdownContent />
Expand All @@ -223,6 +252,10 @@ describe('Dropdown', () => {

expect(queryByTestId('caretUp')).not.toBeInTheDocument();
expect(queryByTestId('caretDown')).not.toBeInTheDocument();

const svg = container.querySelector('svg');

expect(svg).toHaveAttribute('aria-hidden', 'true');
});

it('should render a button with custom icon with specified icon position', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ export const DropdownButton = React.forwardRef<
function getButtonIcon(dropDirection: DropdownDropDirection) {
switch (dropDirection) {
case DropdownDropDirection.left:
return <ArrowLeftIcon testId="caretLeft" />;
return <ArrowLeftIcon testId="caretLeft" aria-hidden="true" />;
case DropdownDropDirection.right:
return <ArrowRightIcon testId="caretRight" />;
return <ArrowRightIcon testId="caretRight" aria-hidden="true" />;
case DropdownDropDirection.up:
return <ArrowDropUpIcon testId="caretUp" />;
return <ArrowDropUpIcon testId="caretUp" aria-hidden="true" />;

default:
return <ArrowDropDownIcon testId="caretDown" />;
return <ArrowDropDownIcon testId="caretDown" aria-hidden="true" />;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,17 @@ export const DropdownSplitButton = React.forwardRef<

const buttonIcon =
resolvedContext.dropDirection === DropdownDropDirection.up ? (
<ArrowDropUpIcon size={theme.iconSizes.medium} testId="caretUp" />
<ArrowDropUpIcon
size={theme.iconSizes.medium}
testId="caretUp"
aria-hidden="true"
/>
) : (
<ArrowDropDownIcon size={theme.iconSizes.medium} testId="caretDown" />
<ArrowDropDownIcon
size={theme.iconSizes.medium}
testId="caretDown"
aria-hidden="true"
/>
);

function handleClick(event: React.SyntheticEvent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ exports[`IconButton Icon Only Button Snapshot should render with large size 1`]
class="emotion-2 emotion-3"
>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="32"
Expand Down Expand Up @@ -449,6 +450,7 @@ exports[`IconButton Icon Only Button Snapshot should render with small size 1`]
class="emotion-2 emotion-3"
>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="20"
Expand Down Expand Up @@ -682,6 +684,7 @@ exports[`IconButton Icon Only Button Snapshot should render with updated color 1
class="emotion-2 emotion-3"
>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down Expand Up @@ -915,6 +918,7 @@ exports[`IconButton Icon Only Button Snapshot should render with updated shape 1
class="emotion-2 emotion-3"
>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down Expand Up @@ -1148,6 +1152,7 @@ exports[`IconButton Icon Only Button Snapshot should render with updated variant
class="emotion-2 emotion-3"
>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down Expand Up @@ -1372,6 +1377,7 @@ exports[`IconButton Icon With Text Button Snapshot should render with large size
Test Text
</span>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="32"
Expand Down Expand Up @@ -1596,6 +1602,7 @@ exports[`IconButton Icon With Text Button Snapshot should render with medium siz
Test Text
</span>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down Expand Up @@ -1820,6 +1827,7 @@ exports[`IconButton Icon With Text Button Snapshot should render with small size
Test Text
</span>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="20"
Expand Down Expand Up @@ -2044,6 +2052,7 @@ exports[`IconButton Icon With Text Button Snapshot should render with updated co
Test Text
</span>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down Expand Up @@ -2268,6 +2277,7 @@ exports[`IconButton Icon With Text Button Snapshot should render with updated sh
Test Text
</span>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down Expand Up @@ -2492,6 +2502,7 @@ exports[`IconButton Icon With Text Button Snapshot should render with updated te
Test Text
</span>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down Expand Up @@ -2716,6 +2727,7 @@ exports[`IconButton Icon With Text Button Snapshot should render with updated va
Test Text
</span>
<svg
aria-hidden="true"
class="icon"
fill="currentColor"
height="24"
Expand Down
9 changes: 5 additions & 4 deletions packages/react-magma-dom/src/components/IconButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
const contextProps = React.useContext(ButtonGroupContext);
const theme = React.useContext(ThemeContext);
const resolvedProps = resolveProps(contextProps, props);
const { color, shape, size, testId, textTransform, variant, ...rest } = resolvedProps;
const { color, shape, size, testId, textTransform, variant, ...rest } =
resolvedProps;

if (instanceOfIconOnly(resolvedProps)) {
icon = resolvedProps.icon;
Expand Down Expand Up @@ -125,6 +126,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
size: icon.props.size
? icon.props.size
: getIconSize(size, theme),
'aria-hidden': 'true',
})
)}
</StyledButton>
Expand All @@ -139,9 +141,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
shape={shape || ButtonShape.fill}
size={size || ButtonSize.medium}
testId={testId}
textTransform={
textTransform || ButtonTextTransform.uppercase
}
textTransform={textTransform || ButtonTextTransform.uppercase}
variant={variant || ButtonVariant.solid}
>
{iconPosition === ButtonIconPosition.right && (
Expand All @@ -153,6 +153,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
React.cloneElement(icon, {
size: icon.props.size || getIconSize(size, theme),
'data-testid': `${testId}-icon`,
'aria-hidden': 'true',
})
)}
{iconPosition !== ButtonIconPosition.right && (
Expand Down

2 comments on commit acbec5c

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.