From 6acc84fd9e3cffa8475afc467952a6d7ed95e480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 30 Jul 2022 09:59:20 +0200 Subject: [PATCH] `Tooltip` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/Tooltip.jsx | 76 -------------------------------------- src/Tooltip.tsx | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 76 deletions(-) delete mode 100644 src/Tooltip.jsx create mode 100644 src/Tooltip.tsx diff --git a/src/Tooltip.jsx b/src/Tooltip.jsx deleted file mode 100644 index 9f613083..00000000 --- a/src/Tooltip.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React, { forwardRef, useRef } from "react"; -import { useTooltipTriggerState } from "@react-stately/tooltip"; -import { FocusableProvider } from "@react-aria/focus"; -import { useTooltipTrigger, useTooltip } from "@react-aria/tooltip"; -import { mergeProps, useObjectRef } from "@react-aria/utils"; -import styles from "./Tooltip.module.css"; -import classNames from "classnames"; -import { OverlayContainer, useOverlayPosition } from "@react-aria/overlays"; - -export const Tooltip = forwardRef( - ({ position, state, className, ...props }, ref) => { - let { tooltipProps } = useTooltip(props, state); - - return ( -
- {props.children} -
- ); - } -); - -export const TooltipTrigger = forwardRef(({ children, ...rest }, ref) => { - const tooltipState = useTooltipTriggerState(rest); - const triggerRef = useObjectRef(ref); - const overlayRef = useRef(); - const { triggerProps, tooltipProps } = useTooltipTrigger( - rest, - tooltipState, - triggerRef - ); - - const { overlayProps } = useOverlayPosition({ - placement: rest.placement || "top", - targetRef: triggerRef, - overlayRef, - isOpen: tooltipState.isOpen, - offset: 5, - }); - - 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 ( - - {} - {tooltipState.isOpen && ( - - - {tooltip()} - - - )} - - ); -}); - -TooltipTrigger.defaultProps = { - delay: 250, -}; diff --git a/src/Tooltip.tsx b/src/Tooltip.tsx new file mode 100644 index 00000000..195443d6 --- /dev/null +++ b/src/Tooltip.tsx @@ -0,0 +1,98 @@ +import React, { + ForwardedRef, + forwardRef, + ReactElement, + ReactNode, + useRef, +} from "react"; +import { + TooltipTriggerState, + useTooltipTriggerState, +} from "@react-stately/tooltip"; +import { FocusableProvider } from "@react-aria/focus"; +import { useTooltipTrigger, useTooltip } from "@react-aria/tooltip"; +import { mergeProps, useObjectRef } from "@react-aria/utils"; +import classNames from "classnames"; +import { OverlayContainer, useOverlayPosition } from "@react-aria/overlays"; +import { Placement } from "@react-types/overlays"; + +import styles from "./Tooltip.module.css"; + +interface TooltipProps { + className?: string; + state: TooltipTriggerState; + children: ReactNode; +} + +export const Tooltip = forwardRef( + ( + { state, className, children, ...rest }: TooltipProps, + ref: ForwardedRef + ) => { + const { tooltipProps } = useTooltip(rest, state); + + return ( +
+ {children} +
+ ); + } +); + +interface TooltipTriggerProps { + children: ReactElement; + placement?: Placement; + delay?: number; + tooltip: () => string; +} + +export const TooltipTrigger = forwardRef( + ( + { children, placement, tooltip, ...rest }: TooltipTriggerProps, + ref: ForwardedRef + ) => { + const tooltipTriggerProps = { delay: 250, ...rest }; + const tooltipState = useTooltipTriggerState(tooltipTriggerProps); + const triggerRef = useObjectRef(ref); + const overlayRef = useRef(); + const { triggerProps, tooltipProps } = useTooltipTrigger( + tooltipTriggerProps, + tooltipState, + triggerRef + ); + + const { overlayProps } = useOverlayPosition({ + placement: placement || "top", + targetRef: triggerRef, + overlayRef, + isOpen: tooltipState.isOpen, + offset: 5, + }); + + return ( + + ( + children.props, + rest + )} + /> + {tooltipState.isOpen && ( + + + {tooltip()} + + + )} + + ); + } +);