Skip to content

Commit

Permalink
feat: Add hovering state for heatmaps (#21794)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite authored Apr 24, 2024
1 parent 5033928 commit 67a39ef
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 15 deletions.
47 changes: 46 additions & 1 deletion frontend/src/toolbar/elements/Heatmap.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,53 @@
import heatmapsJs, { Heatmap as HeatmapJS } from 'heatmap.js'
import { useValues } from 'kea'
import { useCallback, useEffect, useRef } from 'react'
import { MutableRefObject, useCallback, useEffect, useRef } from 'react'

import { heatmapLogic } from '~/toolbar/elements/heatmapLogic'

import { useMousePosition } from './useMousePosition'

function HeatmapMouseInfo({
heatmapJsRef,
}: {
heatmapJsRef: MutableRefObject<HeatmapJS<'value', 'x', 'y'> | undefined>
}): JSX.Element | null {
const { shiftPressed, heatmapFilters } = useValues(heatmapLogic)

const mousePosition = useMousePosition()
const value = heatmapJsRef.current?.getValueAt(mousePosition)

if (!mousePosition || (!value && !shiftPressed)) {
return null
}

const leftPosition = window.innerWidth - mousePosition.x < 100

return (
<div
className="absolute z-10"
// eslint-disable-next-line react/forbid-dom-props
style={{
top: mousePosition.y,
left: mousePosition.x,
}}
>
<div
className="absolute border rounded bg-bg-light shadow-md p-2 mx-2"
// eslint-disable-next-line react/forbid-dom-props
style={{
left: leftPosition ? undefined : 0,
right: leftPosition ? 0 : undefined,
transform: 'translateY(-50%)',
}}
>
<span className="font-semibold whitespace-nowrap">
{value} {heatmapFilters.type + 's'}
</span>
</div>
</div>
)
}

export function Heatmap(): JSX.Element | null {
const { heatmapJsData, heatmapEnabled, heatmapFilters } = useValues(heatmapLogic)
const heatmapsJsRef = useRef<HeatmapJS<'value', 'x', 'y'>>()
Expand Down Expand Up @@ -41,6 +85,7 @@ export function Heatmap(): JSX.Element | null {
return (
<div className="fixed inset-0 overflow-hidden">
<div className="absolute inset-0" ref={setHeatmapContainer} />
<HeatmapMouseInfo heatmapJsRef={heatmapsJsRef} />
</div>
)
}
16 changes: 2 additions & 14 deletions frontend/src/toolbar/elements/ScrollDepth.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@
import { useValues } from 'kea'
import { useEffect, useState } from 'react'

import { heatmapLogic } from '~/toolbar/elements/heatmapLogic'

import { toolbarConfigLogic } from '../toolbarConfigLogic'
import { useMousePosition } from './useMousePosition'

function ScrollDepthMouseInfo(): JSX.Element | null {
const { posthog } = useValues(toolbarConfigLogic)
const { heatmapElements, rawHeatmapLoading } = useValues(heatmapLogic)

// Track the mouse position and render an indicator about how many people have scrolled to this point
const [mouseY, setMouseY] = useState<null | number>(0)

useEffect(() => {
const onMove = (e: MouseEvent): void => {
setMouseY(e.clientY)
}

window.addEventListener('mousemove', onMove)
return () => {
window.removeEventListener('mousemove', onMove)
}
}, [])
const { y: mouseY } = useMousePosition()

if (!mouseY) {
return null
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/toolbar/elements/useMousePosition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useEffect, useState } from 'react'

export const useMousePosition = (): { x: number; y: number } => {
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })

useEffect(() => {
const onMove = (e: MouseEvent): void => {
setMousePosition({ x: e.clientX, y: e.clientY })
}

window.addEventListener('mousemove', onMove)
return () => {
window.removeEventListener('mousemove', onMove)
}
}, [])
return mousePosition
}

0 comments on commit 67a39ef

Please sign in to comment.