Merge pull request #6611 from tudi2d/accessibility-changes

Improve accessibility of core components
This commit is contained in:
Ben Lambert
2021-07-28 09:36:30 +02:00
committed by GitHub
18 changed files with 158 additions and 26 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/core-components': patch
'@backstage/plugin-catalog': patch
'@backstage/plugin-catalog-react': patch
---
Improve accessibility of core & catalog components by adjusting them with non-breaking changes.
@@ -69,6 +69,7 @@ export const StatusOK = (props: PropsWithChildren<{}>) => {
<span
className={classNames(classes.status, classes.ok)}
aria-label="Status ok"
aria-hidden="true"
{...props}
/>
);
@@ -80,6 +81,7 @@ export const StatusWarning = (props: PropsWithChildren<{}>) => {
<span
className={classNames(classes.status, classes.warning)}
aria-label="Status warning"
aria-hidden="true"
{...props}
/>
);
@@ -91,6 +93,7 @@ export const StatusError = (props: PropsWithChildren<{}>) => {
<span
className={classNames(classes.status, classes.error)}
aria-label="Status error"
aria-hidden="true"
{...props}
/>
);
@@ -102,6 +105,7 @@ export const StatusPending = (props: PropsWithChildren<{}>) => {
<span
className={classNames(classes.status, classes.pending)}
aria-label="Status pending"
aria-hidden="true"
{...props}
/>
);
@@ -113,6 +117,7 @@ export const StatusRunning = (props: PropsWithChildren<{}>) => {
<span
className={classNames(classes.status, classes.running)}
aria-label="Status running"
aria-hidden="true"
{...props}
/>
);
@@ -124,6 +129,7 @@ export const StatusAborted = (props: PropsWithChildren<{}>) => {
<span
className={classNames(classes.status, classes.aborted)}
aria-label="Status aborted"
aria-hidden="true"
{...props}
/>
);
@@ -491,7 +491,9 @@ export function Table<T extends object = {}>({
icons={tableIcons}
title={
<>
<Typography variant="h5">{title}</Typography>
<Typography variant="h5" component="h3">
{title}
</Typography>
{subtitle && (
<Typography color="textSecondary" variant="body1">
{subtitle}
@@ -20,6 +20,7 @@ import { BackstageTheme } from '@backstage/theme';
interface StyledTabsProps {
value: number | boolean;
selectionFollowsFocus: boolean;
onChange: (event: React.ChangeEvent<{}>, newValue: number) => void;
}
@@ -107,7 +107,11 @@ export const Tabs = ({ tabs }: TabsProps) => {
<div className={classes.root}>
<AppBar ref={wrapper} className={classes.appbar} position="static">
<div>
<StyledTabs value={currentIndex} onChange={handleChange}>
<StyledTabs
value={currentIndex}
onChange={handleChange}
selectionFollowsFocus
>
{navIndex !== 0 && (
<StyledIcon
onClick={navigateToPrevChunk}
@@ -15,13 +15,7 @@
*/
import React from 'react';
import {
ListItem,
ListItemIcon,
Divider,
ListItemText,
makeStyles,
} from '@material-ui/core';
import { Divider, Typography, makeStyles } from '@material-ui/core';
import ArrowIcon from '@material-ui/icons/ArrowForward';
import { BackstageTheme } from '@backstage/theme';
import Box from '@material-ui/core/Box';
@@ -54,16 +48,14 @@ export const BottomLink = ({ link, title, onClick }: BottomLinkProps) => {
<div>
<Divider />
<Link to={link} onClick={onClick} underline="none">
<ListItem className={classes.root}>
<ListItemText>
<Box display="flex" alignItems="center" className={classes.root}>
<Typography>
<Box className={classes.boxTitle} fontWeight="fontWeightBold" m={1}>
{title}
</Box>
</ListItemText>
<ListItemIcon>
<ArrowIcon className={classes.arrow} />
</ListItemIcon>
</ListItem>
</Typography>
<ArrowIcon className={classes.arrow} />
</Box>
</Link>
</div>
);
@@ -73,6 +73,7 @@ export const HeaderTabs = ({
return (
<div className={styles.tabsWrapper}>
<Tabs
selectionFollowsFocus
indicatorColor="primary"
textColor="inherit"
variant="scrollable"
@@ -27,24 +27,26 @@ describe('<ItemCardGrid />', () => {
<Card>Hello!</Card>
</ItemCardGrid>,
);
expect(screen.getByRole('grid')).toBeInTheDocument();
expect(screen.getByText('Hello!')).toBeInTheDocument();
});
it('renders custom styles', async () => {
await renderInTestApp(
<>
<ItemCardGrid>
<ItemCardGrid data-testid="cards-hello">
<Card>Hello!</Card>
</ItemCardGrid>
<ItemCardGrid classes={{ root: 'my-css-class' }}>
<ItemCardGrid
data-testid="cards-goodbye"
classes={{ root: 'my-css-class' }}
>
<Card>Goodbye!</Card>
</ItemCardGrid>
</>,
);
expect(screen.getAllByRole('grid')[0]).toHaveStyle({
expect(screen.getByTestId('cards-hello')).toHaveStyle({
gridTemplateColumns: 'repeat(auto-fill, minmax(22em, 1fr))',
});
expect(screen.getAllByRole('grid')[1]).toHaveClass('my-css-class');
expect(screen.getByTestId('cards-goodbye')).toHaveClass('my-css-class');
});
});
@@ -55,7 +55,7 @@ export const ItemCardGrid = (props: ItemCardGridProps) => {
const { children, ...otherProps } = props;
const classes = useStyles(otherProps);
return (
<div role="grid" className={classes.root} {...otherProps}>
<div className={classes.root} {...otherProps}>
{children}
</div>
);
@@ -204,7 +204,7 @@ export const SidebarItem = forwardRef<any, SidebarItemProps>((props, ref) => {
if (isButtonItem(props)) {
return (
<button {...childProps} ref={ref}>
<button aria-label={text} {...childProps} ref={ref}>
{content}
</button>
);
@@ -216,6 +216,7 @@ export const SidebarItem = forwardRef<any, SidebarItemProps>((props, ref) => {
activeClassName={classes.selected}
to={props.to}
ref={ref}
aria-label={text ? text : props.to}
{...navLinkProps}
>
{content}
@@ -44,7 +44,7 @@ const handleSearch = (input: string) => {
export const SampleSidebar = () => (
<Sidebar>
<SidebarSearchField onSearch={handleSearch} />
<SidebarSearchField onSearch={handleSearch} to="/search" />
<SidebarDivider />
<SidebarItem icon={HomeOutlinedIcon} to="#" text="Home" />
<SidebarItem icon={HomeOutlinedIcon} to="#" text="Plugins" />
+1
View File
@@ -7,6 +7,7 @@ module.exports = {
'../../../plugins/**/src/**/*.stories.tsx',
],
addons: [
'@storybook/addon-a11y',
'@storybook/addon-actions',
'@storybook/addon-links',
'@storybook/addon-storysource',
+1
View File
@@ -19,6 +19,7 @@
"react-dom": "^16.12.0"
},
"devDependencies": {
"@storybook/addon-a11y": "^6.3.4",
"@storybook/addon-actions": "^6.1.11",
"@storybook/addon-links": "^6.1.11",
"@storybook/addon-storysource": "^6.1.11",
@@ -76,6 +76,7 @@ export const EntityLifecyclePicker = () => {
<Box pb={1} pt={1}>
<Typography variant="button">Lifecycle</Typography>
<Autocomplete<string>
aria-label="Lifecycle"
multiple
options={availableLifecycles}
value={selectedLifecycles}
@@ -81,6 +81,7 @@ export const EntityOwnerPicker = () => {
<Typography variant="button">Owner</Typography>
<Autocomplete<string>
multiple
aria-label="Owner"
options={availableOwners}
value={selectedOwners}
onChange={(_: object, value: string[]) => setSelectedOwners(value)}
@@ -73,6 +73,7 @@ export const EntityTagPicker = () => {
<Typography variant="button">Tags</Typography>
<Autocomplete<string>
multiple
aria-label="Tags"
options={availableTags}
value={selectedTags}
onChange={(_: object, value: string[]) => setSelectedTags(value)}
@@ -80,7 +80,7 @@ export const CatalogTable = ({ columns, actions }: CatalogTableProps) => {
({ entity }) => {
const url = getEntityMetadataViewUrl(entity);
return {
icon: () => <OpenInNew fontSize="small" />,
icon: () => <OpenInNew aria-label="View" fontSize="small" />,
tooltip: 'View',
disabled: !url,
onClick: () => {
@@ -92,7 +92,7 @@ export const CatalogTable = ({ columns, actions }: CatalogTableProps) => {
({ entity }) => {
const url = getEntityMetadataEditUrl(entity);
return {
icon: () => <Edit fontSize="small" />,
icon: () => <Edit aria-label="Edit" fontSize="small" />,
tooltip: 'Edit',
disabled: !url,
onClick: () => {
+111
View File
@@ -4343,6 +4343,28 @@
resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-10.0.0.tgz#fa076d98d2e7e6c53dd3d86a696307a7010bd056"
integrity sha512-VYOdo8P7lIScAkl02nB9KpUAuOYMManryBIBuKJkAw5D3aVtLobfmdIKvdV6MqEmGMEQPbn7w/UpnjJYhUH+IA==
"@storybook/addon-a11y@^6.3.4":
version "6.3.4"
resolved "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.3.4.tgz#056c3c0e3b2d66d8aa2f02dc84374c948d07df91"
integrity sha512-ABG1dvwDdlNVvW+P+oRtDdiyw40ddc+maSwKbwxTiw9Ibq7TrasWE9ub0r7yNoFLXEZa3pBjPrGKdh+WIYToSQ==
dependencies:
"@storybook/addons" "6.3.4"
"@storybook/api" "6.3.4"
"@storybook/channels" "6.3.4"
"@storybook/client-api" "6.3.4"
"@storybook/client-logger" "6.3.4"
"@storybook/components" "6.3.4"
"@storybook/core-events" "6.3.4"
"@storybook/theming" "6.3.4"
axe-core "^4.2.0"
core-js "^3.8.2"
global "^4.4.0"
lodash "^4.17.20"
react-sizeme "^3.0.1"
regenerator-runtime "^0.13.7"
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/addon-actions@^6.1.11":
version "6.3.0"
resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.3.0.tgz#e5a24c69d70da9aa98560f19d10c06a50495ca2e"
@@ -4593,6 +4615,19 @@
qs "^6.10.0"
telejson "^5.3.2"
"@storybook/channel-postmessage@6.3.4":
version "6.3.4"
resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.3.4.tgz#1a0000aefc9494d5585a1d2c7bdb75f540965f70"
integrity sha512-UIHNrMD9ZaT249nkKXibqRjKEoqfeFJk5HKW2W17/Z/imVcKG9THBnRJ7cb+r7LqS8Yoh+Q87ycRqcPVLRJ/Xw==
dependencies:
"@storybook/channels" "6.3.4"
"@storybook/client-logger" "6.3.4"
"@storybook/core-events" "6.3.4"
core-js "^3.8.2"
global "^4.4.0"
qs "^6.10.0"
telejson "^5.3.2"
"@storybook/channels@6.1.15":
version "6.1.15"
resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.1.15.tgz#22bb06a671a5ae09d2537bcf63aaf90d7f6b9f6b"
@@ -4677,6 +4712,30 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/client-api@6.3.4":
version "6.3.4"
resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.3.4.tgz#7dd6dda0126012ed37fa885642973cc75366b5a8"
integrity sha512-lOrfz8ic3+nHZzqIdNH2I7Q3Wp0kS/Ic0PD/3QKvI2f6iVIapIjjWW1xAuor80Dl7rMhOn8zxgXta+7G7Pn2yQ==
dependencies:
"@storybook/addons" "6.3.4"
"@storybook/channel-postmessage" "6.3.4"
"@storybook/channels" "6.3.4"
"@storybook/client-logger" "6.3.4"
"@storybook/core-events" "6.3.4"
"@storybook/csf" "0.0.1"
"@types/qs" "^6.9.5"
"@types/webpack-env" "^1.16.0"
core-js "^3.8.2"
global "^4.4.0"
lodash "^4.17.20"
memoizerific "^1.11.3"
qs "^6.10.0"
regenerator-runtime "^0.13.7"
stable "^0.1.8"
store2 "^2.12.0"
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/client-logger@6.1.15":
version "6.1.15"
resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.1.15.tgz#b558d6ecbee82c038d684717d8c598eaa4a9324d"
@@ -4795,6 +4854,36 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/components@6.3.4":
version "6.3.4"
resolved "https://registry.npmjs.org/@storybook/components/-/components-6.3.4.tgz#c872ec267edf315eaada505be8595c70eb6db09b"
integrity sha512-0hBKTkkQbW+daaA6nRedkviPr2bEzy1kwq0H5eaLKI1zYeXN3U5Z8fVhO137PPqH5LmLietrmTPkqiljUBk9ug==
dependencies:
"@popperjs/core" "^2.6.0"
"@storybook/client-logger" "6.3.4"
"@storybook/csf" "0.0.1"
"@storybook/theming" "6.3.4"
"@types/color-convert" "^2.0.0"
"@types/overlayscrollbars" "^1.12.0"
"@types/react-syntax-highlighter" "11.0.5"
color-convert "^2.0.1"
core-js "^3.8.2"
fast-deep-equal "^3.1.3"
global "^4.4.0"
lodash "^4.17.20"
markdown-to-jsx "^7.1.3"
memoizerific "^1.11.3"
overlayscrollbars "^1.13.1"
polished "^4.0.5"
prop-types "^15.7.2"
react-colorful "^5.1.2"
react-popper-tooltip "^3.1.1"
react-syntax-highlighter "^13.5.3"
react-textarea-autosize "^8.3.0"
regenerator-runtime "^0.13.7"
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
"@storybook/core-events@6.1.15":
version "6.1.15"
resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.1.15.tgz#f66e30cbed8afdb8df2254d2aa47fe139e641c60"
@@ -7972,6 +8061,11 @@ axe-core@^4.0.2:
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.1.3.tgz#64a4c85509e0991f5168340edc4bedd1ceea6966"
integrity sha512-vwPpH4Aj4122EW38mxO/fxhGKtwWTMLDIJfZ1He0Edbtjcfna/R3YB67yVhezUMzqc3Jr3+Ii50KRntlENL4xQ==
axe-core@^4.2.0:
version "4.3.1"
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.3.1.tgz#0c6a076e4a1c3e0544ba6a9479158f9be7a7928e"
integrity sha512-3WVgVPs/7OnKU3s+lqMtkv3wQlg3WxK1YifmpJSDO0E1aPBrZWlrrTO6cxRqCXLuX2aYgCljqXIQd0VnRidV0g==
axios@^0.20.0:
version "0.20.0"
resolved "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd"
@@ -11759,6 +11853,13 @@ element-resize-detector@^1.2.1:
dependencies:
batch-processor "1.0.0"
element-resize-detector@^1.2.2:
version "1.2.3"
resolved "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.3.tgz#5078d9b99398fe4c589f8c8df94ff99e5d413ff3"
integrity sha512-+dhNzUgLpq9ol5tyhoG7YLoXL3ssjfFW+0gpszXPwRU6NjGr1fVHMEAF8fVzIiRJq57Nre0RFeIjJwI8Nh2NmQ==
dependencies:
batch-processor "1.0.0"
elliptic@^6.0.0:
version "6.5.4"
resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
@@ -21826,6 +21927,16 @@ react-sizeme@^2.6.7:
shallowequal "^1.1.0"
throttle-debounce "^2.1.0"
react-sizeme@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.1.tgz#4d12f4244e0e6a0fb97253e7af0314dc7c83a5a0"
integrity sha512-9Hf1NLgSbny1bha77l9HwvwwxQUJxFUqi44Ih+y3evA+PezBpGdCGlnvye6avss2cIgs9PgdYgMnfuzJWn/RUw==
dependencies:
element-resize-detector "^1.2.2"
invariant "^2.2.4"
shallowequal "^1.1.0"
throttle-debounce "^3.0.1"
react-smooth@^1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/react-smooth/-/react-smooth-1.0.5.tgz#94ae161d7951cdd893ccb7099d031d342cb762ad"