From 6e8ef91c03f79b92285056a25466ff9a0e1baa1b Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 2 May 2022 10:04:02 -0400 Subject: [PATCH] A11y: Fix remaining focus issues with Switch (#48376) (#48584) * refactor: replace uses of checked prop for with value prop * fix: remove spaces from ids The ID format is stated as follows([source][1]): > ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods ("."). Since `QueryHeaderSwitch` is used in two places I created a new variable that replaces spaces with a dash in the label. [1]: https://www.w3.org/TR/html401/types.html#type-name * fix: allow Switch in AlertingSettings to be focused by keyboard * fix: allow Switch in PromSettings to be focused by keyboard Fixes #46472 Co-authored-by: Elfo404 (cherry picked from commit c57924e332283bd107886a9b01123edda4f29f8d) Co-authored-by: Adam Simpson --- .../DataSourceSettings/AlertingSettings.tsx | 24 +++--- .../DataSourceHttpSettings.tsx | 84 +++++++++++-------- .../DataSourceSettings/HttpProxySettings.tsx | 70 +++++++++------- .../PanelEditor/getPanelFrameOptions.tsx | 2 +- .../datasources/settings/BasicSettings.tsx | 55 ++++++------ .../__snapshots__/BasicSettings.test.tsx.snap | 46 +++++----- .../prometheus/configuration/PromSettings.tsx | 24 ++++-- .../querybuilder/shared/QueryHeaderSwitch.tsx | 3 +- 8 files changed, 172 insertions(+), 136 deletions(-) diff --git a/packages/grafana-ui/src/components/DataSourceSettings/AlertingSettings.tsx b/packages/grafana-ui/src/components/DataSourceSettings/AlertingSettings.tsx index ac2c050f512..994fd9367bc 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/AlertingSettings.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/AlertingSettings.tsx @@ -2,9 +2,9 @@ import React, { useMemo } from 'react'; import { DataSourceInstanceSettings, DataSourceJsonData, DataSourcePluginOptionsEditorProps } from '@grafana/data'; +import { InlineSwitch } from '../../components/Switch/Switch'; import { InlineField } from '../Forms/InlineField'; import { InlineFieldRow } from '../Forms/InlineFieldRow'; -import { Switch } from '../Forms/Legacy/Switch/Switch'; import { Select } from '../Select/Select'; interface Props extends Pick, 'options' | 'onOptionsChange'> { @@ -37,17 +37,17 @@ export function AlertingSettings({
- - onOptionsChange({ - ...options, - jsonData: { ...options.jsonData, manageAlerts: event!.currentTarget.checked }, - }) - } - /> + + + onOptionsChange({ + ...options, + jsonData: { ...options.jsonData, manageAlerts: event!.currentTarget.checked }, + }) + } + /> +
diff --git a/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx b/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx index 9cf6da6aba2..4f6aeee97e2 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx @@ -7,10 +7,11 @@ import { selectors } from '@grafana/e2e-selectors'; import { useTheme } from '../../themes'; import { FormField } from '../FormField/FormField'; import { InlineFormLabel } from '../FormLabel/FormLabel'; +import { InlineField } from '../Forms/InlineField'; import { Input } from '../Forms/Legacy/Input/Input'; -import { Switch } from '../Forms/Legacy/Switch/Switch'; import { Icon } from '../Icon/Icon'; import { Select } from '../Select/Select'; +import { InlineSwitch } from '../Switch/Switch'; import { TagsInput } from '../TagsInput/TagsInput'; import { BasicAuthSettings } from './BasicAuthSettings'; @@ -59,6 +60,8 @@ const HttpAccessHelp = () => (
); +const LABEL_WIDTH = 26; + export const DataSourceHttpSettings: React.FC = (props) => { const { defaultUrl, @@ -208,53 +211,64 @@ export const DataSourceHttpSettings: React.FC = (props) => {

Auth

- { - onSettingsChange({ basicAuth: event!.currentTarget.checked }); - }} - /> - + { + onSettingsChange({ basicAuth: event!.currentTarget.checked }); + }} + /> + + + { - onSettingsChange({ withCredentials: event!.currentTarget.checked }); - }} tooltip="Whether credentials such as cookies or auth headers should be sent with cross-site requests." - /> + labelWidth={LABEL_WIDTH} + > + { + onSettingsChange({ withCredentials: event!.currentTarget.checked }); + }} + /> +
{azureAuthSettings?.azureAuthSupported && (
- { - onSettingsChange( - azureAuthSettings.setAzureAuthEnabled(dataSourceConfig, event!.currentTarget.checked) - ); - }} tooltip="Use Azure authentication for Azure endpoint." - /> + labelWidth={LABEL_WIDTH} + > + { + onSettingsChange( + azureAuthSettings.setAzureAuthEnabled(dataSourceConfig, event!.currentTarget.checked) + ); + }} + /> +
)} {sigV4AuthToggleEnabled && (
- { - onSettingsChange({ - jsonData: { ...dataSourceConfig.jsonData, sigV4Auth: event!.currentTarget.checked }, - }); - }} - /> + + { + onSettingsChange({ + jsonData: { ...dataSourceConfig.jsonData, sigV4Auth: event!.currentTarget.checked }, + }); + }} + /> +
)} diff --git a/packages/grafana-ui/src/components/DataSourceSettings/HttpProxySettings.tsx b/packages/grafana-ui/src/components/DataSourceSettings/HttpProxySettings.tsx index 07ab46edec3..8eefd4f411c 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/HttpProxySettings.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/HttpProxySettings.tsx @@ -1,9 +1,12 @@ import React from 'react'; -import { Switch } from '../Forms/Legacy/Switch/Switch'; +import { InlineField } from '../Forms/InlineField'; +import { InlineSwitch } from '../Switch/Switch'; import { HttpSettingsBaseProps } from './types'; +const LABEL_WIDTH = 26; + export const HttpProxySettings: React.FC = ({ dataSourceConfig, onChange, @@ -12,42 +15,49 @@ export const HttpProxySettings: React.FC = ({ return ( <>
- onChange({ ...dataSourceConfig.jsonData, tlsAuth: event!.currentTarget.checked })} - /> - - - onChange({ ...dataSourceConfig.jsonData, tlsAuthWithCACert: event!.currentTarget.checked }) - } - tooltip="Needed for verifying self-signed TLS Certs" - /> + + onChange({ ...dataSourceConfig.jsonData, tlsAuth: event!.currentTarget.checked })} + /> + + + + onChange({ ...dataSourceConfig.jsonData, tlsAuthWithCACert: event!.currentTarget.checked }) + } + /> +
- onChange({ ...dataSourceConfig.jsonData, tlsSkipVerify: event!.currentTarget.checked })} - /> + + + onChange({ ...dataSourceConfig.jsonData, tlsSkipVerify: event!.currentTarget.checked }) + } + /> +
{showForwardOAuthIdentityOption && (
- - onChange({ ...dataSourceConfig.jsonData, oauthPassThru: event!.currentTarget.checked }) - } tooltip="Forward the user's upstream OAuth identity to the data source (Their access token gets passed along)." - /> + labelWidth={LABEL_WIDTH} + > + + onChange({ ...dataSourceConfig.jsonData, oauthPassThru: event!.currentTarget.checked }) + } + /> +
)} diff --git a/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx b/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx index 20e4a7a69b7..4cb6c09d2ba 100644 --- a/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx +++ b/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx @@ -57,7 +57,7 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane return ( onPanelConfigChange('transparent', e.currentTarget.checked)} /> ); diff --git a/public/app/features/datasources/settings/BasicSettings.tsx b/public/app/features/datasources/settings/BasicSettings.tsx index ad9d7d49f72..5b3eb0117a7 100644 --- a/public/app/features/datasources/settings/BasicSettings.tsx +++ b/public/app/features/datasources/settings/BasicSettings.tsx @@ -1,9 +1,7 @@ import React, { FC } from 'react'; import { selectors } from '@grafana/e2e-selectors'; -import { InlineFormLabel, LegacyForms } from '@grafana/ui'; - -const { Input, Switch } = LegacyForms; +import { InlineField, InlineSwitch, Input } from '@grafana/ui'; export interface Props { dataSourceName: string; @@ -16,33 +14,34 @@ const BasicSettings: FC = ({ dataSourceName, isDefault, onDefaultChange, return (
-
- + - Name - - onNameChange(event.target.value)} - required - aria-label={selectors.pages.DataSource.name} - /> + onNameChange(event.currentTarget.value)} + required + aria-label={selectors.pages.DataSource.name} + /> +
- { - // @ts-ignore - onDefaultChange(event.target.checked); - }} - /> + + + ) => { + onDefaultChange(event.currentTarget.checked); + }} + /> +
); diff --git a/public/app/features/datasources/settings/__snapshots__/BasicSettings.test.tsx.snap b/public/app/features/datasources/settings/__snapshots__/BasicSettings.test.tsx.snap index a91abfb7c9f..e1d5f3203d3 100644 --- a/public/app/features/datasources/settings/__snapshots__/BasicSettings.test.tsx.snap +++ b/public/app/features/datasources/settings/__snapshots__/BasicSettings.test.tsx.snap @@ -10,32 +10,34 @@ exports[`Render should render component 1`] = ` >
- - Name - - + +
- + labelWidth={8} + > + +
`; diff --git a/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx b/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx index c04f8e74cdf..11fcdf47f17 100644 --- a/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx +++ b/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx @@ -6,12 +6,19 @@ import { SelectableValue, updateDatasourcePluginJsonDataOption, } from '@grafana/data'; -import { EventsWithValidation, InlineFormLabel, LegacyForms, regexValidation } from '@grafana/ui'; +import { + InlineField, + InlineSwitch, + EventsWithValidation, + InlineFormLabel, + LegacyForms, + regexValidation, +} from '@grafana/ui'; import { PromOptions } from '../types'; import { ExemplarsSettings } from './ExemplarsSettings'; -const { Select, Input, FormField, Switch } = LegacyForms; +const { Select, Input, FormField } = LegacyForms; const httpOptions = [ { value: 'POST', label: 'POST' }, @@ -90,13 +97,16 @@ export const PromSettings = (props: Props) => {

Misc

- + > + +
diff --git a/public/app/plugins/datasource/prometheus/querybuilder/shared/QueryHeaderSwitch.tsx b/public/app/plugins/datasource/prometheus/querybuilder/shared/QueryHeaderSwitch.tsx index 3bee386a581..8e591e27c6c 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/shared/QueryHeaderSwitch.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/shared/QueryHeaderSwitch.tsx @@ -12,7 +12,8 @@ export interface Props extends Omit, 'value' | 'ref' } export function QueryHeaderSwitch({ label, ...inputProps }: Props) { - const switchIdRef = useRef(uniqueId(`switch-${label}`)); + const dashedLabel = label.replace(' ', '-'); + const switchIdRef = useRef(uniqueId(`switch-${dashedLabel}`)); const styles = useStyles2(getStyles); return (