Anatomy of the GodUI Hover Card
A preview that grows out of the link it describes, and why its delays matter more than its curve.
↓Scroll to step through it
Grows from the link
The card uses the shared godui-popover-in keyframe. Radix publishes the
point of the card nearest the link as
--radix-hover-card-content-transform-origin, so the 0.96 → 1 scale grows
from there, and the per-side variables add a 4px drift away from the link.
Delays do the heavy lifting
A hover card shouldn't appear because the pointer passed over a link on the
way somewhere else. Radix waits openDelay (700ms by default) before
opening and closeDelay (300ms) before closing, so you can move from the
link into the card without it vanishing.
The animation only runs once those delays are over. It's 260ms on a snappy
spring in, 150ms on ease-out-expo out.
The result
Hover the link and wait for the card, then move into it, or Tab to the link to open it with the keyboard.
- opacity
- 0 → 1
- scale
- 0.96 → 1
- translate
- 0 -4px → 0 0
<HoverCardPrimitive.Contentdata-slot="hover-card-content"className={cn( "z-50 w-64 origin-(--radix-hover-card-content-transform-origin) … data-[side=bottom]:[--godui-enter-y:-0.25rem] data-[side=top]:[--godui-enter-y:0.25rem] … data-[state=open]:animate-godui-popover-in data-[state=closed]:animate-godui-popover-out", className,)}/>Anatomy of the GodUI Hover Card
A preview that grows out of the link it describes, and why its delays matter more than its curve.
- opacity
- 0 → 1
- scale
- 0.96 → 1
- translate
- 0 -4px → 0 0
<HoverCardPrimitive.Contentdata-slot="hover-card-content"className={cn( "z-50 w-64 origin-(--radix-hover-card-content-transform-origin) … data-[side=bottom]:[--godui-enter-y:-0.25rem] data-[side=top]:[--godui-enter-y:0.25rem] … data-[state=open]:animate-godui-popover-in data-[state=closed]:animate-godui-popover-out", className,)}/>Grows from the link
The card uses the shared godui-popover-in keyframe. Radix publishes the
point of the card nearest the link as
--radix-hover-card-content-transform-origin, so the 0.96 → 1 scale grows
from there, and the per-side variables add a 4px drift away from the link.
ease-spring-snappy
<HoverCard openDelay={700} closeDelay={300}>…</HoverCard>Delays do the heavy lifting
A hover card shouldn't appear because the pointer passed over a link on the
way somewhere else. Radix waits openDelay (700ms by default) before
opening and closeDelay (300ms) before closing, so you can move from the
link into the card without it vanishing.
The animation only runs once those delays are over. It's 260ms on a snappy
spring in, 150ms on ease-out-expo out.
The result
Hover the link and wait for the card, then move into it, or Tab to the link to open it with the keyboard.
What's animated
The entrance matches Popover: the card scales up from the edge touching the link and drifts 4px away from it.
| Interaction | Keyframe / mechanism | Properties | Easing | Duration |
|---|---|---|---|---|
Open (after openDelay) | godui-popover-in | opacity, scale 0.96 → 1 from the link, translate 4px → 0 | ease-spring-snappy | 260ms |
Close (after closeDelay) | godui-popover-out | the same, reversed | ease-out-expo | 150ms |
Why GPU-only
The card animates opacity, scale and translate, all composited. It uses
the same keyframe as Popover, so every floating surface in the library moves
alike.
Reduced motion
--godui-motion: 0 cancels the scale and drift, so the card only fades, in
150ms.
Replacing shadcn
npx shadcn add @godui/hover-card overwrites components/ui/hover-card.tsx.
Exports, props and data-slot attributes match shadcn/ui new-york-v4, so
existing imports keep working. It also installs godui-motion (easings,
keyframes, the FLIP hook) into your project.