From 00bede823f7e2060fac4dde675489ba10d0a9b37 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Tue, 8 Nov 2022 18:11:34 +0100 Subject: [PATCH] Tooltips: Make tooltips in FormField and FormLabel interactive and keyboard friendly (#57706) (#58471) * 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 (cherry picked from commit 3e92a2dc7725677336534eae4008be6a679ed44b) Co-authored-by: Adam Simpson --- .../components/FormField/FormField.test.tsx | 19 ++++++++++++++++++- .../src/components/FormField/FormField.tsx | 5 ++++- .../src/components/FormLabel/FormLabel.tsx | 9 +++++---- .../SecretFormField/SecretFormField.tsx | 3 +++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/grafana-ui/src/components/FormField/FormField.test.tsx b/packages/grafana-ui/src/components/FormField/FormField.test.tsx index ac95d812c75..55b2f6996c8 100644 --- a/packages/grafana-ui/src/components/FormField/FormField.test.tsx +++ b/packages/grafana-ui/src/components/FormField/FormField.test.tsx @@ -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); + }); + }); }); diff --git a/packages/grafana-ui/src/components/FormField/FormField.tsx b/packages/grafana-ui/src/components/FormField/FormField.tsx index b15b54c3e1a..b341cfaa206 100644 --- a/packages/grafana-ui/src/components/FormField/FormField.tsx +++ b/packages/grafana-ui/src/components/FormField/FormField.tsx @@ -11,6 +11,8 @@ export interface Props extends InputHTMLAttributes { // 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 = ({ inputWidth, inputEl, className, + interactive, ...inputProps }) => { const styles = getStyles(); return (
- + {label} {inputEl || ( diff --git a/packages/grafana-ui/src/components/FormLabel/FormLabel.tsx b/packages/grafana-ui/src/components/FormLabel/FormLabel.tsx index ae6c1c46466..c01047df2ff 100644 --- a/packages/grafana-ui/src/components/FormLabel/FormLabel.tsx +++ b/packages/grafana-ui/src/components/FormLabel/FormLabel.tsx @@ -12,6 +12,8 @@ interface Props { isInvalid?: boolean; tooltip?: PopoverContent; width?: number | 'auto'; + /** Make tooltip interactive */ + interactive?: boolean; } export const FormLabel: FunctionComponent = ({ @@ -22,6 +24,7 @@ export const FormLabel: FunctionComponent = ({ htmlFor, tooltip, width, + interactive, ...rest }) => { const classes = classNames(className, `gf-form-label width-${width ? width : '10'}`, { @@ -33,10 +36,8 @@ export const FormLabel: FunctionComponent = ({ diff --git a/packages/grafana-ui/src/components/SecretFormField/SecretFormField.tsx b/packages/grafana-ui/src/components/SecretFormField/SecretFormField.tsx index 27da639c5ff..6eb08850410 100644 --- a/packages/grafana-ui/src/components/SecretFormField/SecretFormField.tsx +++ b/packages/grafana-ui/src/components/SecretFormField/SecretFormField.tsx @@ -18,6 +18,7 @@ export interface Props extends Omit, '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 = ({ isConfigured, tooltip, placeholder = 'Password', + interactive, ...inputProps }: Props) => { const styles = getSecretFormFieldStyles(); @@ -53,6 +55,7 @@ export const SecretFormField: FunctionComponent = ({