Skip to content

feat(tooltip): add Floating UI tooltip primitives - #2020

Merged
hshoff merged 10 commits into
masterfrom
harry/visx-floating-tooltip
Jun 18, 2026
Merged

feat(tooltip): add Floating UI tooltip primitives#2020
hshoff merged 10 commits into
masterfrom
harry/visx-floating-tooltip

Conversation

@hshoff

@hshoff hshoff commented Jun 18, 2026

Copy link
Copy Markdown
Member

To be released in 4.1.0

Why Floating UI tooltips?

The post-4.0 registry and primitive chart work needs a modern tooltip foundation that can handle collision-aware placement, virtual anchors, SVG coordinates, arrows, portals, and controlled chart state without changing the existing @visx/tooltip APIs.

This PR adds an additive @visx/tooltip/floating subpath backed by Floating UI. The new surface keeps the visx model intact: users still own the chart render tree, nearest-datum lookup, mark events, and content composition, while visx provides low-level positioning primitives and a convenient chart-tooltip layer.

The goal is to make modern dashboard tooltips easier to build consistently across registry charts and product code, while preserving the existing legacy tooltip package behavior for current consumers.

馃挜 Breaking Changes

  • None.

馃殌 Enhancements

  • Add the @visx/tooltip/floating client subpath with Floating UI-backed tooltip exports.
  • Add anchor utilities for element, client/page point, container-local point, SVG point, rect, and virtual-element positioning.
  • Add useFloatingTooltip for controlled/uncontrolled open state, anchor state, data state, middleware configuration, ids, role wiring, and imperative open/close/update behavior.
  • Add low-level FloatingTooltip primitives: Provider, Root, Trigger, Portal, Positioner, Content, and Arrow.
  • Add trigger interactions for hover, focus, dismiss, delay groups, ARIA wiring, disabled triggers, explicit-anchor-plus-trigger positioning, and role="label" support.
  • Add ChartTooltipContent with config-driven labels, values, colors, icons, hidden items, ordering, formatter precedence, custom renderers, and item keys.
  • Add useChartTooltip and ChartTooltip as a convenience layer for chart-local anchors, SVG-local anchors, hide delays, controlled props, portals, and custom content.
  • Add @floating-ui/react as an @visx/tooltip dependency.

馃摑 Documentation

  • Document the modern floating tooltip API in packages/visx-tooltip/Readme.md.
  • Add packages/visx-tooltip/Handbook.md with source-validated API patterns, coordinate-space guidance, chart tooltip recipes, primitive usage, interaction notes, middleware notes, and styling contracts.
  • Add a MIGRATION.md 4.1 note for the additive @visx/tooltip/floating APIs.

馃悰 Bug Fix

  • None.

馃彔 Internal

  • Add focused tests for floating anchor conversion, primitive behavior, trigger interactions, chart tooltip content, chart tooltip convenience APIs, and type-level API constraints.
  • Add regression coverage for default ids, positioner id overrides, stale reference clearing, disabled trigger behavior, label-role ARIA wiring, and content role forwarding.
  • Add a floating typecheck fixture for @visx/tooltip/floating usage and invalid controlled floatingOptions.

Validation

  • yarn vitest run --config packages/visx-tooltip/vitest.config.ts packages/visx-tooltip/test/floatingPrimitives.test.tsx packages/visx-tooltip/test/floatingInteractions.test.tsx packages/visx-tooltip/test/ChartTooltip.test.tsx
  • PKG=@visx/tooltip yarn type:pkg
  • yarn tsc -p packages/visx-tooltip/test/tsconfig.floating-typecheck.json --pretty false
  • yarn vitest run --config packages/visx-tooltip/vitest.config.ts
  • yarn build
  • yarn test
  • yarn type:update-refs && git diff --exit-code
  • yarn docs:generate
  • git diff --check && git diff --cached --check

@hshoff hshoff added this to the 4.1.0 milestone Jun 18, 2026
@hshoff hshoff self-assigned this Jun 18, 2026
@github-actions

Copy link
Copy Markdown

Size Changes

Package Diff ESM Prev ESM CJS Prev CJS
visx-tooltip 馃敽 +313.8% 37.22 KB 9 KB 45.42 KB 13.35 KB

Compared to master. File sizes are unminified and ungzipped.

View raw build stats

Previous (master)

{
  "visx-a11y": {
    "esm": 28466,
    "lib": 34549
  },
  "visx-annotation": {
    "esm": 19693,
    "lib": 23755
  },
  "visx-axis": {
    "esm": 14072,
    "lib": 19318
  },
  "visx-bounds": {
    "esm": 1495,
    "lib": 1915
  },
  "visx-brush": {
    "esm": 42024,
    "lib": 44001
  },
  "visx-chart": {
    "esm": 5680,
    "lib": 8613
  },
  "visx-chord": {
    "esm": 1907,
    "lib": 2683
  },
  "visx-clip-path": {
    "esm": 1522,
    "lib": 2713
  },
  "visx-curve": {
    "esm": 351,
    "lib": 2594
  },
  "visx-delaunay": {
    "esm": 1475,
    "lib": 2489
  },
  "visx-demo": {
    "esm": 0,
    "lib": 0
  },
  "visx-drag": {
    "esm": 9078,
    "lib": 11025
  },
  "visx-event": {
    "esm": 3571,
    "lib": 5257
  },
  "visx-geo": {
    "esm": 8104,
    "lib": 11674
  },
  "visx-glyph": {
    "esm": 7243,
    "lib": 11421
  },
  "visx-gradient": {
    "esm": 6928,
    "lib": 11581
  },
  "visx-grid": {
    "esm": 9631,
    "lib": 12892
  },
  "visx-group": {
    "esm": 502,
    "lib": 1030
  },
  "visx-heatmap": {
    "esm": 3496,
    "lib": 4564
  },
  "visx-hierarchy": {
    "esm": 8687,
    "lib": 13458
  },
  "visx-kernel": {
    "esm": 12168,
    "lib": 15402
  },
  "visx-legend": {
    "esm": 14929,
    "lib": 20754
  },
  "visx-marker": {
    "esm": 3855,
    "lib": 6120
  },
  "visx-mock-data": {
    "esm": 325698,
    "lib": 330728
  },
  "visx-network": {
    "esm": 3088,
    "lib": 5105
  },
  "visx-pattern": {
    "esm": 7400,
    "lib": 10317
  },
  "visx-point": {
    "esm": 791,
    "lib": 1901
  },
  "visx-react-spring": {
    "esm": 8724,
    "lib": 11009
  },
  "visx-registry": {
    "esm": 116,
    "lib": 79
  },
  "visx-responsive": {
    "esm": 11775,
    "lib": 14019
  },
  "visx-sankey": {
    "esm": 2501,
    "lib": 3894
  },
  "visx-scale": {
    "esm": 19357,
    "lib": 31820
  },
  "visx-shape": {
    "esm": 52847,
    "lib": 76176
  },
  "visx-stats": {
    "esm": 9258,
    "lib": 10690
  },
  "visx-text": {
    "esm": 6416,
    "lib": 7990
  },
  "visx-theme": {
    "esm": 22587,
    "lib": 31584
  },
  "visx-threshold": {
    "esm": 2067,
    "lib": 2758
  },
  "visx-tooltip": {
    "esm": 9212,
    "lib": 13672
  },
  "visx-vendor": {
    "esm": 2974,
    "lib": 3226
  },
  "visx-visx": {
    "esm": 1718,
    "lib": 4399
  },
  "visx-voronoi": {
    "esm": 1909,
    "lib": 3235
  },
  "visx-wordcloud": {
    "esm": 1996,
    "lib": 2995
  },
  "visx-xychart": {
    "esm": 126022,
    "lib": 155810
  },
  "visx-zoom": {
    "esm": 12508,
    "lib": 14835
  }
}

Current

{
  "visx-a11y": {
    "esm": 28466,
    "lib": 34549
  },
  "visx-annotation": {
    "esm": 19693,
    "lib": 23755
  },
  "visx-axis": {
    "esm": 14072,
    "lib": 19318
  },
  "visx-bounds": {
    "esm": 1495,
    "lib": 1915
  },
  "visx-brush": {
    "esm": 42024,
    "lib": 44001
  },
  "visx-chart": {
    "esm": 5680,
    "lib": 8613
  },
  "visx-chord": {
    "esm": 1907,
    "lib": 2683
  },
  "visx-clip-path": {
    "esm": 1522,
    "lib": 2713
  },
  "visx-curve": {
    "esm": 351,
    "lib": 2594
  },
  "visx-delaunay": {
    "esm": 1475,
    "lib": 2489
  },
  "visx-demo": {
    "esm": 0,
    "lib": 0
  },
  "visx-drag": {
    "esm": 9078,
    "lib": 11025
  },
  "visx-event": {
    "esm": 3571,
    "lib": 5257
  },
  "visx-geo": {
    "esm": 8104,
    "lib": 11674
  },
  "visx-glyph": {
    "esm": 7243,
    "lib": 11421
  },
  "visx-gradient": {
    "esm": 6928,
    "lib": 11581
  },
  "visx-grid": {
    "esm": 9631,
    "lib": 12892
  },
  "visx-group": {
    "esm": 502,
    "lib": 1030
  },
  "visx-heatmap": {
    "esm": 3496,
    "lib": 4564
  },
  "visx-hierarchy": {
    "esm": 8687,
    "lib": 13458
  },
  "visx-kernel": {
    "esm": 12168,
    "lib": 15402
  },
  "visx-legend": {
    "esm": 14929,
    "lib": 20754
  },
  "visx-marker": {
    "esm": 3855,
    "lib": 6120
  },
  "visx-mock-data": {
    "esm": 325698,
    "lib": 330728
  },
  "visx-network": {
    "esm": 3088,
    "lib": 5105
  },
  "visx-pattern": {
    "esm": 7400,
    "lib": 10317
  },
  "visx-point": {
    "esm": 791,
    "lib": 1901
  },
  "visx-react-spring": {
    "esm": 8724,
    "lib": 11009
  },
  "visx-registry": {
    "esm": 116,
    "lib": 79
  },
  "visx-responsive": {
    "esm": 11775,
    "lib": 14019
  },
  "visx-sankey": {
    "esm": 2501,
    "lib": 3894
  },
  "visx-scale": {
    "esm": 19357,
    "lib": 31820
  },
  "visx-shape": {
    "esm": 52847,
    "lib": 76176
  },
  "visx-stats": {
    "esm": 9258,
    "lib": 10690
  },
  "visx-text": {
    "esm": 6416,
    "lib": 7990
  },
  "visx-theme": {
    "esm": 22587,
    "lib": 31584
  },
  "visx-threshold": {
    "esm": 2067,
    "lib": 2758
  },
  "visx-tooltip": {
    "esm": 38115,
    "lib": 46512
  },
  "visx-vendor": {
    "esm": 2974,
    "lib": 3226
  },
  "visx-visx": {
    "esm": 1718,
    "lib": 4399
  },
  "visx-voronoi": {
    "esm": 1909,
    "lib": 3235
  },
  "visx-wordcloud": {
    "esm": 1996,
    "lib": 2995
  },
  "visx-xychart": {
    "esm": 126022,
    "lib": 155810
  },
  "visx-zoom": {
    "esm": 12508,
    "lib": 14835
  }
}

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new additive @visx/tooltip/floating entrypoint that provides Floating UI鈥揵acked tooltip primitives and chart-focused convenience APIs, while keeping the existing @visx/tooltip surface unchanged.

Changes:

  • Introduces @visx/tooltip/floating exports (hooks, primitives, chart tooltip components) backed by @floating-ui/react.
  • Adds anchor conversion utilities + middleware builder for consistent positioning behavior.
  • Adds docs (README/Handbook/Migration note) and a focused test + typecheck suite for the new surface.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
yarn.lock Locks new @floating-ui/react dependency chain and tabbable.
packages/visx-tooltip/package.json Adds ./floating export map and @floating-ui/react dependency.
packages/visx-tooltip/src/floating/index.ts New client entrypoint exporting the floating tooltip surface.
packages/visx-tooltip/src/floating/types.ts Public types for anchors, interactions, primitives, and hooks.
packages/visx-tooltip/src/floating/anchors.ts Anchor-to-reference conversion utilities (DOM, points, SVG, rect, virtual).
packages/visx-tooltip/src/floating/middleware.ts Builds Floating UI middleware in a consistent order with override modes.
packages/visx-tooltip/src/floating/useFloatingTooltip.ts Core hook managing open/anchor/data state + Floating UI interactions/refs.
packages/visx-tooltip/src/floating/context.tsx Context for sharing tooltip state across primitives.
packages/visx-tooltip/src/floating/FloatingTooltip.tsx Primitive components (Root, Trigger, Portal, Positioner, Content, Arrow).
packages/visx-tooltip/src/floating/ChartTooltipContent.tsx Config-driven chart tooltip content renderer.
packages/visx-tooltip/src/floating/ChartTooltip.tsx Controlled chart tooltip component composing the primitives.
packages/visx-tooltip/src/floating/useChartTooltip.ts Convenience hook for chart-local tooltip state + anchor shorthand handling.
packages/visx-tooltip/test/floatingAnchors.test.ts Tests anchor conversion behavior.
packages/visx-tooltip/test/floatingPrimitives.test.tsx Tests hook behavior, middleware ordering, primitive rendering and attributes.
packages/visx-tooltip/test/floatingInteractions.test.tsx Tests trigger interactions + ARIA wiring and disabled-trigger behavior.
packages/visx-tooltip/test/ChartTooltipContent.test.tsx Tests config precedence, filtering, ordering, and custom renderers.
packages/visx-tooltip/test/ChartTooltip.test.tsx Tests chart hook behavior + portal/renderContent/prop precedence behavior.
packages/visx-tooltip/test/floating.typecheck.tsx Type-level fixture ensuring intended constraints on public APIs.
packages/visx-tooltip/test/tsconfig.floating-typecheck.json Dedicated TS config for the floating typecheck fixture.
packages/visx-tooltip/Readme.md Documents the new @visx/tooltip/floating surface and usage patterns.
packages/visx-tooltip/Handbook.md Detailed handbook covering patterns, anchors, middleware, and styling contracts.
MIGRATION.md Adds a 4.1 migration note for the new additive @visx/tooltip/floating APIs.

馃挕 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/visx-tooltip/src/floating/FloatingTooltip.tsx
@hshoff
hshoff merged commit b2254ab into master Jun 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants