Gooey Navbar Menu

A spring-animated navbar menu with a gooey SVG-filtered background that connects the active trigger and dropdown panel.

Installation

Pro components require registry authentication. Add your Unlumen UI Pro key as UNLUMEN_LICENSE_KEY in your .env.local file and follow the setup guide.

File Structure

gooey-navbar-menu.tsx

Usage

import {
  GooeyNavbarMenu,
  GooeyNavbarMenuContent,
  GooeyNavbarMenuItem,
  GooeyNavbarMenuLink,
  GooeyNavbarMenuList,
  GooeyNavbarMenuTrigger,
} from "@/components/unlumen-ui/gooey-navbar-menu";

const contentHighlightClassName =
  "bg-primary/10 rounded-lg ring-1 ring-primary/15";

export default function Example() {
  return (
    <GooeyNavbarMenu
      viewportClassName="bg-surface border-none shadow-none"
      gooeyClassName="bg-surface rounded-xl"
      gooeyStrength={12}
    >
      <GooeyNavbarMenuList>
        <GooeyNavbarMenuItem value="products">
          <GooeyNavbarMenuTrigger>Products</GooeyNavbarMenuTrigger>
          <GooeyNavbarMenuContent
            highlightClassName={contentHighlightClassName}
          >
            <div className="grid w-[400px] grid-cols-2 gap-1">
              <GooeyNavbarMenuLink href="/analytics">
                <span className="text-sm font-medium">Analytics</span>
                <span className="text-muted-foreground text-xs">
                  Understand your data flow.
                </span>
              </GooeyNavbarMenuLink>
              <GooeyNavbarMenuLink href="/automation">
                <span className="text-sm font-medium">Automation</span>
                <span className="text-muted-foreground text-xs">
                  Streamline workflows.
                </span>
              </GooeyNavbarMenuLink>
            </div>
          </GooeyNavbarMenuContent>
        </GooeyNavbarMenuItem>

        <GooeyNavbarMenuItem>
          <GooeyNavbarMenuLink
            href="/pricing"
            className="px-4 py-2 text-sm font-medium"
          >
            Pricing
          </GooeyNavbarMenuLink>
        </GooeyNavbarMenuItem>
      </GooeyNavbarMenuList>
    </GooeyNavbarMenu>
  );
}

API Reference

GooeyNavbarMenu

viewport?
boolean
true

When true, renders content inside the shared morphing viewport. The gooey bridge is only rendered when the shared viewport is enabled.

viewportClassName?
string

Additional classes applied to the morphing viewport.

gooey?
boolean
true

When true, renders the SVG-filtered background that connects the active trigger and shared viewport.

gooeyClassName?
string

Additional classes applied to the gooey background shapes. Match this to the viewport background for the cleanest merge.

gooeyFilterId?
string

Custom SVG filter id used by the gooey background. Useful when you need a stable id.

gooeyStrength?
number
12

Blur strength used by the gooey SVG filter. Higher values create a stronger merge between shapes.

springBounce?
number
0

Bounce used by the spring transition for the viewport, bridge, and content animations.

springStiffness?
number
350

Stiffness used by the spring transition for the viewport, bridge, and content animations.

springDamping?
number
32

Damping used by the spring transition for the viewport, bridge, and content animations.

value?
string

Controlled active item value. Use an empty string to close the menu.

onValueChange?
(value: string) => void

Callback fired when the active item value changes.

className?
string

Additional classes applied to the root element.

GooeyNavbarMenuList

className?
string

Additional classes applied to the list element.

highlightClassName?
string

Additional classes applied to the hover highlight rendered behind trigger items.

GooeyNavbarMenuItem

value?
string

Unique identifier for this item. Required when the item has a Trigger + Content pair.

className?
string

Additional classes applied to the list item.

GooeyNavbarMenuTrigger

className?
string

Additional classes applied to the trigger button.

children?
React.ReactNode

Trigger content.

GooeyNavbarMenuContent

Renders the panel shown when the parent item's trigger is active. Must be placed inside a GooeyNavbarMenuItem that has a value prop. The content is rendered into the morphing container, so its width drives the container and gooey bridge animation.

className?
string

Additional classes applied to the content wrapper.

highlightClassName?
string

Additional classes applied to the hover highlight rendered behind links inside the content.

innerClassName?
string

Additional classes applied to the inner content container.

GooeyNavbarMenuLink

href?
string

Destination URL for the anchor.

className?
string

Additional classes applied to the link.

children?
React.ReactNode

Link content.

Notes

  • Gooey bridge: the active trigger and shared viewport are connected by an SVG-filtered background layer. Use gooeyClassName to match the viewport color.
  • Shared viewport: with viewport enabled, open content is rendered inside one morphing viewport that animates width, height, opacity, and scale.
  • Direction-aware transitions: switching between menus slides content horizontally based on whether the new item is to the left or right of the previous one.
  • Controlled mode: pass value and onValueChange to control the active item from outside the component.
  • Overflow clamping: the dropdown automatically stays within its nearest clipping ancestor — no configuration needed when the menu is inside a constrained container like a preview panel or modal.

Credits

Built by leo.

Keep in mind

Most components on this site are inspired by or recreated from existing work across the web. I'm not here to take credit; just to learn, experiment, and sometimes push things a bit further. If something looks familiar and I forgot to mention you, reach out and I'll fix that right away.