For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.
1
Sponsor

Fluid Hover

One highlight glides to the nearest item across lists, tabs, and grids.

Fluid Hover treats a group of items as one continuous pointer target. Instead of each item independently turning its background on and off, one highlight moves between them.

Ordinary hover can flicker off in the gaps between rows or cards. Here, the nearest eligible item remains the visual target while the pointer is inside the group. That makes a tightly related list feel connected, including the small spaces between its items.

Hover is not selection

The highlight answers “which item is under my pointer?” It does not mean that item has been selected, and it does not move keyboard focus. In the preview, the selected folder changes only after activation; moving the pointer merely moves the highlight.

Use this for related rows, navigation, menus, and grids where a shared highlight makes the target clearer. Keep ordinary hover for unrelated controls. For tables or consequential actions, disable gap-click routing so empty space does not activate a nearby item.

The hook calculates the target and geometry; FluidHoverHighlight draws it with the shared Motion preset. This separation lets the same behavior work with ordinary buttons, semantic table rows, or Base UI menu items without replacing their accessibility behavior.

Move slowly across the gaps in the vertical list, then compare horizontal tabs and the grid. Touch input does not create a persistent hover highlight.

Preview

Selected: Inbox

Horizontal tabs

Your workspace at a glance.

Grid

Selected: Inbox

Installation

Use useFluidHover, FluidHoverHighlight, lib/motion.ts, and lib/shape-context.tsx. The starter includes Motion already.

Usage

const ref = useRef<HTMLDivElement>(null);
const hover = useFluidHover(ref, { axis: "y" });
 
<div ref={ref} {...hover.handlers} className="relative">
  <FluidHoverHighlight hover={hover} />
  {items.map((item, index) => (
    <button key={item.id} ref={(node) => hover.registerItem(index, node)}>
      {item.label}
    </button>
  ))}
</div>;

API Reference

PropMeaning
hoverReturn value of useFluidHover
hiddenHide without discarding the hook state
transitionMotion transition or false to snap
classNameAdditional highlight classes

The Hook owns registration, measurement, pointer tracking, and selection. The Foundation only draws the highlight with the fast spring. A new pointer entry fades in at its target instead of flying in from an old location. Reduced motion snaps position while retaining a short opacity fade. Touch does not synthesize hover.

Selected: Inbox

Mail folders
FolderMessages
24
3
18
42

Selected: Inbox

Use axis y for menus and table rows, x for horizontal lists, and xy for grids. Register the actual row element. Keep native table markup and draw a decorative overlay in its positioned container. Base UI retains menu navigation and focus management; do not replace it with pointer logic. Set gapClick={false} for tables or destructive actions where empty space must stay inert.