From b2f2bcb8331f13f0f8acfe8825ddc8789d9ed11d Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 6 Jul 2022 14:19:51 -0400 Subject: [PATCH] Center tooltips and add arrow --- app/soapbox/components/ui/tooltip/tooltip.css | 4 ++ app/soapbox/components/ui/tooltip/tooltip.tsx | 49 +++++++++++++++++-- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/app/soapbox/components/ui/tooltip/tooltip.css b/app/soapbox/components/ui/tooltip/tooltip.css index 6d439ddb3..9e4addd1f 100644 --- a/app/soapbox/components/ui/tooltip/tooltip.css +++ b/app/soapbox/components/ui/tooltip/tooltip.css @@ -6,3 +6,7 @@ @apply pointer-events-none absolute px-2.5 py-1.5 rounded shadow whitespace-nowrap text-xs font-medium bg-gray-800 text-white; z-index: 100; } + +[data-reach-tooltip-arrow] { + @apply absolute z-50 w-0 h-0 border-l-8 border-solid border-l-transparent border-r-8 border-r-transparent border-b-8 border-b-gray-800; +} diff --git a/app/soapbox/components/ui/tooltip/tooltip.tsx b/app/soapbox/components/ui/tooltip/tooltip.tsx index 4efa4749f..e04221200 100644 --- a/app/soapbox/components/ui/tooltip/tooltip.tsx +++ b/app/soapbox/components/ui/tooltip/tooltip.tsx @@ -1,4 +1,5 @@ -import { default as ReachTooltip } from '@reach/tooltip'; +import Portal from '@reach/portal'; +import { TooltipPopup, useTooltip } from '@reach/tooltip'; import React from 'react'; import './tooltip.css'; @@ -8,15 +9,55 @@ interface ITooltip { text: string, } +const centered = (triggerRect: any, tooltipRect: any) => { + const triggerCenter = triggerRect.left + triggerRect.width / 2; + const left = triggerCenter - tooltipRect.width / 2; + const maxLeft = window.innerWidth - tooltipRect.width - 2; + return { + left: Math.min(Math.max(2, left), maxLeft) + window.scrollX, + top: triggerRect.bottom + 8 + window.scrollY, + }; +}; + /** Hoverable tooltip element. */ const Tooltip: React.FC = ({ children, text, }) => { + // get the props from useTooltip + const [trigger, tooltip] = useTooltip(); + + // destructure off what we need to position the triangle + const { isVisible, triggerRect } = tooltip; + return ( - - {children} - + + {React.cloneElement(children as any, trigger)} + + {isVisible && ( + // The Triangle. We position it relative to the trigger, not the popup + // so that collisions don't have a triangle pointing off to nowhere. + // Using a Portal may seem a little extreme, but we can keep the + // positioning logic simpler here instead of needing to consider + // the popup's position relative to the trigger and collisions + +
+ + )} + + ); };