-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Anchored tooltip #15568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Anchored tooltip #15568
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Implemented anchored tooltip functionality for bar charts using Floating UI, replacing the native Nivo tooltip system with a custom implementation that allows users to hover over tooltips.
Key Changes:
- Created new
useBarChartFloatingTooltiphook that manages tooltip positioning using virtual elements and debounced hover states - Tooltips now render in a
FloatingPortaloutside the chart SVG, enabling pointer events and user interaction - Added
interactiveandscrollableprops toGraphWidgetTooltipto enable pointer events and handle overflow - Removed
enableGroupTooltipprop from the public API (now determined automatically based ongroupMode) - Enriched bar datum with positioning data (
barAbsX,barAbsY, etc.) to calculate virtual anchor elements - Implemented 100ms debounce to allow smooth transitions between bar and tooltip hover states
Implementation Details:
- Uses Floating UI's
flipandshiftmiddleware for intelligent tooltip placement - Virtual element positioning calculates bounding rect from SVG coordinates
- Tooltip visibility controlled by combined state:
isChartHovered || isTooltipHovered
Confidence Score: 4/5
- Safe to merge with minor cleanup recommended
- The implementation is well-structured with proper state management and debouncing. The TODO comment on line 14 should be addressed. This is the first usage of FloatingPortal in the codebase, so thorough testing is recommended to ensure proper behavior across different scenarios.
- Check
useBarChartFloatingTooltip.tsfor the TODO comment to be resolved
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useBarChartFloatingTooltip.ts | 4/5 | New hook implementing floating tooltip with virtual element positioning; contains TODO comment to address |
| packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChart.tsx | 5/5 | Integrated floating tooltip system, removed enableGroupTooltip prop, tooltip now renders in portal with proper event handling |
| packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetTooltip.tsx | 5/5 | Added interactive and scrollable props to support anchored tooltip with pointer events and overflow handling |
Sequence Diagram
sequenceDiagram
participant User
participant CustomBarItem
participant GraphWidgetBarChart
participant useBarChartFloatingTooltip
participant FloatingUI
participant FloatingPortal
participant GraphWidgetTooltip
User->>CustomBarItem: Mouse enters bar
CustomBarItem->>CustomBarItem: Enrich bar datum with position data
CustomBarItem->>GraphWidgetBarChart: onMouseEnter(enrichedDatum)
GraphWidgetBarChart->>useBarChartFloatingTooltip: handleBarMouseEnter(enrichedDatum)
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Cancel debounce timer
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Set isChartHovered = true
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Set hoveredDatum
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Create virtual element from bar position
useBarChartFloatingTooltip->>FloatingUI: refs.setReference(virtualElement)
FloatingUI->>FloatingUI: Calculate tooltip position with flip/shift
useBarChartFloatingTooltip-->>GraphWidgetBarChart: isTooltipVisible = true
GraphWidgetBarChart->>FloatingPortal: Render tooltip in portal
FloatingPortal->>GraphWidgetTooltip: Render with interactive=true, scrollable=true
GraphWidgetTooltip-->>User: Display anchored tooltip
User->>CustomBarItem: Mouse leaves bar
CustomBarItem->>GraphWidgetBarChart: onMouseLeave()
GraphWidgetBarChart->>useBarChartFloatingTooltip: handleBarMouseLeave()
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Debounce setChartHovered(false)
alt User moves to tooltip within 100ms
User->>GraphWidgetTooltip: Mouse enters tooltip
GraphWidgetTooltip->>useBarChartFloatingTooltip: handleTooltipMouseEnter()
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Cancel debounce, setIsTooltipHovered = true
useBarChartFloatingTooltip-->>GraphWidgetBarChart: isTooltipVisible = true
Note over GraphWidgetTooltip: Tooltip stays visible
else Timeout expires
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: setIsChartHovered = false
useBarChartFloatingTooltip-->>GraphWidgetBarChart: isTooltipVisible = false
GraphWidgetBarChart->>FloatingPortal: Unmount tooltip
end
User->>GraphWidgetTooltip: Mouse leaves tooltip
GraphWidgetTooltip->>useBarChartFloatingTooltip: handleTooltipMouseLeave()
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Set isTooltipHovered = false
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Set hoveredDatum = null
useBarChartFloatingTooltip-->>GraphWidgetBarChart: isTooltipVisible = false
GraphWidgetBarChart->>FloatingPortal: Unmount tooltip
7 files reviewed, 1 comment
...rc/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useBarChartFloatingTooltip.ts
Outdated
Show resolved
Hide resolved
|
🚀 Preview Environment Ready! Your preview environment is available at: http://bore.pub:27419 This environment will automatically shut down when the PR is closed or after 5 hours. |
|
Could you provide a description in your PR and also link an existing issue ? |
|
@Bonapara I suggest that we put in bold the line in the tooltip that corresponds to the hovered group, example :
|
|
Great idea @lucasbordeau - medium + darker colors (secondary for the label & tertiary for the value) |
|
@lucasbordeau mb, updated the description! and will push the new requirements shortly after |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Replaces Nivo's cursor-following tooltip with an anchored tooltip using floating-ui. The tooltip now anchors to the bar element itself, enabling scrolling for long content lists without following the cursor.
Key changes:
- New
useBarChartFloatingTooltiphook manages tooltip positioning using floating-ui's virtual element API - Tooltip stays anchored at bar position with smart placement (flip/shift middleware)
- Added 300ms debounced hide to allow users to hover into the tooltip for scrolling
- Tooltip supports max-height (120px) with overflow scrolling when
scrollableprop is enabled - Removed
enableGroupTooltipprop - now automatically enabled for stacked mode - Bar geometry data (position, dimensions) passed through mouse events for accurate positioning
Confidence Score: 5/5
- This PR is safe to merge with minimal risk
- Well-structured refactoring that replaces library tooltip with custom implementation. Clean separation of concerns with dedicated hook, proper debouncing, existing floating-ui dependency, and backward-compatible changes.
- No files require special attention
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useBarChartFloatingTooltip.ts | 5/5 | New hook implementing floating-ui based tooltip positioning with debounced hide logic and virtual element anchoring |
| packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChart.tsx | 5/5 | Refactored to use custom floating tooltip instead of Nivo's built-in tooltip, added FloatingPortal with mouse event handlers |
| packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetTooltip.tsx | 5/5 | Added interactive and scrollable props, implemented highlighting for hovered items, and added key field to tooltip items |
Sequence Diagram
sequenceDiagram
participant User
participant CustomBarItem
participant GraphWidgetBarChart
participant useBarChartFloatingTooltip
participant FloatingUI
participant GraphWidgetTooltip
User->>CustomBarItem: Mouse enters bar
CustomBarItem->>CustomBarItem: Gather bar geometry data
Note over CustomBarItem: barElement, barX, barY,<br/>barWidth, barHeight, etc.
CustomBarItem->>GraphWidgetBarChart: onMouseEnter(barDatumWithGeometry)
GraphWidgetBarChart->>useBarChartFloatingTooltip: showTooltipForBar(datum)
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Cancel any pending hide
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: createFloatingAnchorFromBarGeometry()
useBarChartFloatingTooltip->>FloatingUI: refs.setReference(virtualElement)
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: setHoveredBarDatum(datum)
FloatingUI->>FloatingUI: Calculate position with flip/shift/offset
GraphWidgetBarChart->>GraphWidgetTooltip: Render tooltip in FloatingPortal
GraphWidgetTooltip-->>User: Display anchored tooltip
User->>CustomBarItem: Mouse leaves bar
CustomBarItem->>GraphWidgetBarChart: onMouseLeave()
GraphWidgetBarChart->>useBarChartFloatingTooltip: scheduleTooltipHide()
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Start 300ms debounced timer
alt User hovers tooltip before timer expires
User->>GraphWidgetTooltip: Mouse enters tooltip
GraphWidgetTooltip->>GraphWidgetBarChart: onMouseEnter
GraphWidgetBarChart->>useBarChartFloatingTooltip: cancelTooltipHide()
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: Cancel debounced timer
Note over GraphWidgetTooltip: Tooltip remains visible<br/>and scrollable
User->>GraphWidgetTooltip: Mouse leaves tooltip
GraphWidgetTooltip->>GraphWidgetBarChart: onMouseLeave
GraphWidgetBarChart->>useBarChartFloatingTooltip: hideTooltip()
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: setHoveredBarDatum(null)
else Timer expires
useBarChartFloatingTooltip->>useBarChartFloatingTooltip: setHoveredBarDatum(null)
end
GraphWidgetTooltip-->>User: Tooltip disappears
7 files reviewed, no comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Replaced Nivo's cursor-following tooltips with anchored tooltips using floating-ui to enable scrollable content for charts with many data points.
Key Changes:
- Introduced
GraphWidgetFloatingTooltipcomponent that uses floating-ui's positioning system with flip/shift middleware for intelligent placement - Added
useTooltipFloatinghook to wrap floating-ui configuration with chart-specific settings - Updated
GraphWidgetTooltipto support scrollable content (max height 120px) and highlighting for multi-series data - Refactored bar charts to pass anchor element references instead of using Nivo's built-in tooltip system
- Created
CustomCrosshairLayerfor line charts to handle mouse tracking and tooltip positioning - Added utility functions to create virtual elements from SVG elements and coordinates for floating-ui positioning
- Implemented debounced tooltip hiding (300ms) with ability to cancel when hovering over tooltip
- Changed tooltip
pointer-eventsfromnonetoautoto enable interaction with clickable links
Technical Approach:
- Bar charts anchor tooltips to the actual bar SVG elements
- Line charts create virtual elements from calculated offset positions
- Tooltips remain anchored while allowing scroll within content area
- Error handling added for missing container elements
Confidence Score: 5/5
- This PR is safe to merge - well-architected refactoring with proper error handling and no breaking changes
- The implementation is clean, follows React best practices, includes proper error handling for missing DOM elements, uses established libraries (floating-ui), maintains existing functionality while adding new capabilities, and improves UX for charts with many data points. The code is well-structured with clear separation of concerns.
- No files require special attention
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetFloatingTooltip.tsx | 5/5 | introduced new floating tooltip component using floating-ui for positioning, handles both bar chart and line chart anchor types with error handling |
| packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetTooltip.tsx | 5/5 | updated tooltip to support scrollable content with max height, highlighting, proper key-based rendering, and changed pointer-events to auto for interactivity |
| packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChart.tsx | 5/5 | refactored to use new anchored tooltip system with state management, debounced hiding, and passes anchor element reference on mouse enter events |
| packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/components/GraphWidgetLineChart.tsx | 5/5 | integrated new anchored tooltip with crosshair layer, uses custom crosshair layer for better tooltip positioning control |
| packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/components/CustomCrosshairLayer.tsx | 5/5 | added new custom crosshair layer with animated vertical line, handles mouse movement to find nearest slice and closest point for tooltip anchoring |
Sequence Diagram
sequenceDiagram
participant User
participant BarChart
participant CustomBarItem
participant LineChart
participant CustomCrosshairLayer
participant FloatingTooltip
participant FloatingUI
participant TooltipComponent
Note over User,TooltipComponent: Bar Chart Interaction Flow
User->>BarChart: Mouse enters bar
BarChart->>CustomBarItem: onMouseEnter event
CustomBarItem->>BarChart: Passes event to parent handler
BarChart->>BarChart: getTooltipData(datum)
BarChart->>BarChart: setActiveTooltipData with bar-element-anchor
BarChart->>FloatingTooltip: Render with tooltipData
FloatingTooltip->>FloatingTooltip: getTooltipReferenceFromBarChartElementAnchor
FloatingTooltip->>FloatingUI: useFloating with reference element
FloatingUI->>FloatingUI: Calculate position with flip/shift
FloatingUI-->>FloatingTooltip: Return position styles
FloatingTooltip->>TooltipComponent: Render with items & highlighting
TooltipComponent-->>User: Display anchored tooltip
Note over User,TooltipComponent: Line Chart Interaction Flow
User->>LineChart: Mouse moves over chart
LineChart->>CustomCrosshairLayer: onMouseMove event
CustomCrosshairLayer->>CustomCrosshairLayer: Find nearest slice & closest point
CustomCrosshairLayer->>LineChart: onSliceHover with hover data
LineChart->>LineChart: createSliceTooltipData
LineChart->>LineChart: setActiveTooltipData with line-point-anchor
LineChart->>LineChart: setCrosshairX for visual indicator
LineChart->>FloatingTooltip: Render with tooltipData
FloatingTooltip->>FloatingTooltip: getTooltipReferenceFromLineChartPointAnchor
FloatingTooltip->>FloatingTooltip: createVirtualElementFromContainerOffset
FloatingTooltip->>FloatingUI: useFloating with virtual element
FloatingUI->>FloatingUI: Calculate position with flip/shift
FloatingUI-->>FloatingTooltip: Return position styles
FloatingTooltip->>TooltipComponent: Render with items & highlighting
TooltipComponent-->>User: Display anchored tooltip with crosshair
Note over User,TooltipComponent: Tooltip Interaction & Hiding
User->>TooltipComponent: Mouse enters tooltip
TooltipComponent->>FloatingTooltip: onMouseEnter
FloatingTooltip->>BarChart: onCancelScheduledHide
BarChart->>BarChart: Cancel debounced hide
User->>TooltipComponent: Mouse leaves tooltip
TooltipComponent->>FloatingTooltip: onMouseLeave
FloatingTooltip->>BarChart: onScheduleHide
BarChart->>BarChart: Schedule debounced hide (300ms)
BarChart->>BarChart: setActiveTooltipData(null)
BarChart->>FloatingTooltip: Unmount tooltip
44 files reviewed, no comments
lucasbordeau
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall that's better yes, we could refine the behavior of the tooltips with Bonapara later, but for now let's focus on the code, I think that you can push it a little bit further.
...front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/CustomBarItem.tsx
Show resolved
Hide resolved
packages/twenty-front/src/modules/page-layout/widgets/graph/hooks/useTooltipFloating.ts
Outdated
Show resolved
Hide resolved
...twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetFloatingTooltip.tsx
Outdated
Show resolved
Hide resolved
...twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetFloatingTooltip.tsx
Outdated
Show resolved
Hide resolved
...front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useBarChartHandlers.ts
Outdated
Show resolved
Hide resolved
...-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useBarChartTooltip.ts
Outdated
Show resolved
Hide resolved
...src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChart.tsx
Outdated
Show resolved
Hide resolved
...src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChart.tsx
Outdated
Show resolved
Hide resolved
| @@ -0,0 +1 @@ | |||
| export const LINE_CHART_MARGIN_TOP = 20; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
polish: we could group these into one file:
export const LINE_CHART_MARGINS = { right: / top: }
|
Thanks @ehconitin for your contribution! |


Issue -
what we want -
what I did -