Hover Card

For sighted users to preview content available behind a link.

<script setup lang="ts">
import { Calendar03Icon } from "@hugeicons/core-free-icons"
import { HugeiconsIcon } from "@hugeicons/vue"
import {
  Avatar,
  AvatarFallback,
  AvatarImage,
} from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from '@/components/ui/hover-card'

withDefaults(
  defineProps<{
    side?: 'top' | 'right' | 'bottom' | 'left'
    sideOffset?: number
    align?: 'start' | 'center' | 'end'
    alignOffset?: number
    followCursor?: boolean | 'x' | 'y'
  }>(),
  { side: 'bottom', sideOffset: 4, align: 'center', alignOffset: 0, followCursor: false },
)
</script>

<template>
  <HoverCard :follow-cursor="followCursor">
    <HoverCardTrigger as-child>
      <Button variant="link">
        @nuxt
      </Button>
    </HoverCardTrigger>
    <HoverCardContent class="w-80" :side="side" :side-offset="Number(sideOffset)" :align="align" :align-offset="Number(alignOffset)">
      <div class="flex justify-between space-x-4">
        <Avatar>
          <AvatarImage src="/avatars/vercel.png" />
          <AvatarFallback>VC</AvatarFallback>
        </Avatar>
        <div class="space-y-1">
          <h4 class="text-sm font-semibold">
            @nuxt
          </h4>
          <p class="text-sm">
            The Vue Framework – The Progressive Web Framework.
          </p>
          <div class="flex items-center pt-2">
            <HugeiconsIcon :icon="Calendar03Icon" :stroke-width="2" class="mr-2 h-4 w-4 opacity-70" />
            <span class="text-xs text-muted-foreground">
              Joined December 2021
            </span>
          </div>
        </div>
      </div>
    </HoverCardContent>
  </HoverCard>
</template>

Installation

Install the packages

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

Add the shadcn-vue component

npx shadcn-vue@latest add hover-card
pnpm dlx shadcn-vue@latest add hover-card
yarn dlx shadcn-vue@latest add hover-card
bun x shadcn-vue@latest add hover-card

Animate it

The CLI finds your shadcn-vue components through components.json, swaps their primitive imports for Animate UI's and removes the CSS animation classes Motion replaces.

npx @animate-ui/cli@latest animate hover-card
pnpm dlx @animate-ui/cli@latest animate hover-card
yarn dlx @animate-ui/cli@latest animate hover-card
bun x @animate-ui/cli@latest animate hover-card

Usage

<script setup lang="ts">
import {
  HoverCardContent,
  HoverCardPortal,
  HoverCardRoot,
  HoverCardTrigger,
} from '@animate-ui/vue/primitives/reka-ui';
</script>

<template>
  <HoverCardRoot>
    <HoverCardTrigger href="https://animate-ui.com"
      >@animate_ui</HoverCardTrigger
    >
    <HoverCardPortal>
      <HoverCardContent :side-offset="4"
        >Animated drop-in primitives for Reka UI.</HoverCardContent
      >
    </HoverCardPortal>
  </HoverCardRoot>
</template>

Animation

The motion of Animate UI's React Hover Card:

  • Content grows from 0.8 and fades in, from the trigger (--reka-hover-card-content-transform-origin), on a spring (stiffness 400, damping 29) that overshoots a little before it settles.
  • Once reka-ui's close-delay is over, it closes the same way: it shrinks back to 0.8 on the same spring while it fades out, then unmounts.
  • reka-ui only opens it for mouse-like pointers: a tap on a touch screen follows the link, nothing sticks.
  • With force-mount (on the Content or the Portal), the closed content stays in the DOM: it plays its exit, then is hidden and inert.
  • Reopening while it closes picks up from where it is, on the same spring.
  • Open from the start (default-open), it plays the same entrance on page load.
  • With follow-cursor on the Root, the content leans towards the pointer while it moves over the trigger, by half its offset from the trigger's center, on a spring (stiffness 200, damping 17): on both axes, or only 'x' or 'y'. Under reduced motion it follows without the spring.
  • Under reduced motion, it only fades (no scale).

API Reference

Every part takes exactly the props of reka-ui's Hover Card. Animate UI adds the animation props below.

HoverCardRoot

reka-ui props, plus:

PropTypeDefault
follow-cursor?
boolean | 'x' | 'y'false
follow-cursor-spring-options?
SpringOptions{ stiffness: 200, damping: 17 }

HoverCardTrigger, HoverCardPortal, HoverCardArrow

reka-ui props only. They are not animated.

HoverCardContent

reka-ui props, plus:

PropTypeDefault
transition?
Transition{ type: 'spring', stiffness: 400, damping: 29 }
exit-transition?
Transitiontransition

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

Last updated: 10/23/2026