GooeyNav
gooey-navMoves a liquid-like selection indicator between navigation items.
Usage
Basic usage
Just pass in the navigation item array. When you click to switch, the pill will slide and emit colored particles.
<div
className="flex h-40 items-center justify-center rounded-xl"
style={{ background: "oklch(0.16 0.02 265)" }}
>
<GooeyNav
items={[
{ label: "Home", href: "#" },
{ label: "Product", href: "#" },
{ label: "Documentation", href: "#" },
{ label: "About", href: "#" },
]}
/>
</div>Specify initial selection
Set uncontrolled initial highlight position via initialActiveIndex.
<GooeyNav items={items} initialActiveIndex={2} />Dense particles
Increase the particleCount and increase the explosion radius to make the explosion more brilliant.
<GooeyNav
items={items}
particleCount={24}
particleDistances={[110, 14]}
/>Warm color palette
colors Get the Hulian chart token serial number and customize the particle color matching.
<GooeyNav items={items} colors={[3, 4, 5, 3]} initialActiveIndex={1} />Pill slide only (particles off)
particleCount={0} Turns off the burst, leaving only the smooth sliding of the pill.
<GooeyNav items={items} particleCount={0} />When to use
Use GooeyNav for a highly animated horizontal navigation bar with a ceremonial particle burst, usually on a marketing page or portfolio. Use NavigationMenu or NavMenu when dropdowns, hierarchy, and keyboard conventions matter most, or Navbar for structural header layout. Set particleCount={0} for a sliding pill closer to PillNav.
Import
import { GooeyNav } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| items* | GooeyNavItem[] | - | At least one { label, href? } entry; href defaults to "#". |
| initialActiveIndex | number | 0 | Initial selection in uncontrolled mode. |
| activeIndex | number | - | Controlled selected index. |
| animationTime | number | 600 | Particle burst duration in milliseconds. |
| particleCount | number | 14 | Particles per switch; zero keeps only the pill. |
| particleDistances | [number, number] | [86, 12] | Initial burst and return radii in pixels. |
| colors | number[] | [1, 2, 3, 1, 4] | Chart-token indices from 1 through 5. |
| className | string | - | Root class name. |
| style | CSSProperties | - | Root inline styles. |
GooeyNavItem
| Name | Type | Default | Description |
|---|---|---|---|
| label * | string | - | Displayed text. |
| href | string | "#" | Link destination. |
Events
| Event | Type | Description |
|---|---|---|
| onChange | (index: number) => void | Called by click, Enter|Space. |
Example
<GooeyNav items={[{ label: "Home", href: "#" }, { label: "Product", href: "#" }, { label: "Docs", href: "#" }, { label: "About", href: "#" }]} />Pill only:
<GooeyNav items={items} particleCount={0} />Usage guidelines
- With activeIndex, update parent state from onChange. Controlled state does not update internally.
- The container must be dark and
overflow-hidden: the pill and particles fuse through blur and contrast, so light backgrounds and poor clipping ruin the effect. - Because the container is always dark, this component uses fixed black and white steps (
text-white/80,bg-white) instead of theme tokens. That is deliberate, not a missing token: following the page theme would make--color-foregroundresolve togray-900in light mode, turning inactive items into dark text on a dark bar. On light surfaces the reverse happens, so reach for PillNav or NavMenu instead. - Reduced motion skips particles and spring travel while preserving selection.
Related
Navbar · BeianFooter · NavMenu · NavigationMenu · Menu · Menubar
Playground
<div className="flex h-40 items-center justify-center rounded-xl"
style={{ background: "oklch(0.16 0.02 265)" }}>
<GooeyNav
items={[
{ label: "Home", href: "#" },
{ label: "Product", href: "#" },
{ label: "Documentation", href: "#" },
{ label: "About", href: "#" },
]}
particleCount={14}
animationTime={600}
initialActiveIndex={0}
/>
</div>