Make tooltips keyboard accessible (#7281)
* show tooltips on hover in eventtile Signed-off-by: Kerry Archibald <kerrya@element.io> * use tooltip props pass thru * use tooltiptarget in InfoTooltip Signed-off-by: Kerry Archibald <kerrya@element.io> * use target in TestWithTooltip Signed-off-by: Kerry Archibald <kerrya@element.io> * tsc fixes Signed-off-by: Kerry Archibald <kerrya@element.io> * test tooltip target Signed-off-by: Kerry Archibald <kerrya@element.io> * lint fix Signed-off-by: Kerry Archibald <kerrya@element.io> * rename tooltip handlers Signed-off-by: Kerry Archibald <kerrya@element.io> * update copyright to 2021 Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
4712ae49b2
commit
0c850b2f13
11 changed files with 242 additions and 98 deletions
|
@ -13,6 +13,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
.mx_TextWithTooltip_target {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_TextWithTooltip_tooltip {
|
.mx_TextWithTooltip_tooltip {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -52,14 +52,14 @@ export default class AccessibleTooltipButton extends React.PureComponent<IToolti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseOver = () => {
|
showTooltip = () => {
|
||||||
if (this.props.forceHide) return;
|
if (this.props.forceHide) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
hover: true,
|
hover: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMouseLeave = () => {
|
hideTooltip = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
hover: false,
|
hover: false,
|
||||||
});
|
});
|
||||||
|
@ -78,8 +78,10 @@ export default class AccessibleTooltipButton extends React.PureComponent<IToolti
|
||||||
return (
|
return (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
{...props}
|
{...props}
|
||||||
onMouseOver={this.onMouseOver}
|
onMouseOver={this.showTooltip}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.hideTooltip}
|
||||||
|
onFocus={this.showTooltip}
|
||||||
|
onBlur={this.hideTooltip}
|
||||||
aria-label={title}
|
aria-label={title}
|
||||||
>
|
>
|
||||||
{ children }
|
{ children }
|
||||||
|
|
|
@ -58,13 +58,17 @@ export default class ActionButton extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private onMouseEnter = (): void => {
|
private onMouseEnter = (): void => {
|
||||||
if (this.props.tooltip) this.setState({ showTooltip: true });
|
this.showTooltip();
|
||||||
if (this.props.mouseOverAction) {
|
if (this.props.mouseOverAction) {
|
||||||
dis.dispatch({ action: this.props.mouseOverAction });
|
dis.dispatch({ action: this.props.mouseOverAction });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onMouseLeave = (): void => {
|
private showTooltip = (): void => {
|
||||||
|
if (this.props.tooltip) this.setState({ showTooltip: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
private hideTooltip = (): void => {
|
||||||
this.setState({ showTooltip: false });
|
this.setState({ showTooltip: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,7 +92,9 @@ export default class ActionButton extends React.Component<IProps, IState> {
|
||||||
className={classNames.join(" ")}
|
className={classNames.join(" ")}
|
||||||
onClick={this.onClick}
|
onClick={this.onClick}
|
||||||
onMouseEnter={this.onMouseEnter}
|
onMouseEnter={this.onMouseEnter}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.hideTooltip}
|
||||||
|
onFocus={this.showTooltip}
|
||||||
|
onBlur={this.hideTooltip}
|
||||||
aria-label={this.props.label}
|
aria-label={this.props.label}
|
||||||
>
|
>
|
||||||
{ icon }
|
{ icon }
|
||||||
|
|
|
@ -18,9 +18,10 @@ limitations under the License.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import Tooltip, { Alignment } from './Tooltip';
|
import { Alignment } from './Tooltip';
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
import { TooltipTarget } from './TooltipTarget';
|
||||||
|
|
||||||
export enum InfoTooltipKind {
|
export enum InfoTooltipKind {
|
||||||
Info = "info",
|
Info = "info",
|
||||||
|
@ -34,31 +35,12 @@ interface ITooltipProps {
|
||||||
kind?: InfoTooltipKind;
|
kind?: InfoTooltipKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
|
||||||
hover: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@replaceableComponent("views.elements.InfoTooltip")
|
@replaceableComponent("views.elements.InfoTooltip")
|
||||||
export default class InfoTooltip extends React.PureComponent<ITooltipProps, IState> {
|
export default class InfoTooltip extends React.PureComponent<ITooltipProps> {
|
||||||
constructor(props: ITooltipProps) {
|
constructor(props: ITooltipProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
|
||||||
hover: false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseOver = () => {
|
|
||||||
this.setState({
|
|
||||||
hover: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMouseLeave = () => {
|
|
||||||
this.setState({
|
|
||||||
hover: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { tooltip, children, tooltipClassName, className, kind } = this.props;
|
const { tooltip, children, tooltipClassName, className, kind } = this.props;
|
||||||
const title = _t("Information");
|
const title = _t("Information");
|
||||||
|
@ -68,22 +50,16 @@ export default class InfoTooltip extends React.PureComponent<ITooltipProps, ISta
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tooltip are forced on the right for a more natural feel to them on info icons
|
// Tooltip are forced on the right for a more natural feel to them on info icons
|
||||||
const tip = this.state.hover ? <Tooltip
|
|
||||||
className="mx_InfoTooltip_container"
|
|
||||||
tooltipClassName={classNames("mx_InfoTooltip_tooltip", tooltipClassName)}
|
|
||||||
label={tooltip || title}
|
|
||||||
alignment={Alignment.Right}
|
|
||||||
/> : <div />;
|
|
||||||
return (
|
return (
|
||||||
<div
|
<TooltipTarget tooltipTargetClassName={classNames("mx_InfoTooltip", className)}
|
||||||
onMouseOver={this.onMouseOver}
|
className="mx_InfoTooltip_container"
|
||||||
onMouseLeave={this.onMouseLeave}
|
tooltipClassName={classNames("mx_InfoTooltip_tooltip", tooltipClassName)}
|
||||||
className={classNames("mx_InfoTooltip", className)}
|
label={tooltip || title}
|
||||||
|
alignment={Alignment.Right}
|
||||||
>
|
>
|
||||||
<span className={classNames("mx_InfoTooltip_icon", iconClassName)} aria-label={title} />
|
<span className={classNames("mx_InfoTooltip_icon", iconClassName)} aria-label={title} />
|
||||||
{ children }
|
{ children }
|
||||||
{ tip }
|
</TooltipTarget>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import Tooltip from "./Tooltip";
|
import { TooltipTarget } from './TooltipTarget';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
class?: string;
|
class?: string;
|
||||||
|
@ -26,41 +27,27 @@ interface IProps {
|
||||||
onClick?: (ev?: React.MouseEvent) => void;
|
onClick?: (ev?: React.MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
|
||||||
hover: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@replaceableComponent("views.elements.TextWithTooltip")
|
@replaceableComponent("views.elements.TextWithTooltip")
|
||||||
export default class TextWithTooltip extends React.Component<IProps, IState> {
|
export default class TextWithTooltip extends React.Component<IProps> {
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
|
||||||
hover: false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMouseOver = (): void => {
|
|
||||||
this.setState({ hover: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
private onMouseLeave = (): void => {
|
|
||||||
this.setState({ hover: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
const { class: className, children, tooltip, tooltipClass, tooltipProps, ...props } = this.props;
|
const { class: className, children, tooltip, tooltipClass, tooltipProps, ...props } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span {...props} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} onClick={this.props.onClick} className={className}>
|
<TooltipTarget
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
tooltipTargetClassName={classNames("mx_TextWithTooltip_target", className)}
|
||||||
|
{...tooltipProps}
|
||||||
|
label={tooltip}
|
||||||
|
tooltipClassName={tooltipClass}
|
||||||
|
className="mx_TextWithTooltip_tooltip"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
{ children }
|
{ children }
|
||||||
{ this.state.hover && <Tooltip
|
</TooltipTarget>
|
||||||
{...tooltipProps}
|
|
||||||
label={tooltip}
|
|
||||||
tooltipClassName={tooltipClass}
|
|
||||||
className="mx_TextWithTooltip_tooltip"
|
|
||||||
/> }
|
|
||||||
</span>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ export enum Alignment {
|
||||||
Bottom, // Centered
|
Bottom, // Centered
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
export interface ITooltipProps {
|
||||||
// Class applied to the element used to position the tooltip
|
// Class applied to the element used to position the tooltip
|
||||||
className?: string;
|
className?: string;
|
||||||
// Class applied to the tooltip itself
|
// Class applied to the tooltip itself
|
||||||
|
@ -46,10 +46,13 @@ interface IProps {
|
||||||
label: React.ReactNode;
|
label: React.ReactNode;
|
||||||
alignment?: Alignment; // defaults to Natural
|
alignment?: Alignment; // defaults to Natural
|
||||||
yOffset?: number;
|
yOffset?: number;
|
||||||
|
// id describing tooltip
|
||||||
|
// used to associate tooltip with target for a11y
|
||||||
|
id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.elements.Tooltip")
|
@replaceableComponent("views.elements.Tooltip")
|
||||||
export default class Tooltip extends React.Component<IProps> {
|
export default class Tooltip extends React.Component<ITooltipProps> {
|
||||||
private tooltipContainer: HTMLElement;
|
private tooltipContainer: HTMLElement;
|
||||||
private tooltip: void | Element | Component<Element, any, any>;
|
private tooltip: void | Element | Component<Element, any, any>;
|
||||||
private parent: Element;
|
private parent: Element;
|
||||||
|
|
|
@ -17,48 +17,28 @@ limitations under the License.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import Tooltip from './Tooltip';
|
import { TooltipTarget } from './TooltipTarget';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
helpText: React.ReactNode | string;
|
helpText: React.ReactNode | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
|
||||||
hover: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@replaceableComponent("views.elements.TooltipButton")
|
@replaceableComponent("views.elements.TooltipButton")
|
||||||
export default class TooltipButton extends React.Component<IProps, IState> {
|
export default class TooltipButton extends React.Component<IProps> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
|
||||||
hover: false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMouseOver = () => {
|
|
||||||
this.setState({
|
|
||||||
hover: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
private onMouseLeave = () => {
|
|
||||||
this.setState({
|
|
||||||
hover: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const tip = this.state.hover ? <Tooltip
|
|
||||||
className="mx_TooltipButton_container"
|
|
||||||
tooltipClassName="mx_TooltipButton_helpText"
|
|
||||||
label={this.props.helpText}
|
|
||||||
/> : <div />;
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_TooltipButton" onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave}>
|
<TooltipTarget
|
||||||
|
className="mx_TooltipButton_container"
|
||||||
|
tooltipClassName="mx_TooltipButton_helpText"
|
||||||
|
tooltipTargetClassName="mx_TooltipButton"
|
||||||
|
label={this.props.helpText}
|
||||||
|
>
|
||||||
?
|
?
|
||||||
{ tip }
|
</TooltipTarget>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
68
src/components/views/elements/TooltipTarget.tsx
Normal file
68
src/components/views/elements/TooltipTarget.tsx
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useState, HTMLAttributes } from 'react';
|
||||||
|
import Tooltip, { ITooltipProps } from './Tooltip';
|
||||||
|
|
||||||
|
interface IProps extends HTMLAttributes<HTMLSpanElement>, Omit<ITooltipProps, 'visible'> {
|
||||||
|
tooltipTargetClassName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic tooltip target element that handles tooltip visibility state
|
||||||
|
* and displays children
|
||||||
|
*/
|
||||||
|
export const TooltipTarget: React.FC<IProps> = ({
|
||||||
|
children,
|
||||||
|
tooltipTargetClassName,
|
||||||
|
// tooltip pass through props
|
||||||
|
className,
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
alignment,
|
||||||
|
yOffset,
|
||||||
|
tooltipClassName,
|
||||||
|
...rest
|
||||||
|
}) => {
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
||||||
|
const show = () => setIsVisible(true);
|
||||||
|
const hide = () => setIsVisible(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
tabIndex={0}
|
||||||
|
aria-describedby={id}
|
||||||
|
className={tooltipTargetClassName}
|
||||||
|
onMouseOver={show}
|
||||||
|
onMouseLeave={hide}
|
||||||
|
onFocus={show}
|
||||||
|
onBlur={hide}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{ children }
|
||||||
|
<Tooltip
|
||||||
|
id={id}
|
||||||
|
className={className}
|
||||||
|
tooltipClassName={tooltipClassName}
|
||||||
|
label={label}
|
||||||
|
yOffset={yOffset}
|
||||||
|
alignment={alignment}
|
||||||
|
visible={isVisible}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1203,7 +1203,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
_t(
|
_t(
|
||||||
'<requestLink>Re-request encryption keys</requestLink> from your other sessions.',
|
'<requestLink>Re-request encryption keys</requestLink> from your other sessions.',
|
||||||
{},
|
{},
|
||||||
{ 'requestLink': (sub) => <a onClick={this.onRequestKeysClick}>{ sub }</a> },
|
{ 'requestLink': (sub) => <a tabIndex={0} onClick={this.onRequestKeysClick}>{ sub }</a> },
|
||||||
);
|
);
|
||||||
|
|
||||||
const keyRequestInfo = isEncryptionFailure && !isRedacted ?
|
const keyRequestInfo = isEncryptionFailure && !isRedacted ?
|
||||||
|
|
90
test/components/views/elements/TooltipTarget-test.tsx
Normal file
90
test/components/views/elements/TooltipTarget-test.tsx
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// skinned-sdk should be the first import in most tests
|
||||||
|
import '../../../skinned-sdk';
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
renderIntoDocument,
|
||||||
|
Simulate,
|
||||||
|
} from 'react-dom/test-utils';
|
||||||
|
import { act } from "react-dom/test-utils";
|
||||||
|
|
||||||
|
import { Alignment } from '../../../../src/components/views/elements/Tooltip';
|
||||||
|
import { TooltipTarget } from "../../../../src/components/views/elements/TooltipTarget";
|
||||||
|
|
||||||
|
describe('<TooltipTarget />', () => {
|
||||||
|
const defaultProps = {
|
||||||
|
"tooltipTargetClassName": 'test tooltipTargetClassName',
|
||||||
|
"className": 'test className',
|
||||||
|
"tooltipClassName": 'test tooltipClassName',
|
||||||
|
"label": 'test label',
|
||||||
|
"yOffset": 1,
|
||||||
|
"alignment": Alignment.Left,
|
||||||
|
"id": 'test id',
|
||||||
|
'data-test-id': 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const getComponent = (props = {}) => {
|
||||||
|
const wrapper = renderIntoDocument<HTMLSpanElement>(
|
||||||
|
// wrap in element so renderIntoDocument can render functional component
|
||||||
|
<span>
|
||||||
|
<TooltipTarget {...defaultProps} {...props}>
|
||||||
|
<span>child</span>
|
||||||
|
</TooltipTarget>
|
||||||
|
</span>,
|
||||||
|
) as HTMLSpanElement;
|
||||||
|
return wrapper.querySelector('[data-test-id=test]');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getVisibleTooltip = () => document.querySelector('.mx_Tooltip.mx_Tooltip_visible');
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// clean up visible tooltips
|
||||||
|
const tooltipWrapper = document.querySelector('.mx_Tooltip_wrapper');
|
||||||
|
document.body.removeChild(tooltipWrapper);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders container', () => {
|
||||||
|
const component = getComponent();
|
||||||
|
expect(component).toMatchSnapshot();
|
||||||
|
expect(getVisibleTooltip()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays tooltip on mouseover', () => {
|
||||||
|
const wrapper = getComponent();
|
||||||
|
act(() => {
|
||||||
|
Simulate.mouseOver(wrapper);
|
||||||
|
});
|
||||||
|
expect(getVisibleTooltip()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides tooltip on mouseleave', () => {
|
||||||
|
const wrapper = getComponent();
|
||||||
|
act(() => {
|
||||||
|
Simulate.mouseOver(wrapper);
|
||||||
|
});
|
||||||
|
expect(getVisibleTooltip()).toBeTruthy();
|
||||||
|
act(() => {
|
||||||
|
Simulate.mouseLeave(wrapper);
|
||||||
|
});
|
||||||
|
expect(getVisibleTooltip()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays tooltip on focus', () => {
|
||||||
|
const wrapper = getComponent();
|
||||||
|
act(() => {
|
||||||
|
Simulate.focus(wrapper);
|
||||||
|
});
|
||||||
|
expect(getVisibleTooltip()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides tooltip on blur', async () => {
|
||||||
|
const wrapper = getComponent();
|
||||||
|
act(() => {
|
||||||
|
Simulate.focus(wrapper);
|
||||||
|
});
|
||||||
|
expect(getVisibleTooltip()).toBeTruthy();
|
||||||
|
await act(async () => {
|
||||||
|
await Simulate.blur(wrapper);
|
||||||
|
});
|
||||||
|
expect(getVisibleTooltip()).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<TooltipTarget /> displays tooltip on mouseover 1`] = `
|
||||||
|
<div
|
||||||
|
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
||||||
|
style="right: 1008px; top: -26px; display: block;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Tooltip_chevron"
|
||||||
|
/>
|
||||||
|
test label
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<TooltipTarget /> renders container 1`] = `
|
||||||
|
<div
|
||||||
|
aria-describedby="test id"
|
||||||
|
class="test tooltipTargetClassName"
|
||||||
|
data-test-id="test"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
child
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
class="test className"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`;
|
Loading…
Add table
Add a link
Reference in a new issue