A11y: Make the Library Panel "clear filter" buttons accessible (#46341)

* swap span for button + add aria-label

* swap span for button + add aria-label

* add new style + increase padding

* fix typo

* switch to link variant + trim custom css
This commit is contained in:
matt abrams 2022-03-11 00:10:13 -10:00 committed by GitHub
parent 73ba04cda6
commit ec84b7bd23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 35 deletions

View File

@ -1,7 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react';
import { css } from '@emotion/css';
import debounce from 'debounce-promise';
import { AsyncMultiSelect, Icon, useStyles2 } from '@grafana/ui';
import { AsyncMultiSelect, Icon, Button, useStyles2 } from '@grafana/ui';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { FolderInfo, PermissionLevelString } from 'app/types';
@ -44,9 +44,16 @@ export function FolderFilter({ onChange: propsOnChange, maxMenuHeight }: FolderF
return (
<div className={styles.container}>
{value.length > 0 && (
<span className={styles.clear} onClick={() => onChange([])}>
<Button
size="xs"
icon="trash-alt"
variant="link"
className={styles.clear}
onClick={() => onChange([])}
aria-label="Clear folders"
>
Clear folders
</span>
</Button>
)}
<AsyncMultiSelect
menuShouldPortal
@ -90,17 +97,10 @@ function getStyles(theme: GrafanaTheme2) {
`,
clear: css`
label: clear;
text-decoration: underline;
font-size: ${theme.spacing(1.5)};
position: absolute;
top: -${theme.spacing(2.75)};
top: -${theme.spacing(4.5)};
right: 0;
cursor: pointer;
color: ${theme.colors.text.link};
&:hover {
color: ${theme.colors.text.maxContrast};
}
`,
};
}

View File

@ -1,7 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react';
import { GrafanaTheme2, PanelPluginMeta, SelectableValue } from '@grafana/data';
import { getAllPanelPluginMeta } from 'app/features/panel/state/util';
import { Icon, MultiSelect, useStyles2 } from '@grafana/ui';
import { Icon, Button, MultiSelect, useStyles2 } from '@grafana/ui';
import { css } from '@emotion/css';
export interface Props {
@ -51,9 +51,16 @@ export const PanelTypeFilter = ({ onChange: propsOnChange, maxMenuHeight }: Prop
return (
<div className={styles.container}>
{value.length > 0 && (
<span className={styles.clear} onClick={() => onChange([])}>
<Button
size="xs"
icon="trash-alt"
variant="link"
className={styles.clear}
onClick={() => onChange([])}
aria-label="Clear types"
>
Clear types
</span>
</Button>
)}
<MultiSelect menuShouldPortal {...selectOptions} prefix={<Icon name="filter" />} aria-label="Panel Type filter" />
</div>
@ -70,17 +77,10 @@ function getStyles(theme: GrafanaTheme2) {
`,
clear: css`
label: clear;
text-decoration: underline;
font-size: ${theme.spacing(1.5)};
position: absolute;
top: -${theme.spacing(2.75)};
top: -${theme.spacing(4.5)};
right: 0;
cursor: pointer;
color: ${theme.colors.text.link};
&:hover {
color: ${theme.colors.text.maxContrast};
}
`,
};
}

View File

@ -66,18 +66,23 @@ export const LibraryPanelsSearch = ({
placeholder={'Search by name or description'}
width={0}
/>
<HorizontalGroup
spacing="sm"
justify={(showSort && showPanelFilter) || showFolderFilter ? 'space-between' : 'flex-end'}
>
{showSort && (
<SortPicker value={sortDirection} onChange={onSortChange} filter={['alpha-asc', 'alpha-desc']} />
)}
<HorizontalGroup spacing="sm" justify={showFolderFilter && showPanelFilter ? 'space-between' : 'flex-end'}>
{showFolderFilter && <FolderFilter onChange={onFolderFilterChange} />}
{showPanelFilter && <PanelTypeFilter onChange={onPanelFilterChange} />}
<div className={styles.buttonRow}>
<HorizontalGroup
spacing="sm"
justify={(showSort && showPanelFilter) || showFolderFilter ? 'space-between' : 'flex-end'}
>
{showSort && (
<SortPicker value={sortDirection} onChange={onSortChange} filter={['alpha-asc', 'alpha-desc']} />
)}
<HorizontalGroup
spacing="sm"
justify={showFolderFilter && showPanelFilter ? 'space-between' : 'flex-end'}
>
{showFolderFilter && <FolderFilter onChange={onFolderFilterChange} />}
{showPanelFilter && <PanelTypeFilter onChange={onPanelFilterChange} />}
</HorizontalGroup>
</HorizontalGroup>
</HorizontalGroup>
</div>
<div className={styles.libraryPanelsView}>
<LibraryPanelsView
onClickCard={onClick}
@ -98,7 +103,7 @@ export const LibraryPanelsSearch = ({
return (
<div className={styles.container}>
<VerticalGroup spacing="xs">
<div className={styles.buttonRow}>
<div className={styles.tightButtonRow}>
<div className={styles.tightFilter}>
<FilterInput value={searchQuery} onChange={onFilterChange} placeholder={'Search by name'} width={0} />
</div>
@ -136,7 +141,13 @@ function getStyles(theme: GrafanaTheme2) {
display: flex;
justify-content: space-between;
width: 100%;
margin-top: ${theme.spacing(1.5)}; // Clear types link
margin-top: ${theme.spacing(2)}; // Clear types link
`,
tightButtonRow: css`
display: flex;
justify-content: space-between;
width: 100%;
margin-top: ${theme.spacing(4)}; // Clear types link
`,
tightFilter: css`
flex-grow: 1;