diff --git a/app/soapbox/components/ui/tooltip/tooltip.css b/app/soapbox/components/ui/tooltip/tooltip.css deleted file mode 100644 index 670571c8b..000000000 --- a/app/soapbox/components/ui/tooltip/tooltip.css +++ /dev/null @@ -1,12 +0,0 @@ -:root { - --reach-tooltip: 1; -} - -[data-reach-tooltip] { - @apply pointer-events-none absolute px-2.5 py-1.5 rounded shadow whitespace-nowrap text-xs font-medium bg-gray-800 text-gray-100 dark:bg-gray-100 dark:text-gray-900; - 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 dark:border-b-gray-100; -} diff --git a/app/soapbox/components/ui/tooltip/tooltip.tsx b/app/soapbox/components/ui/tooltip/tooltip.tsx index f2b6ffedc..0d492bcb6 100644 --- a/app/soapbox/components/ui/tooltip/tooltip.tsx +++ b/app/soapbox/components/ui/tooltip/tooltip.tsx @@ -1,67 +1,88 @@ -import { TooltipPopup, useTooltip } from '@reach/tooltip'; -import React from 'react'; - -import Portal from '../portal/portal'; - -import './tooltip.css'; +import { + arrow, + FloatingArrow, + FloatingPortal, + offset, + useFloating, + useHover, + useInteractions, + useTransitionStyles, +} from '@floating-ui/react'; +import React, { useRef, useState } from 'react'; interface ITooltip { + /** Element to display the tooltip around. */ + children: React.ReactElement> /** Text to display in the tooltip. */ text: string - /** Element to display the tooltip around. */ - children: React.ReactNode } -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, - }; -}; +/** + * Tooltip + */ +const Tooltip: React.FC = (props) => { + const { children, text } = props; -/** Hoverable tooltip element. */ -const Tooltip: React.FC = ({ - children, - text, -}) => { - // get the props from useTooltip - const [trigger, tooltip] = useTooltip(); + const [isOpen, setIsOpen] = useState(false); - // destructure off what we need to position the triangle - const { isVisible, triggerRect } = tooltip; + const arrowRef = useRef(null); + + const { x, y, strategy, refs, context } = useFloating({ + open: isOpen, + onOpenChange: setIsOpen, + placement: 'top', + middleware: [ + offset(6), + arrow({ + element: arrowRef, + }), + ], + }); + + const hover = useHover(context); + const { isMounted, styles } = useTransitionStyles(context, { + initial: { + opacity: 0, + transform: 'scale(0.8)', + }, + duration: { + open: 200, + close: 200, + }, + }); + + const { getReferenceProps, getFloatingProps } = useInteractions([ + hover, + ]); return ( - - {React.cloneElement(children as any, trigger)} + <> + {React.cloneElement(children, { + ref: refs.setReference, + ...getReferenceProps(), + })} - {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 - + {(isMounted) && ( +
- + className='pointer-events-none z-[100] whitespace-nowrap rounded bg-gray-800 px-2.5 py-1.5 text-xs font-medium text-gray-100 shadow dark:bg-gray-100 dark:text-gray-900' + {...getFloatingProps()} + > + {text} + + +
+
)} - -
+ ); }; -export default Tooltip; +export default Tooltip; \ No newline at end of file diff --git a/package.json b/package.json index 57831cd0e..ddd13f24a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "@reach/popover": "^0.18.0", "@reach/rect": "^0.18.0", "@reach/tabs": "^0.18.0", - "@reach/tooltip": "^0.18.0", "@reduxjs/toolkit": "^1.8.1", "@sentry/browser": "^7.37.2", "@sentry/react": "^7.37.2", diff --git a/yarn.lock b/yarn.lock index 4d6585981..5220b11d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2749,30 +2749,11 @@ "@reach/polymorphic" "0.18.0" "@reach/utils" "0.18.0" -"@reach/tooltip@^0.18.0": - version "0.18.0" - resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.18.0.tgz#6d416e77a82543af9a57d122962f9c0294fc2a5f" - integrity sha512-yugoTmTjB3qoMk/nUvcnw99MqpyE2TQMOXE29qnQhSqHriRwQhfftjXlTAGTSzsUJmbyms3A/1gQW0X61kjFZw== - dependencies: - "@reach/auto-id" "0.18.0" - "@reach/polymorphic" "0.18.0" - "@reach/portal" "0.18.0" - "@reach/rect" "0.18.0" - "@reach/utils" "0.18.0" - "@reach/visually-hidden" "0.18.0" - "@reach/utils@0.18.0": version "0.18.0" resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.18.0.tgz#4f3cebe093dd436eeaff633809bf0f68f4f9d2ee" integrity sha512-KdVMdpTgDyK8FzdKO9SCpiibuy/kbv3pwgfXshTI6tEcQT1OOwj7BAksnzGC0rPz0UholwC+AgkqEl3EJX3M1A== -"@reach/visually-hidden@0.18.0": - version "0.18.0" - resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.18.0.tgz#17923c08acc5946624c2836b2b09d359b3aa8c27" - integrity sha512-NsJ3oeHJtPc6UOeV6MHMuzQ5sl1ouKhW85i3C0S7VM+klxVlYScBZ2J4UVnWB50A2c+evdVpCnld2YeuyYYwBw== - dependencies: - "@reach/polymorphic" "0.18.0" - "@reduxjs/toolkit@^1.8.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.8.1.tgz#94ee1981b8cf9227cda40163a04704a9544c9a9f"