diff --git a/src/components/Universe/Graph/Cubes/Cube/components/Tooltip/index.tsx b/src/components/Universe/Graph/Cubes/Cube/components/Tooltip/index.tsx index fbd3cd24b..a565f13ba 100644 --- a/src/components/Universe/Graph/Cubes/Cube/components/Tooltip/index.tsx +++ b/src/components/Universe/Graph/Cubes/Cube/components/Tooltip/index.tsx @@ -8,15 +8,11 @@ import { formatDescription } from '~/utils/formatDescription' import { TwitData } from './Tweet' const Wrapper = styled(Flex)(({ theme }) => ({ - position: 'absolute', - top: '65px', - right: '55px', width: '300px', pointerEvents: 'auto', background: colors.dashboardHeader, boxShadow: '0px 1px 6px rgba(0, 0, 0, 0.1)', color: colors.primaryText1, - zIndex: 100, maxHeight: '400px', overflowY: 'auto', transition: 'opacity 0.6s', diff --git a/src/components/Universe/Graph/Cubes/index.tsx b/src/components/Universe/Graph/Cubes/index.tsx index c36d379c5..bf3a58497 100644 --- a/src/components/Universe/Graph/Cubes/index.tsx +++ b/src/components/Universe/Graph/Cubes/index.tsx @@ -17,7 +17,7 @@ const POINTER_IN_DELAY = 200 export const Cubes = memo(() => { const selectedNode = useSelectedNode() const relativeIds = useSelectedNodeRelativeIds() - const { selectionGraphData, showSelectionGraph, setHoveredNode } = useGraphStore((s) => s) + const { selectionGraphData, showSelectionGraph, setHoveredNode, setIsHovering } = useGraphStore((s) => s) const data = useDataStore((s) => s.dataInitial) const setTranscriptOpen = useAppStore((s) => s.setTranscriptOpen) @@ -56,6 +56,7 @@ export const Cubes = memo(() => { const onPointerOut = useCallback( (e: ThreeEvent) => { e.stopPropagation() + setIsHovering(false) if (hoverTimeoutRef.current) { clearTimeout(hoverTimeoutRef.current) @@ -64,7 +65,7 @@ export const Cubes = memo(() => { setHoveredNode(null) }, - [setHoveredNode], + [setHoveredNode, setIsHovering], ) const onPointerIn = useCallback( @@ -77,6 +78,7 @@ export const Cubes = memo(() => { if (!ignoreNodeEvent(node)) { e.stopPropagation() + setIsHovering(true) hoverTimeoutRef.current = setTimeout(() => { setHoveredNode(node) @@ -84,7 +86,7 @@ export const Cubes = memo(() => { } } }, - [setHoveredNode, ignoreNodeEvent], + [setHoveredNode, ignoreNodeEvent, setIsHovering], ) const hideUniverse = showSelectionGraph && !!selectedNode @@ -119,4 +121,4 @@ export const Cubes = memo(() => { ) }) -Cubes.displayName = 'Cubes' +Cubes.displayName = 'Cubes' \ No newline at end of file diff --git a/src/components/Universe/Overlay/index.tsx b/src/components/Universe/Overlay/index.tsx index 38deb9c83..872d6b252 100644 --- a/src/components/Universe/Overlay/index.tsx +++ b/src/components/Universe/Overlay/index.tsx @@ -1,17 +1,44 @@ +import { useCallback, useEffect, useState } from 'react' import styled from 'styled-components' import { ActionsToolbar } from '~/components/App/ActionsToolbar' import { useGraphStore } from '~/stores/useGraphStore' import { Tooltip } from '../Graph/Cubes/Cube/components/Tooltip' export const Overlay = () => { - const [hoveredNode] = useGraphStore((s) => [s.hoveredNode]) + const [hoveredNode, isHovering] = useGraphStore((s) => [s.hoveredNode, s.isHovering]) + const [isVisible, setIsVisible] = useState(false) + const [isTooltipHovered, setIsTooltipHovered] = useState(false) + + useEffect(() => { + let timer: NodeJS.Timeout | null = null + + if (isHovering || isTooltipHovered) { + setIsVisible(true) + } else { + timer = setTimeout(() => setIsVisible(false), 300) + } + + return () => { + if (timer) { + clearTimeout(timer) + } + } + }, [isHovering, isTooltipHovered]) + + const handleTooltipMouseEnter = useCallback(() => { + setIsTooltipHovered(true) + }, []) + + const handleTooltipMouseLeave = useCallback(() => { + setIsTooltipHovered(false) + }, []) return ( - {hoveredNode && ( -
+ {hoveredNode && isVisible && ( + -
+ )}
@@ -37,3 +64,10 @@ const OverlayWrap = styled('div')(({ theme }) => ({ top: 50, }, })) + +const TooltipWrapper = styled.div` + position: absolute; + top: 65px; + right: 55px; + z-index: 100; +` diff --git a/src/stores/useGraphStore/index.ts b/src/stores/useGraphStore/index.ts index b74f2772a..2deec1cf2 100644 --- a/src/stores/useGraphStore/index.ts +++ b/src/stores/useGraphStore/index.ts @@ -79,6 +79,7 @@ export type GraphStore = { scrollEventsDisabled: boolean simulation: ForceSimulation | null simulationHelpers: SimulationHelpers + isHovering: boolean setDisableCameraRotation: (rotation: boolean) => void setScrollEventsDisabled: (rotation: boolean) => void @@ -92,6 +93,7 @@ export type GraphStore = { setShowSelectionGraph: (_: boolean) => void setSelectionData: (data: GraphData) => void simulationCreate: (nodes: Node[], links: Link[]) => void + setIsHovering: (isHovering: boolean) => void } const defaultData: Omit< @@ -110,6 +112,7 @@ const defaultData: Omit< | 'setSelectionData' | 'setHideNodeDetails' | 'simulationCreate' + | 'setIsHovering' > = { data: null, simulation: null, @@ -124,6 +127,7 @@ const defaultData: Omit< nearbyNodeIds: [], showSelectionGraph: false, simulationHelpers: defaultSimulationHelpers, + isHovering: false, } export const useGraphStore = create()((set, get) => ({ @@ -134,6 +138,7 @@ export const useGraphStore = create()((set, get) => ({ setSelectionData: (selectionGraphData) => set({ selectionGraphData }), setScrollEventsDisabled: (scrollEventsDisabled) => set({ scrollEventsDisabled }), setDisableCameraRotation: (rotation) => set({ disableCameraRotation: rotation }), + setIsHovering: (isHovering) => set({ isHovering }), setGraphRadius: (graphRadius) => set({ graphRadius }), setGraphStyle: (graphStyle) => set({ graphStyle }), setHoveredNode: (hoveredNode) => {