2022-01-20 21:03:54 +00:00
|
|
|
import React, { forwardRef, useRef } from "react";
|
2021-12-15 06:00:00 +00:00
|
|
|
import { useTooltipTriggerState } from "@react-stately/tooltip";
|
2022-01-20 21:03:54 +00:00
|
|
|
import { FocusableProvider } from "@react-aria/focus";
|
2021-12-15 06:00:00 +00:00
|
|
|
import { useTooltipTrigger, useTooltip } from "@react-aria/tooltip";
|
2021-12-23 22:40:23 +00:00
|
|
|
import { mergeProps, useObjectRef } from "@react-aria/utils";
|
2021-12-15 06:00:00 +00:00
|
|
|
import styles from "./Tooltip.module.css";
|
|
|
|
import classNames from "classnames";
|
2022-01-20 21:03:54 +00:00
|
|
|
import { OverlayContainer, useOverlayPosition } from "@react-aria/overlays";
|
2021-12-15 06:00:00 +00:00
|
|
|
|
2022-01-20 21:03:54 +00:00
|
|
|
export const Tooltip = forwardRef(
|
|
|
|
({ position, state, className, ...props }, ref) => {
|
|
|
|
let { tooltipProps } = useTooltip(props, state);
|
2021-12-15 06:00:00 +00:00
|
|
|
|
2022-01-20 21:03:54 +00:00
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={classNames(styles.tooltip, className)}
|
|
|
|
{...mergeProps(props, tooltipProps)}
|
|
|
|
ref={ref}
|
|
|
|
>
|
|
|
|
{props.children}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
2021-12-15 06:00:00 +00:00
|
|
|
|
|
|
|
export const TooltipTrigger = forwardRef(({ children, ...rest }, ref) => {
|
|
|
|
const tooltipState = useTooltipTriggerState(rest);
|
2021-12-23 22:40:23 +00:00
|
|
|
const triggerRef = useObjectRef(ref);
|
2022-01-20 21:03:54 +00:00
|
|
|
const overlayRef = useRef();
|
2021-12-15 06:00:00 +00:00
|
|
|
const { triggerProps, tooltipProps } = useTooltipTrigger(
|
|
|
|
rest,
|
|
|
|
tooltipState,
|
|
|
|
triggerRef
|
|
|
|
);
|
|
|
|
|
2022-01-20 21:03:54 +00:00
|
|
|
const { overlayProps } = useOverlayPosition({
|
|
|
|
placement: rest.placement || "top",
|
|
|
|
targetRef: triggerRef,
|
|
|
|
overlayRef,
|
|
|
|
isOpen: tooltipState.isOpen,
|
|
|
|
offset: 5,
|
|
|
|
});
|
|
|
|
|
2021-12-15 06:00:00 +00:00
|
|
|
if (
|
|
|
|
!Array.isArray(children) ||
|
|
|
|
children.length > 2 ||
|
|
|
|
typeof children[1] !== "function"
|
|
|
|
) {
|
|
|
|
throw new Error(
|
|
|
|
"TooltipTrigger must have two props. The first being a button and the second being a render prop."
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const [tooltipTrigger, tooltip] = children;
|
|
|
|
|
|
|
|
return (
|
2022-01-20 21:03:54 +00:00
|
|
|
<FocusableProvider ref={triggerRef} {...triggerProps}>
|
|
|
|
{<tooltipTrigger.type {...mergeProps(tooltipTrigger.props, rest)} />}
|
|
|
|
{tooltipState.isOpen && (
|
|
|
|
<OverlayContainer>
|
|
|
|
<Tooltip
|
|
|
|
state={tooltipState}
|
|
|
|
{...mergeProps(tooltipProps, overlayProps)}
|
|
|
|
ref={overlayRef}
|
|
|
|
>
|
|
|
|
{tooltip()}
|
|
|
|
</Tooltip>
|
|
|
|
</OverlayContainer>
|
|
|
|
)}
|
|
|
|
</FocusableProvider>
|
2021-12-15 06:00:00 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
TooltipTrigger.defaultProps = {
|
|
|
|
delay: 250,
|
|
|
|
};
|