Merge pull request #6611 from tudi2d/accessibility-changes
Improve accessibility of core components
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -7,6 +7,7 @@ module.exports = {
|
||||
'../../../plugins/**/src/**/*.stories.tsx',
|
||||
],
|
||||
addons: [
|
||||
'@storybook/addon-a11y',
|
||||
'@storybook/addon-actions',
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-storysource',
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user