Skip to content

Commit d868bd9

Browse files
Allow tooltips to be focusable (#526)
* Allow tooltips to be focusable * Prevent multiple tooltips, add escape to close * Disabled tooltips are not focusable
1 parent 3bd481a commit d868bd9

File tree

4 files changed

+56
-12
lines changed

4 files changed

+56
-12
lines changed

src/components/ClickableTooltip.tsx

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,62 @@
11
import { Flex, Tooltip, TooltipProps, useDisclosure } from "@chakra-ui/react";
2-
import { ReactNode } from "react";
2+
import { ReactNode, useCallback, useRef } from "react";
33

44
interface ClickableTooltipProps extends TooltipProps {
55
children: ReactNode;
6+
isFocusable?: boolean;
67
}
78

89
// Chakra Tooltip doesn't support triggering on mobile/tablets:
910
// https://github.com/chakra-ui/chakra-ui/issues/2691
1011

11-
const ClickableTooltip = ({ children, ...rest }: ClickableTooltipProps) => {
12+
const ClickableTooltip = ({
13+
children,
14+
isFocusable = false,
15+
isDisabled,
16+
...rest
17+
}: ClickableTooltipProps) => {
1218
const label = useDisclosure();
19+
const ref = useRef<HTMLDivElement>(null);
20+
const handleMouseEnter = useCallback(() => {
21+
const openTooltips = document.querySelectorAll(
22+
'[role="tooltip"]:not([hidden])'
23+
);
24+
if (!openTooltips.length) {
25+
label.onOpen();
26+
}
27+
}, [label]);
28+
const handleMouseLeave = useCallback(() => {
29+
if (
30+
!isFocusable ||
31+
(ref.current !== document.activeElement && isFocusable)
32+
) {
33+
label.onClose();
34+
}
35+
}, [isFocusable, label]);
36+
const handleKeydown = useCallback(
37+
(e: React.KeyboardEvent<HTMLDivElement>) => {
38+
if (e.key === "Escape") {
39+
label.onClose();
40+
}
41+
},
42+
[label]
43+
);
1344
return (
14-
<Tooltip isOpen={label.isOpen} {...rest}>
45+
<Tooltip isOpen={label.isOpen} {...rest} closeOnEsc={true}>
1546
<Flex
16-
onMouseEnter={label.onOpen}
17-
onMouseLeave={label.onClose}
47+
onKeyDown={handleKeydown}
48+
ref={ref}
49+
onMouseEnter={handleMouseEnter}
50+
onMouseLeave={handleMouseLeave}
1851
onClick={label.onOpen}
52+
tabIndex={isDisabled ? undefined : 0}
53+
onFocus={isFocusable ? label.onOpen : undefined}
54+
onBlur={isFocusable ? label.onClose : undefined}
55+
_focusVisible={{
56+
boxShadow: "outline",
57+
outline: "none",
58+
}}
59+
borderRadius="50%"
1960
>
2061
{children}
2162
</Flex>

src/components/HeadingGrid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ const GridColumnHeadingItem = (props: GridColumnHeadingItemProps) => {
3535
<GridItem>
3636
{props.titleId && props.descriptionId && (
3737
<HStack justifyContent="space-between">
38-
<HStack opacity={0.7}>
39-
<Text>
38+
<HStack>
39+
<Text opacity={0.7}>
4040
<FormattedMessage id={props.titleId} />
4141
</Text>
4242
<InfoToolTip
4343
titleId={props.titleId}
4444
descriptionId={props.descriptionId}
45-
></InfoToolTip>
45+
/>
4646
</HStack>
4747
{props.itemsRight}
4848
</HStack>

src/components/InfoToolTip.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import { Icon, Text, VStack } from "@chakra-ui/react";
1+
import { Icon, Text, TooltipProps, VStack } from "@chakra-ui/react";
22
import { RiInformationLine } from "react-icons/ri";
33
import { FormattedMessage } from "react-intl";
44
import ClickableTooltip from "./ClickableTooltip";
55
import { useDeployment } from "../deployment";
66

7-
export interface InfoToolTipProps {
7+
export interface InfoToolTipProps extends Omit<TooltipProps, "children"> {
88
titleId: string;
99
descriptionId: string;
1010
}
11-
const InfoToolTip = ({ titleId, descriptionId }: InfoToolTipProps) => {
11+
const InfoToolTip = ({ titleId, descriptionId, ...rest }: InfoToolTipProps) => {
1212
const { appNameFull } = useDeployment();
1313
return (
1414
<ClickableTooltip
15+
isFocusable
1516
hasArrow
1617
placement="right"
18+
{...rest}
1719
label={
1820
<VStack textAlign="left" alignContent="left" alignItems="left" m={3}>
1921
<Text fontWeight="bold">
@@ -25,7 +27,7 @@ const InfoToolTip = ({ titleId, descriptionId }: InfoToolTipProps) => {
2527
</VStack>
2628
}
2729
>
28-
<Icon h={5} w={5} as={RiInformationLine} />
30+
<Icon opacity={0.7} h={5} w={5} as={RiInformationLine} />
2931
</ClickableTooltip>
3032
);
3133
};

src/components/LiveGraphPanel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ const LiveGraphPanel = ({
123123
<InfoToolTip
124124
titleId="live-graph"
125125
descriptionId="live-graph-tooltip"
126+
isDisabled={isDisconnected}
126127
/>
127128
</HStack>
128129
{isConnected && (

0 commit comments

Comments
 (0)