A11y: Fix fastpass issues for annotation/variables settings (#40364)

* A11y: Fix fastpass issues for annotation/variables settings

* Chore: fixes fastpass for annotations

* Chore: updates after PR comments

* Chore: readd div
This commit is contained in:
Hugo Häggmark 2021-10-13 15:21:34 +02:00 committed by GitHub
parent 281d60095f
commit a512dcf1bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 26 additions and 12 deletions

View File

@ -88,6 +88,9 @@ export const Pages = {
General: {
headerLink: 'Variable editor Header link',
modeLabelNew: 'Variable editor Header mode New',
/**
* @deprecated
*/
modeLabelEdit: 'Variable editor Header mode Edit',
generalNameInput: 'Variable editor Form Name field',
generalTypeSelect: 'Variable editor Form Type select',

View File

@ -29,6 +29,12 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
validationMessageHorizontalOverflow?: boolean;
className?: string;
/**
* A unique id that associates the label of the Field component with the control with the unique id.
* If the `htmlFor` property is missing the `htmlFor` will be inferred from the `id` or `inputId` property of the first child.
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for
*/
htmlFor?: string;
}
export const getFieldStyles = stylesFactory((theme: GrafanaTheme2) => {
@ -72,11 +78,12 @@ export const Field: React.FC<FieldProps> = ({
children,
className,
validationMessageHorizontalOverflow,
htmlFor,
...otherProps
}) => {
const theme = useTheme2();
const styles = getFieldStyles(theme);
const inputId = getChildId(children);
const inputId = htmlFor ?? getChildId(children);
const labelElement =
typeof label === 'string' ? (

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { Checkbox, CollapsableSection, ColorValueEditor, Field, HorizontalGroup, Input } from '@grafana/ui';
import { DashboardModel } from '../../state/DashboardModel';
import { AnnotationQuery, DataSourceInstanceSettings } from '@grafana/data';
import { getDataSourceSrv, DataSourcePicker } from '@grafana/runtime';
import { DataSourcePicker, getDataSourceSrv } from '@grafana/runtime';
import { useAsync } from 'react-use';
import StandardAnnotationQueryEditor from 'app/features/annotations/components/StandardAnnotationQueryEditor';
import { AngularEditorLoader } from './AngularEditorLoader';
@ -78,7 +78,7 @@ export const AnnotationSettingsEdit: React.FC<Props> = ({ editIdx, dashboard })
width={50}
/>
</Field>
<Field label="Data source">
<Field label="Data source" htmlFor="data-source-picker">
<DataSourcePicker
width={50}
annotations

View File

@ -74,7 +74,11 @@ export const AnnotationSettingsList: React.FC<Props> = ({ dashboard, onNew, onEd
) : null}
</td>
<td style={{ width: '1%' }}>
<DeleteButton size="sm" onConfirm={() => onDelete(idx)} />
<DeleteButton
size="sm"
onConfirm={() => onDelete(idx)}
aria-label={`Delete query with title "${annotation.name}"`}
/>
</td>
</tr>
))}

View File

@ -148,7 +148,7 @@ describe('AnnotationsSettings', () => {
).toBeInTheDocument();
expect(screen.queryByRole('button', { name: /new query/i })).not.toBeInTheDocument();
userEvent.click(screen.getByRole('button', { name: /delete/i }));
userEvent.click(screen.getByRole('button', { name: /^delete$/i }));
expect(screen.queryAllByRole('row').length).toBe(0);
expect(

View File

@ -335,6 +335,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
const containerClassNames = classnames(styles.dashboardContainer, {
'panel-in-fullscreen': viewPanel,
});
const showSubMenu = !editPanel && kioskMode === KioskMode.Off && !this.props.queryParams.editview;
return (
<div className={containerClassNames}>
@ -364,7 +365,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
>
<div className={styles.dashboardContent}>
{initError && <DashboardFailed />}
{!editPanel && kioskMode === KioskMode.Off && (
{showSubMenu && (
<section aria-label={selectors.pages.Dashboard.SubMenu.submenu}>
<SubMenu dashboard={dashboard} annotations={dashboard.annotations.list} links={dashboard.links} />
</section>

View File

@ -85,10 +85,7 @@ class VariableEditorContainerUnconnected extends PureComponent<Props> {
</a>
{this.props.idInEditor && (
<span>
<Icon
name="angle-right"
aria-label={selectors.pages.Dashboard.Settings.Variables.Edit.General.modeLabelEdit}
/>
<Icon name="angle-right" />
Edit
</span>
)}

View File

@ -25,14 +25,16 @@ export function VariableSelectField({
labelWidth,
}: PropsWithChildren<VariableSelectFieldProps<any>>): ReactElement {
const styles = useStyles(getStyles);
const inputId = `variable-select-input-${name}`;
return (
<>
<InlineFormLabel width={labelWidth ?? 6} tooltip={tooltip}>
<InlineFormLabel width={labelWidth ?? 6} tooltip={tooltip} htmlFor={inputId}>
{name}
</InlineFormLabel>
<div aria-label={ariaLabel}>
<Select
inputId={inputId}
menuShouldPortal
onChange={onChange}
value={value}

View File

@ -161,7 +161,7 @@ export class QueryVariableEditorUnConnected extends PureComponent<Props, State>
<VerticalGroup spacing="lg">
<VerticalGroup spacing="none">
<InlineFieldRow>
<InlineField label="Data source" labelWidth={20}>
<InlineField label="Data source" labelWidth={20} htmlFor="data-source-picker">
<DataSourcePicker
current={this.props.variable.datasource}
onChange={this.onDataSourceChange}