diff --git a/packages/grafana-e2e-selectors/src/selectors/pages.ts b/packages/grafana-e2e-selectors/src/selectors/pages.ts index 202a579e73a..ea064f58f97 100644 --- a/packages/grafana-e2e-selectors/src/selectors/pages.ts +++ b/packages/grafana-e2e-selectors/src/selectors/pages.ts @@ -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', diff --git a/packages/grafana-ui/src/components/Forms/Field.tsx b/packages/grafana-ui/src/components/Forms/Field.tsx index b9ae14679c7..2f1d1230ede 100644 --- a/packages/grafana-ui/src/components/Forms/Field.tsx +++ b/packages/grafana-ui/src/components/Forms/Field.tsx @@ -29,6 +29,12 @@ export interface FieldProps extends HTMLAttributes { 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 = ({ 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' ? ( diff --git a/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsEdit.tsx b/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsEdit.tsx index 236bdccea39..10ab93456d6 100644 --- a/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsEdit.tsx +++ b/public/app/features/dashboard/components/AnnotationSettings/AnnotationSettingsEdit.tsx @@ -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 = ({ editIdx, dashboard }) width={50} /> - + = ({ dashboard, onNew, onEd ) : null} - onDelete(idx)} /> + onDelete(idx)} + aria-label={`Delete query with title "${annotation.name}"`} + /> ))} diff --git a/public/app/features/dashboard/components/DashboardSettings/AnnotationsSettings.test.tsx b/public/app/features/dashboard/components/DashboardSettings/AnnotationsSettings.test.tsx index 46f927828e7..92e0a657ee3 100644 --- a/public/app/features/dashboard/components/DashboardSettings/AnnotationsSettings.test.tsx +++ b/public/app/features/dashboard/components/DashboardSettings/AnnotationsSettings.test.tsx @@ -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( diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index c1f076eaacd..fd43c05b66b 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -335,6 +335,7 @@ export class UnthemedDashboardPage extends PureComponent { const containerClassNames = classnames(styles.dashboardContainer, { 'panel-in-fullscreen': viewPanel, }); + const showSubMenu = !editPanel && kioskMode === KioskMode.Off && !this.props.queryParams.editview; return (
@@ -364,7 +365,7 @@ export class UnthemedDashboardPage extends PureComponent { >
{initError && } - {!editPanel && kioskMode === KioskMode.Off && ( + {showSubMenu && (
diff --git a/public/app/features/variables/editor/VariableEditorContainer.tsx b/public/app/features/variables/editor/VariableEditorContainer.tsx index 6f03c6efbad..2ebafabb99b 100644 --- a/public/app/features/variables/editor/VariableEditorContainer.tsx +++ b/public/app/features/variables/editor/VariableEditorContainer.tsx @@ -85,10 +85,7 @@ class VariableEditorContainerUnconnected extends PureComponent { {this.props.idInEditor && ( - + Edit )} diff --git a/public/app/features/variables/editor/VariableSelectField.tsx b/public/app/features/variables/editor/VariableSelectField.tsx index 640b0aab404..2f447b29ab3 100644 --- a/public/app/features/variables/editor/VariableSelectField.tsx +++ b/public/app/features/variables/editor/VariableSelectField.tsx @@ -25,14 +25,16 @@ export function VariableSelectField({ labelWidth, }: PropsWithChildren>): ReactElement { const styles = useStyles(getStyles); + const inputId = `variable-select-input-${name}`; return ( <> - + {name}