element-call/src/Tooltip.jsx

77 lines
2.1 KiB
React
Raw Normal View History

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,
};