1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
import { type FC, type MouseEventHandler, useRef } from 'react';
import { useIntl } from 'react-intl';
import { useOnClickOutside } from '../../../../utils/hooks';
import { Heading, Icon } from '../../../atoms';
import { HelpButton } from '../../buttons';
import { Modal, type ModalProps } from '../modal';
import styles from './tooltip.module.scss';
export type TooltipProps = Omit<ModalProps, 'heading'> & {
/**
* The tooltip direction when opening.
*
* @default "downwards"
*/
direction?: 'downwards' | 'upwards';
/**
* The tooltip heading.
*/
heading: string;
/**
* Should the tooltip be opened?
*
* @default false
*/
isOpen?: boolean;
/**
* A callback function to trigger when clicking outside the modal.
*/
onClickOutside?: () => void;
/**
* An event handler when clicking on the help button.
*/
onToggle?: MouseEventHandler<HTMLButtonElement>;
};
/**
* Tooltip component
*
* Render a button and a modal. Note: you should add a CSS rule
* `position: relative;` on the consumer.
*/
export const Tooltip: FC<TooltipProps> = ({
children,
className = '',
direction = 'downwards',
heading,
isOpen,
onClickOutside,
onToggle,
...props
}) => {
const intl = useIntl();
const helpLabel = intl.formatMessage({
defaultMessage: 'Show help',
description: 'Tooltip: show help label',
id: '1Xgg7+',
});
const directionModifier =
direction === 'upwards' ? 'tooltip--up' : 'tooltip--down';
const visibilityModifier = isOpen ? 'tooltip--visible' : 'tooltip--hidden';
const tooltipClass = `${styles.tooltip} ${styles[directionModifier]} ${styles[visibilityModifier]} ${className}`;
const btnRef = useRef<HTMLButtonElement>(null);
const closeModal = ({ target }: MouseEvent | FocusEvent) => {
if (
onClickOutside &&
btnRef.current &&
!btnRef.current.contains(target as Node)
) {
onClickOutside();
}
};
const modalRef = useOnClickOutside<HTMLDivElement>(closeModal);
return (
<>
<Modal
{...props}
className={tooltipClass}
heading={
<Heading className={styles.heading} isFake level={6}>
{heading}
</Heading>
}
icon={<Icon aria-hidden shape="help" size="sm" />}
kind="secondary"
ref={modalRef}
>
{children}
</Modal>
<HelpButton
className={styles.btn}
isPressed={isOpen}
label={helpLabel}
onClick={onToggle}
ref={btnRef}
/>
</>
);
};
|