mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
A11y/Dashboard: Fix misc. fastpass issues (#40296)
* A11y/Dashboard: Fix misc. fastpass issues See #39429
This commit is contained in:
@@ -39,6 +39,7 @@ export interface SliderFieldConfigSettings {
|
||||
min: number;
|
||||
max: number;
|
||||
step?: number;
|
||||
ariaLabelForHandle?: string;
|
||||
}
|
||||
|
||||
export interface DataLinksFieldConfigSettings {}
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface StandardEditorProps<TValue = any, TSettings = any, TOptions = a
|
||||
onChange: (value?: TValue) => void;
|
||||
item: StandardEditorsRegistryItem<TValue, TSettings>;
|
||||
context: StandardEditorContext<TOptions, TState>;
|
||||
id?: string;
|
||||
}
|
||||
export interface StandardEditorsRegistryItem<TValue = any, TSettings = any> extends RegistryItem {
|
||||
editor: ComponentType<StandardEditorProps<TValue, TSettings>>;
|
||||
|
||||
@@ -17,6 +17,8 @@ export interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
tooltip?: string;
|
||||
/** For image icons */
|
||||
imgSrc?: string;
|
||||
/** Alt text for imgSrc */
|
||||
imgAlt?: string;
|
||||
/** if true or false will show angle-down/up */
|
||||
isOpen?: boolean;
|
||||
/** Controls flex-grow: 1 */
|
||||
@@ -39,6 +41,7 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
||||
className,
|
||||
children,
|
||||
imgSrc,
|
||||
imgAlt,
|
||||
fullWidth,
|
||||
isOpen,
|
||||
narrow,
|
||||
@@ -72,12 +75,12 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
||||
<button
|
||||
ref={ref}
|
||||
className={buttonStyles}
|
||||
aria-label={getButttonAriaLabel(ariaLabel, tooltip)}
|
||||
aria-label={getButtonAriaLabel(ariaLabel, tooltip)}
|
||||
aria-expanded={isOpen}
|
||||
{...rest}
|
||||
>
|
||||
{renderIcon(icon)}
|
||||
{imgSrc && <img className={styles.img} src={imgSrc} />}
|
||||
{imgSrc && <img className={styles.img} src={imgSrc} alt={imgAlt ?? ''} />}
|
||||
{children && !iconOnly && <div className={contentStyles}>{children}</div>}
|
||||
{isOpen === false && <Icon name="angle-down" />}
|
||||
{isOpen === true && <Icon name="angle-up" />}
|
||||
@@ -94,7 +97,7 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
||||
}
|
||||
);
|
||||
|
||||
function getButttonAriaLabel(ariaLabel: string | undefined, tooltip: string | undefined) {
|
||||
function getButtonAriaLabel(ariaLabel: string | undefined, tooltip: string | undefined) {
|
||||
return ariaLabel ? ariaLabel : tooltip ? selectors.components.PageToolbar.item(tooltip) : undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
||||
value,
|
||||
onChange,
|
||||
item,
|
||||
id,
|
||||
}) => {
|
||||
const theme = useTheme2();
|
||||
const styles = useStyles2(getStyles);
|
||||
@@ -81,6 +82,7 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
||||
value={mode}
|
||||
onChange={onModeChange}
|
||||
className={styles.select}
|
||||
inputId={id}
|
||||
/>
|
||||
<ColorValueEditor value={value?.fixedColor} onChange={onColorChange} />
|
||||
</div>
|
||||
@@ -97,7 +99,14 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
||||
return (
|
||||
<>
|
||||
<div style={{ marginBottom: theme.spacing(2) }}>
|
||||
<Select menuShouldPortal minMenuHeight={200} options={options} value={mode} onChange={onModeChange} />
|
||||
<Select
|
||||
menuShouldPortal
|
||||
minMenuHeight={200}
|
||||
options={options}
|
||||
value={mode}
|
||||
onChange={onModeChange}
|
||||
inputId={id}
|
||||
/>
|
||||
</div>
|
||||
<Field label="Color series by">
|
||||
<RadioButtonGroup value={value?.seriesBy ?? 'last'} options={seriesModes} onChange={onSeriesModeChange} />
|
||||
@@ -106,7 +115,9 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
||||
);
|
||||
}
|
||||
|
||||
return <Select menuShouldPortal minMenuHeight={200} options={options} value={mode} onChange={onModeChange} />;
|
||||
return (
|
||||
<Select menuShouldPortal minMenuHeight={200} options={options} value={mode} onChange={onModeChange} inputId={id} />
|
||||
);
|
||||
};
|
||||
|
||||
interface ModeProps {
|
||||
|
||||
@@ -17,6 +17,7 @@ export const SliderValueEditor: React.FC<FieldConfigEditorProps<number, SliderFi
|
||||
max={settings?.max || 100}
|
||||
step={settings?.step}
|
||||
onChange={onChange}
|
||||
ariaLabelForHandle={settings?.ariaLabelForHandle}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ export const StatsPickerEditor: React.FC<FieldConfigEditorProps<string[], StatsP
|
||||
value,
|
||||
onChange,
|
||||
item,
|
||||
id,
|
||||
}) => {
|
||||
return (
|
||||
<StatsPicker
|
||||
@@ -13,6 +14,7 @@ export const StatsPickerEditor: React.FC<FieldConfigEditorProps<string[], StatsP
|
||||
onChange={onChange}
|
||||
allowMultiple={!!item.settings?.allowMultiple}
|
||||
defaultStat={item.settings?.defaultStat}
|
||||
inputId={id}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
||||
reverse,
|
||||
step,
|
||||
value,
|
||||
ariaLabelForHandle,
|
||||
}) => {
|
||||
const isHorizontal = orientation === 'horizontal';
|
||||
const theme = useTheme2();
|
||||
@@ -79,6 +80,7 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
||||
onAfterChange={onAfterChange}
|
||||
vertical={!isHorizontal}
|
||||
reverse={reverse}
|
||||
ariaLabelForHandle={ariaLabelForHandle}
|
||||
/>
|
||||
{/* Uses text input so that the number spinners are not shown */}
|
||||
<Input
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface SliderProps {
|
||||
formatTooltipResult?: (value: number) => number;
|
||||
onChange?: (value: number) => void;
|
||||
onAfterChange?: (value?: number) => void;
|
||||
ariaLabelForHandle?: string;
|
||||
}
|
||||
|
||||
export interface RangeSliderProps {
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface Props {
|
||||
className?: string;
|
||||
width?: number;
|
||||
menuPlacement?: 'auto' | 'bottom' | 'top';
|
||||
inputId?: string;
|
||||
}
|
||||
|
||||
export class StatsPicker extends PureComponent<Props> {
|
||||
@@ -63,7 +64,7 @@ export class StatsPicker extends PureComponent<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { stats, allowMultiple, defaultStat, placeholder, className, menuPlacement, width } = this.props;
|
||||
const { stats, allowMultiple, defaultStat, placeholder, className, menuPlacement, width, inputId } = this.props;
|
||||
|
||||
const select = fieldReducers.selectOptions(stats);
|
||||
return (
|
||||
@@ -79,6 +80,7 @@ export class StatsPicker extends PureComponent<Props> {
|
||||
placeholder={placeholder}
|
||||
onChange={this.onSelectionChange}
|
||||
menuPlacement={menuPlacement}
|
||||
inputId={inputId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -151,11 +151,13 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
|
||||
renderInput(threshold: ThresholdWithKey, styles: ThresholdStyles, idx: number) {
|
||||
const isPercent = this.props.thresholds.mode === ThresholdsMode.Percentage;
|
||||
|
||||
const ariaLabel = `Threshold ${idx + 1}`;
|
||||
if (!isFinite(threshold.value)) {
|
||||
return (
|
||||
<Input
|
||||
type="text"
|
||||
value={'Base'}
|
||||
aria-label={ariaLabel}
|
||||
disabled
|
||||
prefix={
|
||||
<div className={styles.colorPicker}>
|
||||
@@ -177,6 +179,7 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
|
||||
key={isPercent.toString()}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => this.onChangeThresholdValue(event, threshold)}
|
||||
value={threshold.value}
|
||||
aria-label={ariaLabel}
|
||||
ref={idx === 0 ? this.latestThresholdInputRef : null}
|
||||
onBlur={this.onBlur}
|
||||
prefix={
|
||||
|
||||
Reference in New Issue
Block a user