Accessibility: turn on jsx-a11y/no-noninteractive-tabindex + fix/ignore errors (#56084)

* turn on jsx-a11y/no-noninteractive-tabindex + fix/ignore errors

* update comments
This commit is contained in:
Ashley Harrison 2022-09-30 13:20:39 +01:00 committed by GitHub
parent 09079bfb65
commit 5b1fdd535a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 23 additions and 20 deletions

View File

@ -113,7 +113,7 @@
}
],
"jsx-a11y/no-noninteractive-element-to-interactive-role": "off",
"jsx-a11y/no-noninteractive-tabindex": "off",
"jsx-a11y/no-noninteractive-tabindex": "error",
"jsx-a11y/no-redundant-roles": "error",
"jsx-a11y/no-static-element-interactions": "off",
"jsx-a11y/role-has-required-aria-props": "error",

View File

@ -63,7 +63,7 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps) {
};
const onOpen = useCallback(
(event: FormEvent<HTMLDivElement>) => {
(event: FormEvent<HTMLButtonElement>) => {
event.stopPropagation();
event.preventDefault();
setIsOpen(!isOpen);
@ -94,7 +94,7 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps) {
return (
<div className={styles.container}>
<div tabIndex={0} className={styles.pickerInput} onClick={onOpen}>
<button className={styles.pickerInput} onClick={onOpen}>
<span className={styles.clockIcon}>
<Icon name="clock-nine" />
</span>
@ -104,7 +104,7 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps) {
<span className={styles.caretIcon}>
<Icon name={isOpen ? 'angle-up' : 'angle-down'} size="lg" />
</span>
</div>
</button>
{isOpen && (
<ClickOutsideWrapper includeButtonPress={false} onClick={onClose}>
<div className={styles.content}>

View File

@ -51,7 +51,7 @@ export const TimeRangeInput: FC<TimeRangeInputProps> = ({
const theme = useTheme2();
const styles = getStyles(theme, disabled);
const onOpen = (event: FormEvent<HTMLDivElement>) => {
const onOpen = (event: FormEvent<HTMLButtonElement>) => {
event.stopPropagation();
event.preventDefault();
if (disabled) {
@ -78,12 +78,7 @@ export const TimeRangeInput: FC<TimeRangeInputProps> = ({
return (
<div className={styles.container}>
<div
tabIndex={0}
className={styles.pickerInput}
aria-label={selectors.components.TimePicker.openButton}
onClick={onOpen}
>
<button className={styles.pickerInput} aria-label={selectors.components.TimePicker.openButton} onClick={onOpen}>
{isValidTimeRange(value) ? (
<TimePickerButtonLabel value={value} timeZone={timeZone} />
) : (
@ -98,7 +93,7 @@ export const TimeRangeInput: FC<TimeRangeInputProps> = ({
<Icon name={isOpen ? 'angle-up' : 'angle-down'} size="lg" />
</span>
)}
</div>
</button>
{isOpen && (
<ClickOutsideWrapper includeButtonPress={false} onClick={onClose}>
<TimePickerContent

View File

@ -40,9 +40,13 @@ export const VizLayout: VizLayoutComponentType = ({ width, height, legend, child
if (!legend) {
return (
<div tabIndex={0} style={containerStyle} className={styles.viz}>
{children(width, height)}
</div>
<>
{/* tabIndex={0} is needed for keyboard accessibility in the plot area */}
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
<div tabIndex={0} style={containerStyle} className={styles.viz}>
{children(width, height)}
</div>
</>
);
}
@ -88,6 +92,8 @@ export const VizLayout: VizLayoutComponentType = ({ width, height, legend, child
return (
<div style={containerStyle}>
{/* tabIndex={0} is needed for keyboard accessibility in the plot area */}
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
<div tabIndex={0} className={styles.viz}>
{size && children(size.width, size.height)}
</div>

View File

@ -85,7 +85,7 @@ export function NavBarItemMenu(props: NavBarItemMenuProps): ReactElement | null
const menu = [headerComponent, contentComponent];
return (
<ul className={styles.menu} ref={ref} {...mergeProps(menuProps, contextMenuProps)} tabIndex={menuHasFocus ? 0 : -1}>
<ul className={styles.menu} ref={ref} {...mergeProps(menuProps, contextMenuProps)} tabIndex={-1}>
{reverseMenuDirection ? menu.reverse() : menu}
</ul>
);

View File

@ -161,9 +161,9 @@ export const TagFilter: FC<Props> = ({
return (
<div className={styles.tagFilter}>
{isClearable && tags.length > 0 && (
<span className={styles.clear} onClick={() => onTagChange([])} tabIndex={0}>
<button className={styles.clear} onClick={() => onTagChange([])}>
Clear tags
</span>
</button>
)}
<MultiSelect {...selectOptions} prefix={<Icon name="tag-alt" />} aria-label="Tag filter" />
</div>
@ -184,8 +184,11 @@ const getStyles = (theme: GrafanaTheme2) => ({
}
`,
clear: css`
background: none;
border: none;
text-decoration: underline;
font-size: 12px;
padding: none;
position: absolute;
top: -17px;
right: 0;

View File

@ -29,7 +29,7 @@ export function DashboardSearch({}: Props) {
const { onKeyDown, keyboardEvents } = useKeyNavigationListener();
return (
<div tabIndex={0} className={styles.overlay}>
<div className={styles.overlay}>
<div className={styles.container}>
<div className={styles.searchField}>
<div>
@ -39,7 +39,6 @@ export function DashboardSearch({}: Props) {
value={query.query ?? ''}
onChange={onSearchQueryChange}
onKeyDown={onKeyDown}
tabIndex={0}
spellCheck={false}
className={styles.input}
autoFocus