Tooltips: Make tooltips in FormField and FormLabel interactive and keyboard friendly (#57706)

* Tooltips: add tabindex and interactive

A couple tooltips used in configuration of datasources like ADX were not
clickable or didn't show on keyboard focus.

- fixes #56561
- Same solution as #47137

* test: add test around tabbing to tooltips
This commit is contained in:
Adam Simpson 2022-11-08 11:55:53 -05:00 committed by GitHub
parent 43a0afeac4
commit 3e92a2dc77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 6 deletions

View File

@ -1,4 +1,5 @@
import { render, screen } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { FormField, Props } from './FormField';
@ -29,4 +30,20 @@ describe('FormField', () => {
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
expect(screen.getByRole('checkbox')).toBeInTheDocument();
});
it('tooltips should be focusable via Tab key', async () => {
const tooltip = 'Test tooltip';
setup();
setup({
tooltip,
});
//focus the first input
screen.getAllByRole('textbox')[0].focus();
await userEvent.tab();
await waitFor(() => {
screen.getByText(tooltip);
});
});
});

View File

@ -11,6 +11,8 @@ export interface Props extends InputHTMLAttributes<HTMLInputElement> {
// If null no width will be specified not even default one
inputWidth?: number | null;
inputEl?: React.ReactNode;
/** Make tooltip interactive */
interactive?: boolean;
}
const defaultProps = {
@ -29,12 +31,13 @@ export const FormField: FunctionComponent<Props> = ({
inputWidth,
inputEl,
className,
interactive,
...inputProps
}) => {
const styles = getStyles();
return (
<div className={cx(styles.formField, className)}>
<InlineFormLabel width={labelWidth} tooltip={tooltip}>
<InlineFormLabel width={labelWidth} tooltip={tooltip} interactive={interactive}>
{label}
</InlineFormLabel>
{inputEl || (

View File

@ -12,6 +12,8 @@ interface Props {
isInvalid?: boolean;
tooltip?: PopoverContent;
width?: number | 'auto';
/** Make tooltip interactive */
interactive?: boolean;
}
export const FormLabel: FunctionComponent<Props> = ({
@ -22,6 +24,7 @@ export const FormLabel: FunctionComponent<Props> = ({
htmlFor,
tooltip,
width,
interactive,
...rest
}) => {
const classes = classNames(className, `gf-form-label width-${width ? width : '10'}`, {
@ -33,10 +36,8 @@ export const FormLabel: FunctionComponent<Props> = ({
<label className={classes} {...rest} htmlFor={htmlFor}>
{children}
{tooltip && (
<Tooltip placement="top" content={tooltip} theme={'info'}>
<div className="gf-form-help-icon gf-form-help-icon--right-normal">
<Icon name="info-circle" size="sm" style={{ marginLeft: '10px' }} />
</div>
<Tooltip placement="top" content={tooltip} theme={'info'} interactive={interactive}>
<Icon tabIndex={0} name="info-circle" size="sm" style={{ marginLeft: '10px' }} />
</Tooltip>
)}
</label>

View File

@ -18,6 +18,7 @@ export interface Props extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onRe
inputWidth?: number;
// Placeholder of the input field when in non configured state.
placeholder?: string;
interactive?: boolean;
}
const getSecretFormFieldStyles = () => {
@ -46,6 +47,7 @@ export const SecretFormField: FunctionComponent<Props> = ({
isConfigured,
tooltip,
placeholder = 'Password',
interactive,
...inputProps
}: Props) => {
const styles = getSecretFormFieldStyles();
@ -53,6 +55,7 @@ export const SecretFormField: FunctionComponent<Props> = ({
<FormField
label={label!}
tooltip={tooltip}
interactive={interactive}
labelWidth={labelWidth}
inputEl={
isConfigured ? (