mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
A11y: Fix misc. fastpass issues (#41088)
This commit is contained in:
parent
d98cb8274c
commit
124c3f537f
@ -96,7 +96,7 @@ class DarkColors implements ThemeColorsBase<Partial<ThemeRichColor>> {
|
||||
text = {
|
||||
primary: `rgb(${this.whiteBase})`,
|
||||
secondary: `rgba(${this.whiteBase}, 0.65)`,
|
||||
disabled: `rgba(${this.whiteBase}, 0.57)`,
|
||||
disabled: `rgba(${this.whiteBase}, 0.58)`,
|
||||
link: palette.blueDarkText,
|
||||
maxContrast: palette.white,
|
||||
};
|
||||
|
@ -60,7 +60,7 @@ export const Alert = React.forwardRef<HTMLDivElement, Props>(
|
||||
{/* If onRemove is specified, giving preference to onRemove */}
|
||||
{onRemove && !buttonContent && (
|
||||
<div className={styles.close}>
|
||||
<IconButton name="times" onClick={onRemove} size="lg" type="button" />
|
||||
<IconButton aria-label="Close alert" name="times" onClick={onRemove} size="lg" type="button" />
|
||||
</div>
|
||||
)}
|
||||
{onRemove && buttonContent && (
|
||||
|
@ -135,7 +135,7 @@ const DateTimeInput: FC<InputProps> = ({ date, label, onChange, isFullscreen, on
|
||||
}
|
||||
}, [internalDate.value, onChange]);
|
||||
|
||||
const icon = <Button icon="calendar-alt" variant="secondary" onClick={onOpen} />;
|
||||
const icon = <Button aria-label="Time picker" icon="calendar-alt" variant="secondary" onClick={onOpen} />;
|
||||
return (
|
||||
<InlineField
|
||||
label={label}
|
||||
@ -195,7 +195,9 @@ const DateTimeCalendar: FC<DateTimeCalendarProps> = ({ date, onClose, onChange,
|
||||
prev2Label={null}
|
||||
value={internalDate}
|
||||
nextLabel={<Icon name="angle-right" />}
|
||||
nextAriaLabel="Next month"
|
||||
prevLabel={<Icon name="angle-left" />}
|
||||
prevAriaLabel="Previous month"
|
||||
onChange={onChangeDate}
|
||||
locale="en"
|
||||
className={calendarStyles.body}
|
||||
|
@ -5,7 +5,7 @@ import { Select } from '../Select/Select';
|
||||
import { useFieldDisplayNames, useSelectOptions, frameHasName } from './utils';
|
||||
|
||||
export const FieldNameMatcherEditor = memo<MatcherUIProps<string>>((props) => {
|
||||
const { data, options, onChange: onChangeFromProps } = props;
|
||||
const { data, options, onChange: onChangeFromProps, id } = props;
|
||||
const names = useFieldDisplayNames(data);
|
||||
const selectOptions = useSelectOptions(names, options);
|
||||
|
||||
@ -20,7 +20,7 @@ export const FieldNameMatcherEditor = memo<MatcherUIProps<string>>((props) => {
|
||||
);
|
||||
|
||||
const selectedOption = selectOptions.find((v) => v.value === options);
|
||||
return <Select menuShouldPortal value={selectedOption} options={selectOptions} onChange={onChange} />;
|
||||
return <Select menuShouldPortal value={selectedOption} options={selectOptions} onChange={onChange} inputId={id} />;
|
||||
});
|
||||
FieldNameMatcherEditor.displayName = 'FieldNameMatcherEditor';
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { FieldMatcherID, fieldMatchers, SelectableValue, FieldType, DataFrame }
|
||||
import { Select } from '../Select/Select';
|
||||
|
||||
export const FieldTypeMatcherEditor = memo<MatcherUIProps<string>>((props) => {
|
||||
const { data, options, onChange: onChangeFromProps } = props;
|
||||
const { data, options, onChange: onChangeFromProps, id } = props;
|
||||
const counts = useFieldCounts(data);
|
||||
const selectOptions = useSelectOptions(counts, options);
|
||||
|
||||
@ -16,7 +16,7 @@ export const FieldTypeMatcherEditor = memo<MatcherUIProps<string>>((props) => {
|
||||
);
|
||||
|
||||
const selectedOption = selectOptions.find((v) => v.value === options);
|
||||
return <Select menuShouldPortal value={selectedOption} options={selectOptions} onChange={onChange} />;
|
||||
return <Select inputId={id} value={selectedOption} options={selectOptions} onChange={onChange} menuShouldPortal />;
|
||||
});
|
||||
FieldTypeMatcherEditor.displayName = 'FieldTypeMatcherEditor';
|
||||
|
||||
|
@ -10,6 +10,7 @@ export interface FieldMatcherUIRegistryItem<TOptions> extends RegistryItem {
|
||||
|
||||
export interface MatcherUIProps<T> {
|
||||
matcher: FieldMatcherInfo<T>;
|
||||
id?: string;
|
||||
data: DataFrame[];
|
||||
options: T;
|
||||
onChange: (options: T) => void;
|
||||
|
@ -3,6 +3,7 @@ import { cx } from '@emotion/css';
|
||||
|
||||
export interface CardProps {
|
||||
logoUrl?: string;
|
||||
logoAlt?: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
labels?: React.ReactNode;
|
||||
@ -14,6 +15,7 @@ export interface CardProps {
|
||||
|
||||
export const Card: React.FC<CardProps> = ({
|
||||
logoUrl,
|
||||
logoAlt,
|
||||
title,
|
||||
description,
|
||||
labels,
|
||||
@ -26,7 +28,7 @@ export const Card: React.FC<CardProps> = ({
|
||||
|
||||
return (
|
||||
<div className={mainClassName} onClick={onClick} aria-label={ariaLabel}>
|
||||
{logoUrl && <img className="add-data-source-item-logo" src={logoUrl} />}
|
||||
{logoUrl && <img className="add-data-source-item-logo" src={logoUrl} alt={logoAlt ?? ''} />}
|
||||
<div className="add-data-source-item-text-wrapper">
|
||||
<span className="add-data-source-item-text">{title}</span>
|
||||
{description && <span className="add-data-source-item-desc">{description}</span>}
|
||||
|
@ -9,6 +9,7 @@ export type OrgSelectItem = SelectableValue<Organization>;
|
||||
export interface Props {
|
||||
onSelected: (org: OrgSelectItem) => void;
|
||||
className?: string;
|
||||
inputId?: string;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
@ -43,12 +44,13 @@ export class OrgPicker extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { className, onSelected } = this.props;
|
||||
const { className, onSelected, inputId } = this.props;
|
||||
const { isLoading } = this.state;
|
||||
|
||||
return (
|
||||
<AsyncSelect
|
||||
menuShouldPortal
|
||||
inputId={inputId}
|
||||
className={className}
|
||||
isLoading={isLoading}
|
||||
defaultOptions={true}
|
||||
|
@ -121,6 +121,7 @@ export function getFieldOverrideCategories(props: OptionPaneRenderProps): Option
|
||||
render: function renderMatcherUI() {
|
||||
return (
|
||||
<matcherUi.component
|
||||
id={`${matcherUi.matcher.id}-${idx}`}
|
||||
matcher={matcherUi.matcher}
|
||||
data={props.data?.series ?? []}
|
||||
options={override.matcher.options}
|
||||
|
@ -132,13 +132,14 @@ export const InspectDataOptions: FC<Props> = ({
|
||||
description="Table data is formatted with options defined in the Field and Override tabs."
|
||||
>
|
||||
<Switch
|
||||
id="formatted-data-toggle"
|
||||
value={!!options.withFieldConfig}
|
||||
onChange={() => onOptionsChange({ ...options, withFieldConfig: !options.withFieldConfig })}
|
||||
/>
|
||||
</Field>
|
||||
)}
|
||||
<Field label="Download for Excel" description="Adds header to CSV for use with Excel">
|
||||
<Switch value={downloadForExcel} onChange={toggleDownloadForExcel} />
|
||||
<Switch id="excel-toggle" value={downloadForExcel} onChange={toggleDownloadForExcel} />
|
||||
</Field>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
|
@ -132,7 +132,13 @@ export class InspectJSONTab extends PureComponent<Props, State> {
|
||||
<>
|
||||
<div className={styles.toolbar} aria-label={selectors.components.PanelInspector.Json.content}>
|
||||
<Field label="Select source" className="flex-grow-1">
|
||||
<Select menuShouldPortal options={jsonOptions} value={selected} onChange={this.onSelectChanged} />
|
||||
<Select
|
||||
inputId="select-source-dropdown"
|
||||
options={jsonOptions}
|
||||
value={selected}
|
||||
onChange={this.onSelectChanged}
|
||||
menuShouldPortal
|
||||
/>
|
||||
</Field>
|
||||
{this.hasPanelJSON && isPanelJSON && canEdit && (
|
||||
<Button className={styles.toolbarItem} onClick={this.onApplyPanelModel}>
|
||||
|
@ -2,6 +2,7 @@ import React, { PropsWithChildren, ReactElement } from 'react';
|
||||
import { InlineFormLabel, Select, useStyles } from '@grafana/ui';
|
||||
import { GrafanaTheme, SelectableValue } from '@grafana/data';
|
||||
import { css } from '@emotion/css';
|
||||
import { useUniqueId } from 'app/plugins/datasource/influxdb/components/useUniqueId';
|
||||
|
||||
interface VariableSelectFieldProps<T> {
|
||||
name: string;
|
||||
@ -25,7 +26,8 @@ export function VariableSelectField({
|
||||
labelWidth,
|
||||
}: PropsWithChildren<VariableSelectFieldProps<any>>): ReactElement {
|
||||
const styles = useStyles(getStyles);
|
||||
const inputId = `variable-select-input-${name}`;
|
||||
const uniqueId = useUniqueId();
|
||||
const inputId = `variable-select-input-${name}-${uniqueId}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { ChangeEvent, PropsWithChildren, ReactElement } from 'react';
|
||||
import { InlineField, InlineSwitch } from '@grafana/ui';
|
||||
import { useUniqueId } from 'app/plugins/datasource/influxdb/components/useUniqueId';
|
||||
interface VariableSwitchFieldProps {
|
||||
value: boolean;
|
||||
name: string;
|
||||
@ -15,9 +16,16 @@ export function VariableSwitchField({
|
||||
onChange,
|
||||
ariaLabel,
|
||||
}: PropsWithChildren<VariableSwitchFieldProps>): ReactElement {
|
||||
const uniqueId = useUniqueId();
|
||||
return (
|
||||
<InlineField label={name} labelWidth={20} tooltip={tooltip}>
|
||||
<InlineSwitch label={name} value={value} onChange={onChange} aria-label={ariaLabel} />
|
||||
<InlineSwitch
|
||||
id={`var-switch-${uniqueId}`}
|
||||
label={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
aria-label={ariaLabel}
|
||||
/>
|
||||
</InlineField>
|
||||
);
|
||||
}
|
||||
|
@ -22,9 +22,10 @@
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label width-6">Scale</label>
|
||||
<label for="yaxis-scale-select-{{$index}}" class="gf-form-label width-6">Scale</label>
|
||||
<div class="gf-form-select-wrapper max-width-20">
|
||||
<select
|
||||
id="yaxis-scale-select-{{$index}}"
|
||||
class="gf-form-input"
|
||||
ng-model="yaxis.logBase"
|
||||
ng-options="v as k for (k, v) in ctrl.logScales"
|
||||
@ -75,8 +76,9 @@
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label width-6">Label</label>
|
||||
<label for="yaxis-label-select-{{$index}}" class="gf-form-label width-6">Label</label>
|
||||
<input
|
||||
id="yaxis-label-select-{{$index}}"
|
||||
type="text"
|
||||
class="gf-form-input max-width-20"
|
||||
ng-model="yaxis.label"
|
||||
@ -125,15 +127,15 @@
|
||||
></gf-form-switch>
|
||||
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label width-6">Mode</label>
|
||||
<label for="xaxis-mode-select" class="gf-form-label width-6">Mode</label>
|
||||
<div class="gf-form-select-wrapper max-width-15">
|
||||
<select
|
||||
id="xaxis-mode-select"
|
||||
class="gf-form-input"
|
||||
ng-model="ctrl.panel.xaxis.mode"
|
||||
ng-options="v as k for (k, v) in ctrl.xAxisModes"
|
||||
ng-change="ctrl.xAxisModeChanged()"
|
||||
>
|
||||
</select>
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -101,7 +101,7 @@ $text-color-strong: #fff;
|
||||
$text-color: rgb(204, 204, 220);
|
||||
$text-color-semi-weak: rgba(204, 204, 220, 0.65);
|
||||
$text-color-weak: rgba(204, 204, 220, 0.65);
|
||||
$text-color-faint: rgba(204, 204, 220, 0.57);
|
||||
$text-color-faint: rgba(204, 204, 220, 0.58);
|
||||
$text-color-emphasis: #fff;
|
||||
$text-blue: #6E9FFF;
|
||||
|
||||
@ -115,7 +115,7 @@ $brand-gradient-vertical: linear-gradient(#f05a28 30%, #fbca0a 99%);
|
||||
// Links
|
||||
// -------------------------
|
||||
$link-color: rgb(204, 204, 220);
|
||||
$link-color-disabled: rgba(204, 204, 220, 0.57);
|
||||
$link-color-disabled: rgba(204, 204, 220, 0.58);
|
||||
$link-hover-color: #fff;
|
||||
$external-link-color: #6E9FFF;
|
||||
|
||||
@ -216,7 +216,7 @@ $input-border-color: rgba(204, 204, 220, 0.15);
|
||||
$input-box-shadow: none;
|
||||
$input-border-focus: #6E9FFF;
|
||||
$input-box-shadow-focus: #6E9FFF !default;
|
||||
$input-color-placeholder: rgba(204, 204, 220, 0.57);
|
||||
$input-color-placeholder: rgba(204, 204, 220, 0.58);
|
||||
$input-label-bg: #22252b;
|
||||
$input-color-select-arrow: $white;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user