From d6f7997eacaee6498d4f3bb7a5581a7ae5e79689 Mon Sep 17 00:00:00 2001 From: Pablo Allendes Date: Fri, 29 Dec 2023 15:15:12 +0100 Subject: [PATCH] fix(Tooltip): add strategy option to support edge use cases --- src/components/tooltip/tooltip-portal.tsx | 20 ++++++++ src/components/tooltip/tooltip.tsx | 62 +++++++++++++++-------- 2 files changed, 60 insertions(+), 22 deletions(-) create mode 100644 src/components/tooltip/tooltip-portal.tsx diff --git a/src/components/tooltip/tooltip-portal.tsx b/src/components/tooltip/tooltip-portal.tsx new file mode 100644 index 00000000..a10932be --- /dev/null +++ b/src/components/tooltip/tooltip-portal.tsx @@ -0,0 +1,20 @@ +import { useEffect, useRef, useState } from "react"; +import ReactDOM from "react-dom"; + +interface PortalProps { + children: React.ReactNode; +} + +export const TooltipPortal = ({ children }: PortalProps) => { + const ref = useRef(null); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + if (document) { + ref.current = document.body; + setMounted(true); + } + }, []); + + return mounted && ref.current ? ReactDOM.createPortal(children, ref.current) : null; +}; diff --git a/src/components/tooltip/tooltip.tsx b/src/components/tooltip/tooltip.tsx index 7739fdcf..7bf7e93a 100644 --- a/src/components/tooltip/tooltip.tsx +++ b/src/components/tooltip/tooltip.tsx @@ -3,6 +3,7 @@ import { Placement } from "@popperjs/core"; import React, { useEffect, useState } from "react"; import { usePopper } from "react-popper"; import { classNames } from "../../util/class-names"; +import { TooltipPortal } from "./tooltip-portal"; interface TooltipProps { children: React.ReactNode; @@ -11,9 +12,17 @@ interface TooltipProps { className?: string; open?: boolean; onClose?: () => void; + strategy?: "fixed" | "absolute" | "portal"; } -export const Tooltip = ({ children, title, position = "right", className, open }: TooltipProps) => { +export const Tooltip = ({ + children, + title, + position = "right", + className, + open, + strategy = "absolute", +}: TooltipProps) => { const [referenceElement, setReferenceElement] = useState(); const [popperElement, setPopperElement] = useState(); const [show, setShow] = useState(false); @@ -21,6 +30,7 @@ export const Tooltip = ({ children, title, position = "right", className, open } const { styles, attributes } = usePopper(referenceElement, popperElement, { placement: position, + strategy: strategy !== "portal" ? strategy : "absolute", modifiers: [{ name: "offset", options: { offset: [0, 8] } }], }); @@ -31,6 +41,30 @@ export const Tooltip = ({ children, title, position = "right", className, open } } }, [open]); + const renderTooltipContent = () => ( + +
el && setPopperElement(el)} + className={classNames( + "rounded-lg bg-neutral-900 p-4 px-4 py-2 text-xs text-neutral-0 shadow", + className + )} + style={styles.popper} + {...attributes.popper} + > + {title} +
+
+ ); + return (
{children}
- -
el && setPopperElement(el)} - className={classNames( - "rounded-lg bg-neutral-900 p-4 px-4 py-2 text-xs text-neutral-0 shadow", - className - )} - style={styles.popper} - {...attributes.popper} - > - {title} -
-
+ {strategy === "portal" ? ( + {renderTooltipContent()} + ) : ( + renderTooltipContent() + )}
); };