Only calculate position when tooltip is shown (#755)
This commit is contained in:
parent
0f7f55ec0a
commit
dcc3c61f52
|
@ -6,9 +6,14 @@ import {
|
||||||
Placement,
|
Placement,
|
||||||
shift,
|
shift,
|
||||||
useFloating,
|
useFloating,
|
||||||
} from '@floating-ui/react-dom'
|
useFocus,
|
||||||
|
useHover,
|
||||||
|
useInteractions,
|
||||||
|
useRole,
|
||||||
|
} from '@floating-ui/react-dom-interactions'
|
||||||
|
import { Transition } from '@headlessui/react'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { ReactNode, useRef } from 'react'
|
import { ReactNode, useRef, useState } from 'react'
|
||||||
|
|
||||||
// See https://floating-ui.com/docs/react-dom
|
// See https://floating-ui.com/docs/react-dom
|
||||||
|
|
||||||
|
@ -23,8 +28,12 @@ export function Tooltip(props: {
|
||||||
|
|
||||||
const arrowRef = useRef(null)
|
const arrowRef = useRef(null)
|
||||||
|
|
||||||
const { x, y, refs, reference, floating, strategy, middlewareData } =
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
|
const { x, y, reference, floating, strategy, middlewareData, context } =
|
||||||
useFloating({
|
useFloating({
|
||||||
|
open,
|
||||||
|
onOpenChange: setOpen,
|
||||||
whileElementsMounted: autoUpdate,
|
whileElementsMounted: autoUpdate,
|
||||||
placement,
|
placement,
|
||||||
middleware: [
|
middleware: [
|
||||||
|
@ -37,6 +46,11 @@ export function Tooltip(props: {
|
||||||
|
|
||||||
const { x: arrowX, y: arrowY } = middlewareData.arrow ?? {}
|
const { x: arrowX, y: arrowY } = middlewareData.arrow ?? {}
|
||||||
|
|
||||||
|
const { getReferenceProps, getFloatingProps } = useInteractions([
|
||||||
|
useHover(context, { mouseOnly: noTap }),
|
||||||
|
useFocus(context),
|
||||||
|
useRole(context, { role: 'tooltip' }),
|
||||||
|
])
|
||||||
// which side of tooltip arrow is on. like: if tooltip is top-left, arrow is on bottom of tooltip
|
// which side of tooltip arrow is on. like: if tooltip is top-left, arrow is on bottom of tooltip
|
||||||
const arrowSide = {
|
const arrowSide = {
|
||||||
top: 'bottom',
|
top: 'bottom',
|
||||||
|
@ -48,18 +62,28 @@ export function Tooltip(props: {
|
||||||
return text ? (
|
return text ? (
|
||||||
<div className="contents">
|
<div className="contents">
|
||||||
<div
|
<div
|
||||||
className={clsx('peer inline-block', className)}
|
className={clsx('inline-block', className)}
|
||||||
ref={reference}
|
ref={reference}
|
||||||
tabIndex={noTap ? undefined : 0}
|
tabIndex={noTap ? undefined : 0}
|
||||||
onTouchStart={() => (refs.reference.current as HTMLElement).focus()}
|
{...getReferenceProps()}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
<div
|
{/* conditionally render tooltip and fade in/out */}
|
||||||
|
<Transition
|
||||||
|
show={open}
|
||||||
|
enter="transition ease-out duration-200"
|
||||||
|
enterFrom="opacity-0 "
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="transition ease-in duration-150"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
// div attributes
|
||||||
role="tooltip"
|
role="tooltip"
|
||||||
ref={floating}
|
ref={floating}
|
||||||
style={{ position: strategy, top: y ?? 0, left: x ?? 0 }}
|
style={{ position: strategy, top: y ?? 0, left: x ?? 0 }}
|
||||||
className="-z-10 max-w-xs rounded bg-slate-700 px-2 py-1 text-center text-sm text-white opacity-0 transition-opacity peer-hover:z-10 peer-hover:opacity-100 peer-focus:z-10 peer-focus:opacity-100"
|
className="z-10 max-w-xs rounded bg-slate-700 px-2 py-1 text-center text-sm text-white"
|
||||||
|
{...getFloatingProps()}
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
<div
|
<div
|
||||||
|
@ -73,7 +97,7 @@ export function Tooltip(props: {
|
||||||
[arrowSide]: '-4px',
|
[arrowSide]: '-4px',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>{children}</>
|
<>{children}</>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@amplitude/analytics-browser": "0.4.1",
|
"@amplitude/analytics-browser": "0.4.1",
|
||||||
"@floating-ui/react-dom": "1.0.0",
|
"@floating-ui/react-dom-interactions": "0.9.2",
|
||||||
"@headlessui/react": "1.6.1",
|
"@headlessui/react": "1.6.1",
|
||||||
"@heroicons/react": "1.0.5",
|
"@heroicons/react": "1.0.5",
|
||||||
"@nivo/core": "0.74.0",
|
"@nivo/core": "0.74.0",
|
||||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -2190,7 +2190,15 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@floating-ui/core" "^1.0.1"
|
"@floating-ui/core" "^1.0.1"
|
||||||
|
|
||||||
"@floating-ui/react-dom@1.0.0":
|
"@floating-ui/react-dom-interactions@0.9.2":
|
||||||
|
version "0.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.9.2.tgz#9a364cc44ecbc242b5218dff0e0d071de115e13a"
|
||||||
|
integrity sha512-1I0urs4jlGuo4FRukvjtMmdUwxqvgwtTlESEPVwEvFGHXVh1PKkKaPZJ0Dcp9B8DQt4ewQEbwJxsoker2pDYTQ==
|
||||||
|
dependencies:
|
||||||
|
"@floating-ui/react-dom" "^1.0.0"
|
||||||
|
aria-hidden "^1.1.3"
|
||||||
|
|
||||||
|
"@floating-ui/react-dom@^1.0.0":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-1.0.0.tgz#e0975966694433f1f0abffeee5d8e6bb69b7d16e"
|
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-1.0.0.tgz#e0975966694433f1f0abffeee5d8e6bb69b7d16e"
|
||||||
integrity sha512-uiOalFKPG937UCLm42RxjESTWUVpbbatvlphQAU6bsv+ence6IoVG8JOUZcy8eW81NkU+Idiwvx10WFLmR4MIg==
|
integrity sha512-uiOalFKPG937UCLm42RxjESTWUVpbbatvlphQAU6bsv+ence6IoVG8JOUZcy8eW81NkU+Idiwvx10WFLmR4MIg==
|
||||||
|
@ -3935,6 +3943,13 @@ argparse@^2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||||
|
|
||||||
|
aria-hidden@^1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254"
|
||||||
|
integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA==
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.0.0"
|
||||||
|
|
||||||
aria-query@^4.2.2:
|
aria-query@^4.2.2:
|
||||||
version "4.2.2"
|
version "4.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
|
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
|
||||||
|
@ -11314,7 +11329,7 @@ tsconfig-paths@^3.14.1:
|
||||||
minimist "^1.2.6"
|
minimist "^1.2.6"
|
||||||
strip-bom "^3.0.0"
|
strip-bom "^3.0.0"
|
||||||
|
|
||||||
tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||||
|
|
Loading…
Reference in New Issue
Block a user