mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
A11y: Fix remaining focus issues with Switch (#48376)
* refactor: replace uses of checked prop for <Switch> 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 <me@giordanoricci.com>
This commit is contained in:
parent
a98a872929
commit
c57924e332
@ -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<T> extends Pick<DataSourcePluginOptionsEditorProps<T>, 'options' | 'onOptionsChange'> {
|
||||
@ -37,17 +37,17 @@ export function AlertingSettings<T extends AlertingConfig>({
|
||||
<div className="gf-form-group">
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
<Switch
|
||||
label="Manage alerts via Alerting UI"
|
||||
labelClass="width-13"
|
||||
checked={options.jsonData.manageAlerts !== false}
|
||||
onChange={(event) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
jsonData: { ...options.jsonData, manageAlerts: event!.currentTarget.checked },
|
||||
})
|
||||
}
|
||||
/>
|
||||
<InlineField labelWidth={26} label="Manage alerts via Alerting UI">
|
||||
<InlineSwitch
|
||||
value={options.jsonData.manageAlerts !== false}
|
||||
onChange={(event) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
jsonData: { ...options.jsonData, manageAlerts: event!.currentTarget.checked },
|
||||
})
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
</div>
|
||||
<InlineFieldRow>
|
||||
|
@ -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 = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const LABEL_WIDTH = 26;
|
||||
|
||||
export const DataSourceHttpSettings: React.FC<HttpSettingsProps> = (props) => {
|
||||
const {
|
||||
defaultUrl,
|
||||
@ -208,53 +211,64 @@ export const DataSourceHttpSettings: React.FC<HttpSettingsProps> = (props) => {
|
||||
<h3 className="page-heading">Auth</h3>
|
||||
<div className="gf-form-group">
|
||||
<div className="gf-form-inline">
|
||||
<Switch
|
||||
label="Basic auth"
|
||||
labelClass="width-13"
|
||||
checked={dataSourceConfig.basicAuth}
|
||||
onChange={(event) => {
|
||||
onSettingsChange({ basicAuth: event!.currentTarget.checked });
|
||||
}}
|
||||
/>
|
||||
<Switch
|
||||
<InlineField label="Basic auth" labelWidth={LABEL_WIDTH}>
|
||||
<InlineSwitch
|
||||
id="http-settings-basic-auth"
|
||||
value={dataSourceConfig.basicAuth}
|
||||
onChange={(event) => {
|
||||
onSettingsChange({ basicAuth: event!.currentTarget.checked });
|
||||
}}
|
||||
/>
|
||||
</InlineField>
|
||||
|
||||
<InlineField
|
||||
label="With Credentials"
|
||||
labelClass="width-13"
|
||||
checked={dataSourceConfig.withCredentials}
|
||||
onChange={(event) => {
|
||||
onSettingsChange({ withCredentials: event!.currentTarget.checked });
|
||||
}}
|
||||
tooltip="Whether credentials such as cookies or auth headers should be sent with cross-site requests."
|
||||
/>
|
||||
labelWidth={LABEL_WIDTH}
|
||||
>
|
||||
<InlineSwitch
|
||||
id="http-settings-with-credentials"
|
||||
value={dataSourceConfig.withCredentials}
|
||||
onChange={(event) => {
|
||||
onSettingsChange({ withCredentials: event!.currentTarget.checked });
|
||||
}}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
|
||||
{azureAuthSettings?.azureAuthSupported && (
|
||||
<div className="gf-form-inline">
|
||||
<Switch
|
||||
<InlineField
|
||||
label="Azure Authentication"
|
||||
labelClass="width-13"
|
||||
checked={azureAuthEnabled}
|
||||
onChange={(event) => {
|
||||
onSettingsChange(
|
||||
azureAuthSettings.setAzureAuthEnabled(dataSourceConfig, event!.currentTarget.checked)
|
||||
);
|
||||
}}
|
||||
tooltip="Use Azure authentication for Azure endpoint."
|
||||
/>
|
||||
labelWidth={LABEL_WIDTH}
|
||||
>
|
||||
<InlineSwitch
|
||||
id="http-settings-azure-auth"
|
||||
value={azureAuthEnabled}
|
||||
onChange={(event) => {
|
||||
onSettingsChange(
|
||||
azureAuthSettings.setAzureAuthEnabled(dataSourceConfig, event!.currentTarget.checked)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sigV4AuthToggleEnabled && (
|
||||
<div className="gf-form-inline">
|
||||
<Switch
|
||||
label="SigV4 auth"
|
||||
labelClass="width-13"
|
||||
checked={dataSourceConfig.jsonData.sigV4Auth || false}
|
||||
onChange={(event) => {
|
||||
onSettingsChange({
|
||||
jsonData: { ...dataSourceConfig.jsonData, sigV4Auth: event!.currentTarget.checked },
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<InlineField label="SigV4 auth" labelWidth={LABEL_WIDTH}>
|
||||
<InlineSwitch
|
||||
id="http-settings-sigv4-auth"
|
||||
value={dataSourceConfig.jsonData.sigV4Auth || false}
|
||||
onChange={(event) => {
|
||||
onSettingsChange({
|
||||
jsonData: { ...dataSourceConfig.jsonData, sigV4Auth: event!.currentTarget.checked },
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -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<HttpSettingsBaseProps> = ({
|
||||
dataSourceConfig,
|
||||
onChange,
|
||||
@ -12,42 +15,49 @@ export const HttpProxySettings: React.FC<HttpSettingsBaseProps> = ({
|
||||
return (
|
||||
<>
|
||||
<div className="gf-form-inline">
|
||||
<Switch
|
||||
label="TLS Client Auth"
|
||||
labelClass="width-13"
|
||||
checked={dataSourceConfig.jsonData.tlsAuth || false}
|
||||
onChange={(event) => onChange({ ...dataSourceConfig.jsonData, tlsAuth: event!.currentTarget.checked })}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label="With CA Cert"
|
||||
labelClass="width-13"
|
||||
checked={dataSourceConfig.jsonData.tlsAuthWithCACert || false}
|
||||
onChange={(event) =>
|
||||
onChange({ ...dataSourceConfig.jsonData, tlsAuthWithCACert: event!.currentTarget.checked })
|
||||
}
|
||||
tooltip="Needed for verifying self-signed TLS Certs"
|
||||
/>
|
||||
<InlineField label="TLS Client Auth" labelWidth={LABEL_WIDTH}>
|
||||
<InlineSwitch
|
||||
id="http-settings-tls-client-auth"
|
||||
value={dataSourceConfig.jsonData.tlsAuth || false}
|
||||
onChange={(event) => onChange({ ...dataSourceConfig.jsonData, tlsAuth: event!.currentTarget.checked })}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField label="With CA Cert" tooltip="Needed for verifying self-signed TLS Certs" labelWidth={LABEL_WIDTH}>
|
||||
<InlineSwitch
|
||||
id="http-settings-ca-cert"
|
||||
value={dataSourceConfig.jsonData.tlsAuthWithCACert || false}
|
||||
onChange={(event) =>
|
||||
onChange({ ...dataSourceConfig.jsonData, tlsAuthWithCACert: event!.currentTarget.checked })
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
<div className="gf-form-inline">
|
||||
<Switch
|
||||
label="Skip TLS Verify"
|
||||
labelClass="width-13"
|
||||
checked={dataSourceConfig.jsonData.tlsSkipVerify || false}
|
||||
onChange={(event) => onChange({ ...dataSourceConfig.jsonData, tlsSkipVerify: event!.currentTarget.checked })}
|
||||
/>
|
||||
<InlineField label="Skip TLS Verify" labelWidth={LABEL_WIDTH}>
|
||||
<InlineSwitch
|
||||
id="http-settings-skip-tls-verify"
|
||||
value={dataSourceConfig.jsonData.tlsSkipVerify || false}
|
||||
onChange={(event) =>
|
||||
onChange({ ...dataSourceConfig.jsonData, tlsSkipVerify: event!.currentTarget.checked })
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
{showForwardOAuthIdentityOption && (
|
||||
<div className="gf-form-inline">
|
||||
<Switch
|
||||
<InlineField
|
||||
label="Forward OAuth Identity"
|
||||
labelClass="width-13"
|
||||
checked={dataSourceConfig.jsonData.oauthPassThru || false}
|
||||
onChange={(event) =>
|
||||
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}
|
||||
>
|
||||
<InlineSwitch
|
||||
id="http-settings-forward-oauth"
|
||||
value={dataSourceConfig.jsonData.oauthPassThru || false}
|
||||
onChange={(event) =>
|
||||
onChange({ ...dataSourceConfig.jsonData, oauthPassThru: event!.currentTarget.checked })
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
@ -57,7 +57,7 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
|
||||
return (
|
||||
<Switch
|
||||
value={panel.transparent}
|
||||
id="Transparent background"
|
||||
id="transparent-background"
|
||||
onChange={(e) => onPanelConfigChange('transparent', e.currentTarget.checked)}
|
||||
/>
|
||||
);
|
||||
|
@ -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<Props> = ({ dataSourceName, isDefault, onDefaultChange,
|
||||
return (
|
||||
<div className="gf-form-group" aria-label="Datasource settings page basic settings">
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form max-width-30" style={{ marginRight: '3px' }}>
|
||||
<InlineFormLabel
|
||||
tooltip={
|
||||
'The name is used when you select the data source in panels. The default data source is ' +
|
||||
'preselected in new panels.'
|
||||
}
|
||||
<div className="gf-form max-width-30">
|
||||
<InlineField
|
||||
label="Name"
|
||||
tooltip="The name is used when you select the data source in panels. The default data source is
|
||||
'preselected in new panels."
|
||||
grow
|
||||
>
|
||||
Name
|
||||
</InlineFormLabel>
|
||||
<Input
|
||||
className="gf-form-input max-width-23"
|
||||
type="text"
|
||||
value={dataSourceName}
|
||||
placeholder="Name"
|
||||
onChange={(event) => onNameChange(event.target.value)}
|
||||
required
|
||||
aria-label={selectors.pages.DataSource.name}
|
||||
/>
|
||||
<Input
|
||||
id="basic-settings-name"
|
||||
type="text"
|
||||
value={dataSourceName}
|
||||
placeholder="Name"
|
||||
onChange={(event) => onNameChange(event.currentTarget.value)}
|
||||
required
|
||||
aria-label={selectors.pages.DataSource.name}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
<Switch
|
||||
label="Default"
|
||||
checked={isDefault}
|
||||
onChange={(event) => {
|
||||
// @ts-ignore
|
||||
onDefaultChange(event.target.checked);
|
||||
}}
|
||||
/>
|
||||
|
||||
<InlineField label="Default" labelWidth={8}>
|
||||
<InlineSwitch
|
||||
id="basic-settings-default"
|
||||
value={isDefault}
|
||||
onChange={(event: React.FormEvent<HTMLInputElement>) => {
|
||||
onDefaultChange(event.currentTarget.checked);
|
||||
}}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -10,32 +10,34 @@ exports[`Render should render component 1`] = `
|
||||
>
|
||||
<div
|
||||
className="gf-form max-width-30"
|
||||
style={
|
||||
Object {
|
||||
"marginRight": "3px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<FormLabel
|
||||
tooltip="The name is used when you select the data source in panels. The default data source is preselected in new panels."
|
||||
<InlineField
|
||||
grow={true}
|
||||
label="Name"
|
||||
tooltip="The name is used when you select the data source in panels. The default data source is
|
||||
'preselected in new panels."
|
||||
>
|
||||
Name
|
||||
</FormLabel>
|
||||
<Input
|
||||
aria-label="Data source settings page name input field"
|
||||
className="gf-form-input max-width-23"
|
||||
onChange={[Function]}
|
||||
placeholder="Name"
|
||||
required={true}
|
||||
type="text"
|
||||
value="Graphite"
|
||||
/>
|
||||
<Input
|
||||
aria-label="Data source settings page name input field"
|
||||
id="basic-settings-name"
|
||||
onChange={[Function]}
|
||||
placeholder="Name"
|
||||
required={true}
|
||||
type="text"
|
||||
value="Graphite"
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
<Switch
|
||||
checked={false}
|
||||
<InlineField
|
||||
label="Default"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
labelWidth={8}
|
||||
>
|
||||
<Switch
|
||||
id="basic-settings-default"
|
||||
onChange={[Function]}
|
||||
value={false}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -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) => {
|
||||
<h3 className="page-heading">Misc</h3>
|
||||
<div className="gf-form-group">
|
||||
<div className="gf-form">
|
||||
<Switch
|
||||
checked={options.jsonData.disableMetricsLookup ?? false}
|
||||
<InlineField
|
||||
labelWidth={28}
|
||||
label="Disable metrics lookup"
|
||||
labelClass="width-14"
|
||||
onChange={onUpdateDatasourceJsonDataOptionChecked(props, 'disableMetricsLookup')}
|
||||
tooltip="Checking this option will disable the metrics chooser and metric/label support in the query field's autocomplete. This helps if you have performance issues with bigger Prometheus instances."
|
||||
/>
|
||||
>
|
||||
<InlineSwitch
|
||||
value={options.jsonData.disableMetricsLookup ?? false}
|
||||
onChange={onUpdateDatasourceJsonDataOptionChecked(props, 'disableMetricsLookup')}
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form max-width-30">
|
||||
|
@ -12,7 +12,8 @@ export interface Props extends Omit<HTMLProps<HTMLInputElement>, '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 (
|
||||
|
Loading…
Reference in New Issue
Block a user