Skip to content

Commit

Permalink
Fix ApplicationShell header selectors a11y issues (#2665)
Browse files Browse the repository at this point in the history
* fix(applicaiton-shell): fix a11y labels for project and locale selectors

* refactor(applicaiton-shell): updated labels implementation

* docs: changeset

* chore(applicaiton-shell): added new i18n keys

Co-authored-by: Nicola Molinari <nicola.molinari@commercetools.com>
  • Loading branch information
CarlosCortizasCT and emmenko authored Jun 28, 2022
1 parent c56498c commit a98f9fb
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 27 deletions.
5 changes: 5 additions & 0 deletions .changeset/red-trainers-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@commercetools-frontend/application-shell": patch
---

Fix `ApplicationShell` header selectors a11y issues
1 change: 1 addition & 0 deletions packages/application-shell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@commercetools-frontend/sdk": "21.6.0",
"@commercetools-frontend/sentry": "21.6.0",
"@commercetools-frontend/url-utils": "21.3.4",
"@commercetools-uikit/accessible-hidden": "^15.0.0",
"@commercetools-uikit/avatar": "^15.0.0",
"@commercetools-uikit/card": "^15.0.0",
"@commercetools-uikit/design-system": "^15.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,8 @@ describe('when user does not have permissions to access the project', () => {
});
describe('when switching project', () => {
it('should render app for new project', async () => {
renderApp(<label id="project-switcher">{'Project switcher'}</label>);
await screen.findByText('Project switcher');
const input = await screen.findByLabelText('Project switcher');
renderApp();
const input = await screen.findByLabelText('Projects menu');

fireEvent.focus(input);
fireEvent.keyDown(input, { key: 'ArrowDown' });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import type { SingleValueProps, ValueContainerProps } from 'react-select';
import { useCallback } from 'react';
import { css } from '@emotion/react';
import { FormattedMessage } from 'react-intl';
import AccessibleHidden from '@commercetools-uikit/accessible-hidden';
import SelectInput from '@commercetools-uikit/select-input';
import { WorldIcon } from '@commercetools-uikit/icons';
import { customProperties } from '@commercetools-uikit/design-system';
import messages from './messages';

type CustomSingleValueProps = SingleValueProps & {
localeCount: number;
Expand All @@ -14,6 +17,8 @@ type Props = {
availableLocales: string[];
};

const LOCALE_SWITCHER_LABEL_ID = 'locale-switcher-label';

export const SingleValue = (props: CustomSingleValueProps) => (
<div
css={css`
Expand Down Expand Up @@ -75,10 +80,15 @@ const LocaleSwitcher = (props: Props) => {
`}
data-track-component="LocaleSwitch"
>
<AccessibleHidden>
<span id={LOCALE_SWITCHER_LABEL_ID}>
<FormattedMessage {...messages.localesLabel} />
</span>
</AccessibleHidden>
<SelectInput
value={props.projectDataLocale}
name="locale-switcher"
aria-labelledby="locale-switcher"
aria-labelledby={LOCALE_SWITCHER_LABEL_ID}
onChange={handleSelection}
options={props.availableLocales.map((locale) => ({
label: locale,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineMessages } from 'react-intl';

export default defineMessages({
localesLabel: {
id: 'LocaleSwitcher.localesLabel',
description: 'The label for project dropdown switcher',
defaultMessage: 'Locales menu',
},
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { defineMessages } from 'react-intl';

export default defineMessages({
projects: {
id: 'ProjectSwitcher.projects',
projectsLabel: {
id: 'ProjectSwitcher.projectsLabel',
description: 'The label for project dropdown switcher',
defaultMessage: 'Projects',
defaultMessage: 'Projects menu',
},
searchPlaceholder: {
id: 'ProjectSwitcher.searchPlaceholder',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,10 @@ const render = () => {
getIsExpired: (key) => key === 'key-3',
}),
];
return renderApp(
<>
<label id="project-switcher">{'Project switcher'}</label>
<ProjectSwitcher projectKey="key-0" />
</>,
{
disableRoutePermissionCheck: true,
mocks: mockedRequest,
}
);
return renderApp(<ProjectSwitcher projectKey="key-0" />, {
disableRoutePermissionCheck: true,
mocks: mockedRequest,
});
};

describe('rendering', () => {
Expand All @@ -32,8 +26,7 @@ describe('rendering', () => {

it('should search and select a project', async () => {
render();
await screen.findByLabelText('Project switcher');
const input = screen.getByLabelText('Project switcher');
const input = await screen.findByLabelText('Projects menu');
fireEvent.focus(input);
fireEvent.change(input, { target: { value: 'key-1' } });
fireEvent.keyDown(input, { key: 'Enter', keyCode: 13, which: 13 });
Expand All @@ -44,8 +37,7 @@ describe('rendering', () => {
});
it('should see no results message when search does not match any project', async () => {
render();
await screen.findByLabelText('Project switcher');
const input = screen.getByLabelText('Project switcher');
const input = await screen.findByLabelText('Projects menu');
fireEvent.focus(input);
fireEvent.change(input, { target: { value: 'not existing' } });

Expand All @@ -55,8 +47,7 @@ describe('rendering', () => {
});
it('should prevent clicking on a suspended project', async () => {
render();
await screen.findByLabelText('Project switcher');
const input = screen.getByLabelText('Project switcher');
const input = await screen.findByLabelText('Projects menu');
fireEvent.focus(input);
fireEvent.keyDown(input, { key: 'ArrowDown' });
fireEvent.click(screen.getByText(/Suspended/i));
Expand All @@ -67,8 +58,7 @@ describe('rendering', () => {
});
it('should prevent clicking on an expired project', async () => {
render();
await screen.findByLabelText('Project switcher');
const input = screen.getByLabelText('Project switcher');
const input = await screen.findByLabelText('Projects menu');
fireEvent.focus(input);
fireEvent.keyDown(input, { key: 'ArrowDown' });
fireEvent.click(screen.getByText(/Expired/i));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { FormattedMessage, useIntl } from 'react-intl';
import { css } from '@emotion/react';
import { GRAPHQL_TARGETS } from '@commercetools-frontend/constants';
import { reportErrorToSentry } from '@commercetools-frontend/sentry';
import AccessibleHidden from '@commercetools-uikit/accessible-hidden';
import SelectInput from '@commercetools-uikit/select-input';
import { ErrorIcon } from '@commercetools-uikit/icons';
import { customProperties } from '@commercetools-uikit/design-system';
Expand All @@ -32,6 +33,8 @@ type CustomValueContainerProps = ValueContainerProps & {
projectCount: number;
};

const PROJECT_SWITCHER_LABEL_ID = 'project-switcher-label';

export const ProjectSwitcherValueContainer = ({
projectCount,
...restProps
Expand Down Expand Up @@ -168,10 +171,15 @@ const ProjectSwitcher = (props: Props) => {
data-track-component="ProjectSwitch"
data-track-event="click"
>
<AccessibleHidden>
<span id={PROJECT_SWITCHER_LABEL_ID}>
<FormattedMessage {...messages.projectsLabel} />
</span>
</AccessibleHidden>
<SelectInput
value={props.projectKey || ''}
name="project-switcher"
aria-labelledby="project-switcher"
aria-labelledby={PROJECT_SWITCHER_LABEL_ID}
onChange={(event) => {
const selectedProjectKey = event.target.value as string;
if (selectedProjectKey !== props.projectKey) {
Expand Down
3 changes: 2 additions & 1 deletion packages/i18n/data/core.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"ErrorApologizer.title": "Sorry! An unexpected error occured.",
"FailedAuthentication.paragraph1": "Please try again and contact your system administrator if you have any further questions.",
"FailedAuthentication.title": "We are unable to authorize you to use the Merchant Center.",
"LocaleSwitcher.localesLabel": "Locales menu",
"NavBar.MCSupport.title": "Support",
"Notification.hideNotification": "Hide notification",
"PageNotFound.paragraph1": "The item you are looking for may have been deleted, does not exist, or the URL was entered incorrectly. Check the URL and try again. Please contact your system administrator or the commercetools <a>Help Desk</a> if you have any further questions.",
Expand All @@ -71,7 +72,7 @@
"ProjectSuspended.temporaryMaintenanceSuspensionMessage": "Your Project is temporarily suspended due to maintenance.",
"ProjectSwitcher.expired": "Expired",
"ProjectSwitcher.noResults": "Sorry, but there are no projects that match your search.",
"ProjectSwitcher.projects": "Projects",
"ProjectSwitcher.projectsLabel": "Projects menu",
"ProjectSwitcher.searchPlaceholder": "Search for a project",
"ProjectSwitcher.suspended": "Suspended",
"QuickAccess.inputPlaceholder": "Go to...",
Expand Down
15 changes: 15 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2767,6 +2767,7 @@ __metadata:
"@commercetools-frontend/sdk": 21.6.0
"@commercetools-frontend/sentry": 21.6.0
"@commercetools-frontend/url-utils": 21.3.4
"@commercetools-uikit/accessible-hidden": ^15.0.0
"@commercetools-uikit/avatar": ^15.0.0
"@commercetools-uikit/card": ^15.0.0
"@commercetools-uikit/design-system": ^15.0.0
Expand Down Expand Up @@ -3422,6 +3423,20 @@ __metadata:
languageName: node
linkType: hard

"@commercetools-uikit/accessible-hidden@npm:^15.0.0":
version: 15.0.0
resolution: "@commercetools-uikit/accessible-hidden@npm:15.0.0"
dependencies:
"@babel/runtime": ^7.17.2
"@babel/runtime-corejs3": ^7.17.2
"@emotion/react": ^11.4.0
prop-types: 15.8.1
peerDependencies:
react: 17.x
checksum: 5b5610af0da5c5e70fafa1be190eaad7006793e90b3adb8ab6835254c2f504609042701b1ea9568210f8ae8d344522d70f5b82d6090af3d877c097546f4acc71
languageName: node
linkType: hard

"@commercetools-uikit/avatar@npm:^15.0.0":
version: 15.0.0
resolution: "@commercetools-uikit/avatar@npm:15.0.0"
Expand Down

1 comment on commit a98f9fb

@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.

Deploy preview for merchant-center-application-kit ready!

✅ Preview
https://merchant-center-application-2id4ogqdg-commercetools.vercel.app

Built with commit a98f9fb.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.