mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
09079bfb65
commit
5b1fdd535a
@ -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",
|
||||
|
@ -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}>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user