A background that glides between items on click, on hover or with a controlled value.
Installation
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 thechildrenhighlight.
<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
childrenmode, 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 afterexit-delay(200ms) when no item takes it. - In
parentmode, a single highlight springs its top, left, width and height to the active item, fades in when it appears, and fades outexit-delayafter the last item is left. - Leaving with
hoverfades it out afterexit-delay, so moving between items doesn't flicker. hoveronly applies to pointers that can hover (mouse, trackpad): touch taps never leave a highlight stuck.- In
parentmode,force-update-boundsmeasures the active item on every frame, so the highlight follows it whatever moves it (scrolling, resizing, an animated container). <AnimateUIProvider :tempo>paces the transition andexit-delay.- Under reduced motion, the highlight jumps to the new item and only fades.
API Reference
Highlight
| Prop | Type | Default |
|---|---|---|
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? | boolean | false |
click? | boolean | true |
disabled? | boolean | false |
enabled? | boolean | true |
exit-delay? | number | 200 |
controlled-items? | boolean | - |
items-class-name? | string | - |
Parent mode
| Prop | Type | Default |
|---|---|---|
bounds-offset? | Partial<{ top: number; left: number; width: number; height: number }> | - |
container-class-name? | string | - |
force-update-bounds? | boolean | - |
HighlightItem
| Prop | Type | Default |
|---|---|---|
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? | boolean | false |
force-update-bounds? | boolean | - |
useHighlight
Returns the state of the closest Highlight: activeValue, setActiveValue, mode, and its options.