Highlight

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

<script setup lang="ts">
import { Highlight } from '@animate-ui/vue/primitives/effects/highlight'
import { computed } from 'vue'

const props = withDefaults(
  defineProps<{
    mode?: 'children' | 'parent'
    exitDelay?: number | string
    hover?: boolean | string
  }>(),
  { mode: 'children', exitDelay: 200, hover: false },
)

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

const shared = computed(() => ({
  exitDelay: Number(props.exitDelay),
  hover: props.hover === true || props.hover === 'true',
  defaultValue: TABS[0]?.value,
  class: 'inset-0 rounded-full bg-accent',
}))
</script>

<template>
  <div class="flex rounded-full border p-1">
    <Highlight
      :key="mode"
      :mode="mode"
      :container-class-name="mode === 'parent' ? 'flex' : undefined"
      v-bind="shared"
    >
      <button
        v-for="tab in TABS"
        :key="tab.value"
        type="button"
        :data-value="tab.value"
        class="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>
    </Highlight>
  </div>
</template>

Installation

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

Usage

<script setup lang="ts">
import { Highlight } from '@animate-ui/vue/primitives/effects/highlight';
</script>

<template>
  <Highlight default-value="overview" class="rounded-full bg-accent">
    <button data-value="overview">Overview</button>
    <button data-value="activity">Activity</button>
    <button data-value="settings">Settings</button>
  </Highlight>
</template>

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 controlled-items, place HighlightItems anywhere inside Highlight instead of as direct children.

<Highlight controlled-items hover class="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" container-class-name="flex" class="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 exit-delay (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 exit-delay after the last item is left.
  • Leaving with hover fades it out after exit-delay, 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, force-update-bounds 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 exit-delay.
  • Under reduced motion, the highlight jumps to the new item and only fades.

API Reference

Highlight

PropTypeDefault
as?
string | Component'div'
mode?
'children' | 'parent''children'
v-model?
string | null-
default-value?
string | null-
@update:model-value?
(value: string | null) => void-
class?
string-
style?
StyleValue-
transition?
Transition{ type: 'spring', stiffness: 500, damping: 40 }
hover?
booleanfalse
click?
booleantrue
disabled?
booleanfalse
enabled?
booleantrue
exit-delay?
number200
controlled-items?
boolean-
items-class-name?
string-

Parent mode

PropTypeDefault
bounds-offset?
Partial<{ top: number; left: number; width: number; height: number }>-
container-class-name?
string-
force-update-bounds?
boolean-

HighlightItem

PropTypeDefault
as?
string | Component'div'
#default
slot-
id?
string-
value?
string-
class?
string-
active-class-name?
string-
style?
StyleValue-
transition?
Transition-
disabled?
boolean-
exit-delay?
number-
as-child?
booleanfalse
force-update-bounds?
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/23/2026