Morphiq

Components / Ferrofluid Nav

Ferrofluid Nav

A nav whose active pill does not slide. Two capsule fields are blended with a polynomial smooth-minimum, so below the blend radius they fuse into one surface with a real neck between them — the pill stretches out of the item it is leaving and gathers into the one it is entering. A translate has no surface tension; this does.

Usage

import FerrofluidNav from '@/components/ferrofluid-nav'

<FerrofluidNav
  items={[
    { id: 'overview', label: 'Overview' },
    { id: 'components', label: 'Components' },
  ]}
  blend={26}
  stretch={34}
  onSelect={(id) => setTab(id)}
/>

Installation

npx shadcn@latest add https://morphiq.prathampatel.design/r/ferrofluid-nav.json

Model

smin(a, b, k) = min(a, b) − h²k/4,  h = max(k − |a − b|, 0)/k

a, b distances to the two blobs · k the blend radius

Props

PropertyTypeDefaultDescription
itemsFerrofluidNavItem[][]The nav's items, in order. Each becomes a real role="tab" button.
activeIdstring—Controlled selection.
defaultActiveIdstring—Starting selection when uncontrolled. Defaults to the first item.
onSelect(id: string, item: FerrofluidNavItem, index: number) => void—Called on click, tap, or arrow / Home / End keys, with the item and its index.
blendnumber26Blend radius across the neck, in px, before speed adds to it — how readily the two ends fuse once they are drawn apart. It never inflates the resting pill. Default 26.
stretchnumber34Extra blend radius at full travel speed, in px, so a fast body holds together across a longer neck. Default 34.
paddingnumber10How far the resting pill overhangs an item's box, in px (0 to 120). Default 10.
reachnumber6How far the fluid is drawn toward a hovered item, in px; doubled while it is pressed. 0 turns it off. Default 6.
stiffnessnumber210Spring constant for the leading end's travel, per s². Default 210.
dampingnumber22Damping coefficient for that spring, per s. Default 22 (ζ ≈ 0.76).
colorstring—Fill colour, any CSS colour. Overrides the --ffn-fill custom property.