Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

[terra-tabs] Fixed A11y issues #1833

Merged
merged 6 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/terra-tabs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Changed
* Removed additional screen reader phrase and fixed delete tab hint.
saket2403 marked this conversation as resolved.
Show resolved Hide resolved

## 7.10.0 - (October 11, 2023)

* Changed
Expand Down
13 changes: 9 additions & 4 deletions packages/terra-tabs/src/common-tabs/_Tab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,9 @@ const Tab = ({
attributes.style = { zIndex };

const onFocusResponse = intl.formatMessage({ id: 'Terra.tabs.focus' });
const responseId = `terra-tab-pane-response=${uuidv4()}`;
const responseId = `terra-tab-pane-response-${uuidv4()}`;
const deleteResponseId = `terra-tab-delete-pane-response-${uuidv4()}`;
const ariaDescribedBy = isClosable ? [responseId, deleteResponseId] : responseId;

if (isDraggable) {
return (
Expand All @@ -248,15 +250,16 @@ const Tab = ({
role="tab"
className={variant === 'framework' ? paneClassNames : tabClassNames}
title={label}
aria-label={isClosable ? `${label}. ${tabDeleteLabel}` : label}
aria-describedby={responseId}
aria-label={label}
aria-describedby={ariaDescribedBy}
tabIndex={isSelected ? 0 : -1}
data-terra-tabs-show-focus-styles
data-terra-tab-draggable
>
<div className={variant === 'framework' ? cy('inner', 'draggable-inner') : cx('inner')}>
<IconKnurling />
<VisuallyHiddenText aria-hidden id={responseId} text={onFocusResponse} />
<VisuallyHiddenText aria-hidden id={deleteResponseId} text={tabDeleteLabel} />
<div className={cy('draggable-icon')}>{customDisplay || icon}</div>
{(!customDisplay && !isIconOnly) && <span className={variant === 'framework' ? cy('label') : cx('label')}>{label}</span>}
</div>
Expand All @@ -283,11 +286,13 @@ const Tab = ({
aria-disabled={isDisabled}
className={variant === 'framework' ? paneClassNames : tabClassNames}
title={label}
aria-label={isClosable ? `${label}. ${tabDeleteLabel}` : label}
aria-label={label}
aria-describedby={isClosable ? deleteResponseId : null}
tabIndex={isSelected ? 0 : -1}
data-terra-tabs-show-focus-styles
>
<div className={variant === 'framework' ? cy('inner') : cx('inner')}>
<VisuallyHiddenText aria-hidden id={deleteResponseId} text={tabDeleteLabel} />
{customDisplay || icon}
{(!customDisplay && !isIconOnly) && <span className={variant === 'framework' ? cy('label') : cx('label')}>{label}</span>}
</div>
Expand Down
16 changes: 16 additions & 0 deletions packages/terra-tabs/tests/jest/Tab.test.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { shallowWithIntl } from 'terra-enzyme-intl';
import { v4 as uuidv4 } from 'uuid';
import Tab from '../../src/common-tabs/_Tab';

let mockSpyUuid;

beforeAll(() => {
mockSpyUuid = jest.spyOn(uuidv4, 'v4').mockReturnValue('00000000-0000-0000-0000-000000000000');
});

afterAll(() => {
mockSpyUuid.mockRestore();
});

describe('Tab', () => {
it('should render a common tab as disabled when indicated', () => {
const wrapper = shallowWithIntl(<Tab label="Label" isDisabled variant="framework" />).dive();
Expand All @@ -14,6 +25,11 @@ describe('Tab', () => {
expect(wrapper).toMatchSnapshot();
});

it('should render a closable tab', () => {
const wrapper = shallowWithIntl(<Tab label="Default" className="customClass" variant="framework" isClosable />).dive();
expect(wrapper).toMatchSnapshot();
});

it('correctly applies the theme context className', () => {
jest.spyOn(React, 'useContext')
.mockReturnValue({
Expand Down
11 changes: 11 additions & 0 deletions packages/terra-tabs/tests/jest/TabPane.test.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { shallowWithIntl } from 'terra-enzyme-intl';
import { v4 as uuidv4 } from 'uuid';
import Pane from '../../src/TabPane';

let mockSpyUuid;

beforeAll(() => {
mockSpyUuid = jest.spyOn(uuidv4, 'v4').mockReturnValue('00000000-0000-0000-0000-000000000000');
});

afterAll(() => {
mockSpyUuid.mockRestore();
});

describe('TabPane', () => {
it('should render a default component with label', () => {
const wrapper = shallowWithIntl(<Pane label="Default" />).dive().dive();
Expand Down
67 changes: 67 additions & 0 deletions packages/terra-tabs/tests/jest/__snapshots__/Tab.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

exports[`Tab correctly applies the theme context className 1`] = `
<div
aria-describedby={null}
aria-disabled={false}
aria-label="Default"
aria-selected={false}
Expand All @@ -24,6 +25,11 @@ exports[`Tab correctly applies the theme context className 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<span
className="label"
>
Expand All @@ -33,8 +39,58 @@ exports[`Tab correctly applies the theme context className 1`] = `
</div>
`;

exports[`Tab should render a closable tab 1`] = `
<div
aria-describedby="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
aria-disabled={false}
aria-label="Default"
aria-selected={false}
className="tab is-text-only"
data-focus-styles-enabled={true}
data-terra-tabs-show-focus-styles={true}
onBlur={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
role="tab"
style={
Object {
"zIndex": undefined,
}
}
tabIndex={-1}
title="Default"
>
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<span
className="label"
>
Default
</span>
</div>
<div
className="tabs-remove-button"
onClick={[Function]}
>
<IconClose
data-name="Layer 1"
viewBox="0 0 48 48"
xmlns="http://www.w3.org/2000/svg"
/>
</div>
</div>
`;

exports[`Tab should render a common tab as disabled when indicated 1`] = `
<div
aria-describedby={null}
aria-disabled={true}
aria-label="Label"
aria-selected={false}
Expand All @@ -57,6 +113,11 @@ exports[`Tab should render a common tab as disabled when indicated 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<span
className="label"
>
Expand All @@ -68,6 +129,7 @@ exports[`Tab should render a common tab as disabled when indicated 1`] = `

exports[`Tab should render a common tab with custom props 1`] = `
<div
aria-describedby={null}
aria-disabled={false}
aria-label="Default"
aria-selected={false}
Expand All @@ -90,6 +152,11 @@ exports[`Tab should render a common tab with custom props 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<span
className="label"
>
Expand Down
30 changes: 30 additions & 0 deletions packages/terra-tabs/tests/jest/__snapshots__/TabPane.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

exports[`TabPane correctly applies the theme context className 1`] = `
<div
aria-describedby={null}
aria-disabled={false}
aria-label="Default"
aria-selected={false}
Expand All @@ -24,6 +25,11 @@ exports[`TabPane correctly applies the theme context className 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<span
className="label"
>
Expand All @@ -35,6 +41,7 @@ exports[`TabPane correctly applies the theme context className 1`] = `

exports[`TabPane should render a default component with label 1`] = `
<div
aria-describedby={null}
aria-disabled={false}
aria-label="Default"
aria-selected={false}
Expand All @@ -57,6 +64,11 @@ exports[`TabPane should render a default component with label 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<span
className="label"
>
Expand All @@ -68,6 +80,7 @@ exports[`TabPane should render a default component with label 1`] = `

exports[`TabPane should render with a custom display when provided 1`] = `
<div
aria-describedby={null}
aria-disabled={false}
aria-label="Label"
aria-selected={false}
Expand All @@ -90,6 +103,11 @@ exports[`TabPane should render with a custom display when provided 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<div>
Custom Display
</div>
Expand All @@ -99,6 +117,7 @@ exports[`TabPane should render with a custom display when provided 1`] = `

exports[`TabPane should render with icon and label 1`] = `
<div
aria-describedby={null}
aria-disabled={false}
aria-label="Label"
aria-selected={false}
Expand All @@ -121,6 +140,11 @@ exports[`TabPane should render with icon and label 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<div>
Fake icon
</div>
Expand All @@ -135,6 +159,7 @@ exports[`TabPane should render with icon and label 1`] = `

exports[`TabPane should render with icon only when indicated 1`] = `
<div
aria-describedby={null}
aria-disabled={false}
aria-label="Label"
aria-selected={false}
Expand All @@ -157,6 +182,11 @@ exports[`TabPane should render with icon only when indicated 1`] = `
<div
className="inner"
>
<VisuallyHiddenText
aria-hidden={true}
id="terra-tab-delete-pane-response-00000000-0000-0000-0000-000000000000"
text="Terra.tabs.hint.removable"
/>
<div>
Fake icon
</div>
Expand Down
Loading
Loading