From 514d3111f4b315eaf4caa714c41c55d446011b5b Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Thu, 3 Nov 2022 10:55:58 +0000 Subject: [PATCH] Accessibility: Enable rule `jsx-a11y/no-noninteractive-element-interactions` (#58077) * fixes for no-noninteractive-element-interactions * remaining fixes * add type="button" * fix unit tests --- .eslintrc | 1 - .../TimeRangePicker/TimeRangeOption.tsx | 16 +++--- .../components/Typeahead/Typeahead.test.tsx | 10 ++-- .../src/components/Typeahead/Typeahead.tsx | 2 +- .../components/Typeahead/TypeaheadItem.tsx | 49 +++++++++++-------- .../AnnotationSettingsList.tsx | 14 +++--- .../AnnotationsSettings.test.tsx | 2 +- .../LinksSettings/LinkSettingsList.tsx | 14 +++--- .../PanelHeader/PanelHeaderCorner.test.tsx | 2 +- .../PanelHeader/PanelHeaderCorner.tsx | 4 +- public/app/features/storage/Breadcrumb.tsx | 4 +- .../variables/editor/VariableEditorList.tsx | 1 + .../editor/VariableEditorListRow.tsx | 13 ++--- .../app/plugins/panel/graph/Legend/Legend.tsx | 2 +- .../panel/graph/Legend/LegendSeriesItem.tsx | 4 +- public/sass/components/_panel_header.scss | 6 ++- 16 files changed, 79 insertions(+), 65 deletions(-) diff --git a/.eslintrc b/.eslintrc index 9762e398bbb..0ffbc3f1dbf 100644 --- a/.eslintrc +++ b/.eslintrc @@ -81,7 +81,6 @@ "ignoreNonDOM": true } ], - "jsx-a11y/no-noninteractive-element-interactions": "off", "jsx-a11y/no-static-element-interactions": "off" } } diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx index 5a9d11c8e9a..4a8ac49962c 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx @@ -14,12 +14,6 @@ const getStyles = (theme: GrafanaTheme2) => { align-items: center; flex-direction: row-reverse; justify-content: space-between; - padding: 7px 9px 7px 9px; - - &:hover { - background: ${theme.colors.action.hover}; - cursor: pointer; - } `, selected: css` background: ${theme.colors.action.selected}; @@ -27,6 +21,7 @@ const getStyles = (theme: GrafanaTheme2) => { `, radio: css` opacity: 0; + width: 0 !important; &:focus-visible + label { ${getFocusStyles(theme)}; @@ -34,6 +29,13 @@ const getStyles = (theme: GrafanaTheme2) => { `, label: css` cursor: pointer; + flex: 1; + padding: 7px 9px 7px 9px; + + &:hover { + background: ${theme.colors.action.hover}; + cursor: pointer; + } `, }; }; @@ -54,7 +56,7 @@ export const TimeRangeOption = memo(({ value, onSelect, selected = false, const id = uuidv4(); return ( -
  • onSelect(value)} className={cx(styles.container, selected && styles.selected)}> +
  • { render(); expect(screen.getByTestId('typeahead')).toBeInTheDocument(); - const items = screen.getAllByRole('listitem'); - expect(items).toHaveLength(2); - expect(items[0]).toHaveTextContent('my group'); - expect(items[1]).toHaveTextContent('first item'); + const groupTitles = screen.getAllByRole('listitem'); + expect(groupTitles).toHaveLength(1); + expect(groupTitles[0]).toHaveTextContent('my group'); + const items = screen.getAllByRole('menuitem'); + expect(items).toHaveLength(1); + expect(items[0]).toHaveTextContent('first item'); }); it('can be rendered properly even if the size of items is large', () => { diff --git a/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx b/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx index 080ad2cb822..a733ec1176e 100644 --- a/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx +++ b/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx @@ -162,7 +162,7 @@ export class Typeahead extends PureComponent { return ( -
      +
        ({ typeaheadItem: css` + border: none; + background: none; + text-align: left; label: type-ahead-item; height: auto; font-family: ${theme.typography.fontFamilyMonospace}; @@ -77,27 +80,31 @@ export const TypeaheadItem = (props: Props) => { } return ( -
      • - {item.highlightParts !== undefined ? ( - - ) : ( - - )} +
      • +
      • ); }; diff --git a/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsList.tsx b/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsList.tsx index e413f1e02f5..4698576a747 100644 --- a/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsList.tsx +++ b/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsList.tsx @@ -57,7 +57,7 @@ export const AnnotationSettingsList = ({ dashboard, onNew, onEdit }: Props) => { return ( {annotations.length > 0 && ( - +
        @@ -69,26 +69,26 @@ export const AnnotationSettingsList = ({ dashboard, onNew, onEdit }: Props) => { {dashboard.annotations.list.map((annotation, idx) => ( {annotation.builtIn ? ( - ) : ( - )} - - - -
        Query name
        onEdit(idx)}> + onEdit(idx)}> {getAnnotationName(annotation)} onEdit(idx)}> + onEdit(idx)}> {getAnnotationName(annotation)} onEdit(idx)}> + onEdit(idx)}> {dataSourceSrv.getInstanceSettings(annotation.datasource)?.name || annotation.datasource?.uid} + {idx !== 0 && onMove(idx, -1)} />} + {dashboard.annotations.list.length > 1 && idx !== dashboard.annotations.list.length - 1 ? ( onMove(idx, 1)} /> ) : null} + {!annotation.builtIn && ( { test('it renders empty list cta if only builtIn annotation', async () => { setup(dashboard); - expect(screen.queryByRole('table')).toBeInTheDocument(); + expect(screen.queryByRole('grid')).toBeInTheDocument(); expect(screen.getByRole('row', { name: /annotations & alerts \(built\-in\) grafana/i })).toBeInTheDocument(); expect( screen.getByTestId(selectors.components.CallToActionCard.buttonV2('Add annotation query')) diff --git a/public/app/features/dashboard/components/LinksSettings/LinkSettingsList.tsx b/public/app/features/dashboard/components/LinksSettings/LinkSettingsList.tsx index 935b47d63c7..515c146a36c 100644 --- a/public/app/features/dashboard/components/LinksSettings/LinkSettingsList.tsx +++ b/public/app/features/dashboard/components/LinksSettings/LinkSettingsList.tsx @@ -53,7 +53,7 @@ export const LinkSettingsList: React.FC = ({ dashboard, o return ( <> - +
        @@ -64,28 +64,28 @@ export const LinkSettingsList: React.FC = ({ dashboard, o {links.map((link, idx) => ( - - - - - -
        Type
        onEdit(idx)}> + onEdit(idx)}>   {link.type} + {link.title && {link.title}} {link.type === 'link' && {link.url}} {link.type === 'dashboards' && } + {idx !== 0 && moveLink(idx, -1)} />} + {links.length > 1 && idx !== links.length - 1 ? ( moveLink(idx, 1)} /> ) : null} + duplicateLink(link, idx)} /> + { setup(); expect( - screen.getByRole('region', { name: selectors.components.Panels.Panel.headerCornerInfo('info') }) + screen.getByRole('button', { name: selectors.components.Panels.Panel.headerCornerInfo('info') }) ).toBeInTheDocument(); }); }); diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx index 313b6fea479..d8bae5d0a2b 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx @@ -86,10 +86,10 @@ export class PanelHeaderCorner extends Component { return ( -
        +
        +
        ); } diff --git a/public/app/features/storage/Breadcrumb.tsx b/public/app/features/storage/Breadcrumb.tsx index f2a824a54e4..4ea7f9c3218 100644 --- a/public/app/features/storage/Breadcrumb.tsx +++ b/public/app/features/storage/Breadcrumb.tsx @@ -18,8 +18,8 @@ export function Breadcrumb({ pathName, onPathChange, rootIcon }: Props) { return (
          {rootIcon && ( -
        • onPathChange('')}> - +
        • + onPathChange('')} />
        • )} {paths.map((path, index) => { diff --git a/public/app/features/variables/editor/VariableEditorList.tsx b/public/app/features/variables/editor/VariableEditorList.tsx index 5f57c997398..26b0723e688 100644 --- a/public/app/features/variables/editor/VariableEditorList.tsx +++ b/public/app/features/variables/editor/VariableEditorList.tsx @@ -54,6 +54,7 @@ export function VariableEditorList({ diff --git a/public/app/features/variables/editor/VariableEditorListRow.tsx b/public/app/features/variables/editor/VariableEditorListRow.tsx index 4873a926286..d1a6d3987c9 100644 --- a/public/app/features/variables/editor/VariableEditorListRow.tsx +++ b/public/app/features/variables/editor/VariableEditorListRow.tsx @@ -52,7 +52,7 @@ export function VariableEditorListRow({ ...provided.draggableProps.style, }} > - - - - - -
          + { event.preventDefault(); @@ -77,15 +78,15 @@ export function VariableEditorListRow({ {definition} + + + { event.preventDefault(); @@ -98,7 +99,7 @@ export function VariableEditorListRow({ /> + { event.preventDefault(); @@ -110,7 +111,7 @@ export function VariableEditorListRow({ aria-label={selectors.pages.Dashboard.Settings.Variables.List.tableRowRemoveButtons(variable.name)} /> +
          diff --git a/public/app/plugins/panel/graph/Legend/Legend.tsx b/public/app/plugins/panel/graph/Legend/Legend.tsx index 37a72041840..670b892725e 100644 --- a/public/app/plugins/panel/graph/Legend/Legend.tsx +++ b/public/app/plugins/panel/graph/Legend/Legend.tsx @@ -265,7 +265,7 @@ class LegendTable extends PureComponent> { } return ( - +
          diff --git a/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx b/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx index e34c5e093b7..073c9f5872e 100644 --- a/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx +++ b/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx @@ -107,7 +107,7 @@ export class LegendItem extends PureComponent if (asTable) { return ( - {valueItems} @@ -221,7 +221,7 @@ interface LegendValueProps { function LegendValue({ value, valueName, asTable, onValueClick }: LegendValueProps) { if (asTable) { return ( - ); diff --git a/public/sass/components/_panel_header.scss b/public/sass/components/_panel_header.scss index af75702ca5a..a5eb544898d 100644 --- a/public/sass/components/_panel_header.scss +++ b/public/sass/components/_panel_header.scss @@ -112,6 +112,8 @@ $panel-header-no-title-zindex: 1; } .panel-info-corner { + background: none; + border: none; color: $text-muted; cursor: pointer; position: absolute; @@ -123,8 +125,8 @@ $panel-header-no-title-zindex: 1; top: 0; .fa { - position: relative; - top: -2px; + position: absolute; + top: 6px; left: 6px; font-size: 75%; z-index: $panel-header-no-title-zindex + 2;
          +
          {seriesLabel}
          + {value}