Skip to content
Component

Animated Background

A shared highlight that glides between hovered or selected items, for navs and segmented controls.

Installation

terminal
npx shadcn@latest add https://ui.thilina.dev/r/animated-background.json

Usage

components/nav.tsx
import { AnimatedBackground } from "@/components/animated-background";

export function Nav() {
  return (
    <AnimatedBackground className="bg-accent rounded-md" enableHover>
      {["Overview", "Analytics", "Settings"].map((item) => (
        <button key={item} data-id={item} className="px-3 py-1.5 text-sm">
          {item}
        </button>
      ))}
    </AnimatedBackground>
  );
}

Every direct child needs a unique data-id. With enableHover the highlight follows the pointer; without it, the highlight moves on click and behaves like a segmented control. Children receive data-checked="true" while active, so you can style the selected state with data-[checked=true]: utilities.

Props

PropTypeDefaultDescription
childrenReactElement[]-Items to track. Each needs a unique data-id attribute.
classNamestring-Classes for the sliding highlight layer itself.
defaultValuestring | null-The data-id that starts highlighted.
onValueChange(id: string | null) => void-Called when the active item changes.
enableHoverbooleanfalseMove the highlight on hover instead of click.
transitionTransition-Motion transition for the glide between items.

Accessibility

The highlight is a purely visual layer; your children stay real buttons or links with their own semantics and focus behavior. Under prefers-reduced-motion the highlight still tracks the active item, it just jumps instantly instead of gliding.

Command Palette

Search for a command to run...