Skip to content

Commit ad2ea78

Browse files
committed
feat: better tooltips
1 parent 0fe9fd4 commit ad2ea78

File tree

6 files changed

+51
-21
lines changed

6 files changed

+51
-21
lines changed

packages/react-query-devtools/src/timeline/index.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import useTimelineEvents from './useTimelineEvents'
99
import { SVGQueryTimeline, TooltipOptions } from './timelineComponents'
1010
import { useTheme } from '../theme'
1111
import TimelineOptions from './timelineOptions'
12+
import ReactDOM from 'react-dom'
1213

1314
function clampValue(value: number, min: number, max: number) {
1415
return Math.min(Math.max(value, min), max)
@@ -129,18 +130,24 @@ export function TimelinePanel(props: TimelinePanelProps) {
129130

130131
return (
131132
<>
132-
{tooltip && (
133-
<div
134-
style={{
135-
position: 'absolute',
136-
top: tooltip.y,
137-
left: tooltip.x,
138-
backgroundColor: theme.background,
139-
}}
140-
>
141-
{tooltip.content}
142-
</div>
143-
)}
133+
{tooltip &&
134+
ReactDOM.createPortal(
135+
<div
136+
style={{
137+
position: 'absolute',
138+
top: tooltip.y + 10,
139+
left: tooltip.x + 10,
140+
backgroundColor: theme.gray,
141+
fontFamily: 'sans-serif',
142+
zIndex: 100000,
143+
color: 'white',
144+
padding: '.5em',
145+
}}
146+
>
147+
{tooltip.content}
148+
</div>,
149+
document.body,
150+
)}
144151
<PanelMain isOpen={isOpen}>
145152
<PanelHead {...headProps}>
146153
<TimelineOptions

packages/react-query-devtools/src/timeline/timelineComponents.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import {
55
ReactQueryQueryEvent,
66
} from './useTimelineEvents'
77

8-
import { computeObserverCountBoxes, computeQueryBoxes } from './utils'
8+
import {
9+
computeObserverCountBoxes,
10+
computeQueryBoxes,
11+
formatMillisecondsDuration,
12+
} from './utils'
913

1014
export type TooltipOptions = {
1115
x: number
@@ -98,6 +102,7 @@ export const SVGQueryTimeline = React.forwardRef<
98102
{boxes.map((item) => {
99103
const counts = computeObserverCountBoxes(item)
100104

105+
const cacheTime = formatMillisecondsDuration(item.cacheTime)
101106
return (
102107
<g key={item.startAt.getTime()}>
103108
<rect
@@ -106,7 +111,7 @@ export const SVGQueryTimeline = React.forwardRef<
106111
width={scaleX(item.endAt) - scaleX(item.startAt)}
107112
height="22"
108113
fill="#8798bf42"
109-
{...getTooltipProps(`Cache time: ${item.cacheTime}ms`)}
114+
{...getTooltipProps(`Cache time: ${cacheTime}`)}
110115
/>
111116
{counts.map((count) => (
112117
<React.Fragment key={count.start.getTime()}>

packages/react-query-devtools/src/timeline/timelineOptions.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import * as React from 'react'
22
import { Input } from '../styledComponents'
33
import useTimelineEvents from './useTimelineEvents'
44

@@ -33,13 +33,9 @@ export default function TimelineOptions({
3333
alignSelf: 'flex-end',
3434
}}
3535
>
36-
<button onClick={() => setZoom((zoom) => clampZoom(zoom * 1.5))}>
37-
-
38-
</button>
36+
<button onClick={() => setZoom((z) => clampZoom(z * 1.5))}>-</button>
3937
{Math.floor((zoomBasis / zoom) * 100)}%
40-
<button onClick={() => setZoom((zoom) => clampZoom(zoom / 1.5))}>
41-
+
42-
</button>
38+
<button onClick={() => setZoom((z) => clampZoom(z / 1.5))}>+</button>
4339
</div>
4440
<div
4541
style={{

packages/react-query-devtools/src/timeline/utils.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe('computeQueryBoxes', () => {
2828
expect.objectContaining({
2929
startAt: new Date('2022-07-20T13:19:15.000Z'),
3030
endAt: new Date('2022-07-20T13:19:59.999Z'),
31+
cacheTime: 300000,
3132
}),
3233
)
3334
})

packages/react-query-devtools/src/timeline/utils.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export function computeQueryBoxes(
3838
sortedEvents.forEach((event) => {
3939
if (event.eventType === 'added') {
4040
partial.startAt = event.receivedAt
41+
partial.cacheTime = event.cacheTime
4142
} else if (event.eventType === 'removed') {
4243
items.push({
4344
...createBox(partial),
@@ -102,3 +103,22 @@ export function computeObserverCountBoxes(query: Box) {
102103

103104
return counts.filter((c) => c.count !== 0)
104105
}
106+
107+
export function formatMillisecondsDuration(ms: number | undefined) {
108+
if (!ms) return null
109+
110+
const minutes = Math.floor(ms / 60000)
111+
const seconds = Math.floor((ms % 60000) / 1000)
112+
const milliseconds = Math.floor((ms % 60000) % 1000)
113+
114+
const zipped: [number, string][] = [
115+
[minutes, 'min'],
116+
[seconds, 's'],
117+
[milliseconds, 'ms'],
118+
]
119+
120+
return zipped
121+
.filter(([count, _]) => count > 0)
122+
.map(([count, unit]) => `${count}${unit}`)
123+
.join(' ')
124+
}

rollup.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export default function rollup(options: RollupOptions): RollupOptions[] {
8383
entryFile: 'src/index.ts',
8484
globals: {
8585
react: 'React',
86+
'react-dom': 'ReactDOM',
8687
'@tanstack/react-query': 'ReactQuery',
8788
},
8889
}),

0 commit comments

Comments
 (0)