Highlight

A background that glides between items on click, on hover or with a controlled value.

"use client"

import { Highlight } from "@animate-ui/react/primitives/effects/highlight"

const TABS = [
  { value: "overview", title: "Overview" },
  { value: "activity", title: "Activity" },
  { value: "settings", title: "Settings" },
]

export default function HighlightDemo({
  mode = "children",
  exitDelay = 200,
  hover = false,
}: {
  mode?: "children" | "parent"
  exitDelay?: number
  hover?: boolean
}) {
  const items = TABS.map((tab) => (
    <button
      key={tab.value}
      type="button"
      data-value={tab.value}
      className="flex h-8 items-center justify-center rounded-full px-4 text-sm text-muted-foreground transition-all duration-300 data-[active=true]:font-medium data-[active=true]:text-foreground"
    >
      {tab.title}
    </button>
  ))
  const props = {
    exitDelay,
    hover,
    defaultValue: TABS[0]?.value,
    className: "inset-0 rounded-full bg-accent",
  }

  return (
    <div className="flex rounded-full border p-1">
      {mode === "parent" ? (
        <Highlight mode="parent" containerClassName="flex" {...props}>
          {items}
        </Highlight>
      ) : (
        <Highlight {...props}>{items}</Highlight>
      )}
    </div>
  )
}

Installation

npm install @animate-ui/react motion
pnpm add @animate-ui/react motion
yarn add @animate-ui/react motion
bun add @animate-ui/react motion

Usage

import { Highlight } from '@animate-ui/react/primitives/effects/highlight';

export function Segmented() {
  return (
    <Highlight defaultValue="overview" className="rounded-full bg-accent">
      <button data-value="overview">Overview</button>
      <button data-value="activity">Activity</button>
      <button data-value="settings">Settings</button>
    </Highlight>
  );
}

Each child is wrapped in a HighlightItem. Its value comes from id, value, data-value or the child's id, in that order. Items receive data-active="true" when highlighted, for styling.

Controlled items

With controlledItems, place HighlightItems anywhere inside Highlight instead of as direct children.

<Highlight controlledItems hover className="rounded-md bg-accent">
  <nav>
    <HighlightItem value="docs">
      <a href="/docs">Docs</a>
    </HighlightItem>
    <HighlightItem value="blog">
      <a href="/blog">Blog</a>
    </HighlightItem>
  </nav>
</Highlight>

Modes

  • children (default): the highlight is rendered inside the active item and moves with a shared layout animation. Prefer it in most cases.
  • parent: the highlight is rendered once in a container, and its position and size spring to the active item. Use it when the items clip or stack in a way that hides the children highlight.
<Highlight mode="parent" containerClassName="flex" className="bg-accent">
  <div data-value="a">A</div>
  <div data-value="b">B</div>
</Highlight>

Animation

  • In children mode, the highlight slides to the new item on a spring (stiffness 500, damping 40) with a shared layout animation: the previous item hands its surface over in the same frame, so one surface slides at full opacity. It fades in when nothing was highlighted, and fades out after exitDelay (200ms) when no item takes it.
  • In parent mode, a single highlight springs its top, left, width and height to the active item, fades in when it appears, and fades out exitDelay after the last item is left.
  • Leaving with hover fades it out after exitDelay, so moving between items doesn't flicker.
  • hover only applies to pointers that can hover (mouse, trackpad): touch taps never leave a highlight stuck.
  • In parent mode, forceUpdateBounds measures the active item on every frame, so the highlight follows it whatever moves it (scrolling, resizing, an animated container).
  • <AnimateUIProvider tempo> paces the transition and exitDelay.
  • Under reduced motion, the highlight jumps to the new item and only fades.

API Reference

Highlight

PropTypeDefault
as?
React.ElementType'div'
mode?
'children' | 'parent''children'
value?
string | null-
defaultValue?
string | null-
onValueChange?
(value: string | null) => void-
className?
string-
style?
React.CSSProperties-
transition?
Transition{ type: 'spring', stiffness: 500, damping: 40 }
hover?
booleanfalse
click?
booleantrue
disabled?
booleanfalse
enabled?
booleantrue
exitDelay?
number200
controlledItems?
boolean-
itemsClassName?
string-

Parent mode

PropTypeDefault
boundsOffset?
Partial<{ top: number; left: number; width: number; height: number }>-
containerClassName?
string-
forceUpdateBounds?
boolean-

HighlightItem

PropTypeDefault
as?
React.ElementType'div'
children
React.ReactElement-
id?
string-
value?
string-
className?
string-
activeClassName?
string-
style?
React.CSSProperties-
transition?
Transition-
disabled?
boolean-
exitDelay?
number-
asChild?
booleanfalse
forceUpdateBounds?
boolean-

useHighlight

Returns the state of the closest Highlight: activeValue, setActiveValue, mode, and its options.

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/18/2026

On this page