mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 09:36:27 +00:00
improve dialog accessability
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021-2022 The Pybricks Authors
|
||||
|
||||
import { getByLabelText, waitForElementToBeRemoved } from '@testing-library/react';
|
||||
import { getByLabelText, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { testRender } from '../../test';
|
||||
@@ -22,28 +22,19 @@ it('should manage license dialog open/close', async () => {
|
||||
<AboutDialog isOpen={true} onClose={() => undefined} />,
|
||||
);
|
||||
|
||||
expect(
|
||||
dialog.queryByRole('dialog', { name: 'Open Source Software Licenses' }),
|
||||
).toBeNull();
|
||||
|
||||
userEvent.click(dialog.getByText('Software Licenses'));
|
||||
|
||||
expect(
|
||||
dialog.getByText(
|
||||
`${process.env.REACT_APP_NAME} is built on open source software.`,
|
||||
{
|
||||
exact: false,
|
||||
},
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
const licenseDialog = dialog.getByRole('dialog', {
|
||||
name: 'Open Source Software Licenses',
|
||||
});
|
||||
|
||||
expect(licenseDialog).toBeVisible();
|
||||
|
||||
const licenseDialog = document.querySelector(
|
||||
'.pb-license-dialog',
|
||||
) as HTMLDivElement;
|
||||
userEvent.click(getByLabelText(licenseDialog, 'Close'));
|
||||
|
||||
await waitForElementToBeRemoved(() =>
|
||||
dialog.queryByText(
|
||||
`${process.env.REACT_APP_NAME} is built on open source software.`,
|
||||
{
|
||||
exact: false,
|
||||
},
|
||||
),
|
||||
);
|
||||
await waitFor(() => expect(licenseDialog).not.toBeVisible());
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ const AboutDialog: React.VoidFunctionComponent<AboutDialogProps> = ({
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
title={`Pybricks v${firmwareVersion} (${appName} v${appVersion})`}
|
||||
title={i18n.translate(AboutStringId.Title, { appName })}
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
>
|
||||
@@ -45,6 +45,7 @@ const AboutDialog: React.VoidFunctionComponent<AboutDialogProps> = ({
|
||||
<p>
|
||||
<strong>{i18n.translate(AboutStringId.Description)}</strong>
|
||||
</p>
|
||||
<p>{`v${firmwareVersion} (${appName} v${appVersion})`}</p>
|
||||
<p>{pybricksCopyright}</p>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "About {appName}",
|
||||
"description": "MicroPython for LEGO® Powered Up smart hubs.",
|
||||
"licenseButton": { "label": "Software Licenses" },
|
||||
"changelogButton": { "label": "Changelog" },
|
||||
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021 The Pybricks Authors
|
||||
// Copyright (c) 2021-2022 The Pybricks Authors
|
||||
|
||||
// About dialog translation keys.
|
||||
|
||||
export enum AboutStringId {
|
||||
Title = 'about.title',
|
||||
Description = 'about.description',
|
||||
LicenseButtonLabel = 'about.licenseButton.label',
|
||||
ChangelogButtonLabel = 'about.changelogButton.label',
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('new file button', () => {
|
||||
|
||||
userEvent.click(button);
|
||||
|
||||
const dialog = explorer.getByRole('dialog');
|
||||
const dialog = explorer.getByRole('dialog', { name: 'Create a new file' });
|
||||
expect(dialog).toBeVisible();
|
||||
|
||||
userEvent.click(getByLabelText(dialog, 'Close'));
|
||||
|
||||
@@ -108,11 +108,13 @@ describe('about dialog', () => {
|
||||
<SettingsDrawer isOpen={true} onClose={() => undefined} />,
|
||||
);
|
||||
|
||||
expect(settings.queryByRole('dialog')).toBeNull();
|
||||
const appName = process.env.REACT_APP_NAME;
|
||||
|
||||
expect(settings.queryByRole('dialog', { name: `About ${appName}` })).toBeNull();
|
||||
|
||||
settings.getByText('About').click();
|
||||
|
||||
const dialog = settings.getByRole('dialog');
|
||||
const dialog = settings.getByRole('dialog', { name: `About ${appName}` });
|
||||
|
||||
expect(dialog).toBeVisible();
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from '@blueprintjs/core';
|
||||
import { Tooltip2 } from '@blueprintjs/popover2';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useTernaryDarkMode } from 'usehooks-ts';
|
||||
import AboutDialog from '../about/AboutDialog';
|
||||
@@ -98,12 +98,24 @@ const SettingsDrawer: React.VoidFunctionComponent<SettingsProps> = ({
|
||||
|
||||
useHotkeys(hotkeys);
|
||||
|
||||
// HACK: set additional attributes that are not supported via Drawer props
|
||||
const handleDrawerOpening = useCallback<(node: HTMLElement) => void>((n) => {
|
||||
n.setAttribute('role', 'dialog');
|
||||
n.setAttribute('aria-modal', 'true');
|
||||
n.setAttribute('aria-labelledby', 'settings-drawer-dialog-title');
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
isOpen={isOpen}
|
||||
icon="cog"
|
||||
size={DrawerSize.SMALL}
|
||||
title={i18n.translate(SettingsStringId.Title)}
|
||||
title={
|
||||
<span id="settings-drawer-dialog-title">
|
||||
{i18n.translate(SettingsStringId.Title)}
|
||||
</span>
|
||||
}
|
||||
onOpening={handleDrawerOpening}
|
||||
onClose={onClose}
|
||||
// work around https://github.com/palantir/blueprint/issues/5169
|
||||
shouldReturnFocusOnClose={false}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { getByLabelText, waitFor } from '@testing-library/dom';
|
||||
import React from 'react';
|
||||
import { testRender } from '../../test';
|
||||
import Toolbar from './Toolbar';
|
||||
|
||||
describe('settings button', () => {
|
||||
it('should open settings drawer', async () => {
|
||||
const [toolbar] = testRender(<Toolbar />);
|
||||
|
||||
const settingButton = toolbar.getByLabelText('Settings');
|
||||
|
||||
expect(
|
||||
toolbar.queryByRole('dialog', {
|
||||
name: 'Settings & Help',
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
settingButton.click();
|
||||
|
||||
const settingsDrawer = toolbar.getByRole('dialog', {
|
||||
name: 'Settings & Help',
|
||||
});
|
||||
|
||||
expect(settingsDrawer).toBeVisible();
|
||||
|
||||
getByLabelText(settingsDrawer, 'Close').click();
|
||||
|
||||
await waitFor(() => expect(settingsDrawer).not.toBeVisible());
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user