Overlays
IHoverCard
A preview of what a link points at, shown when the pointer rests on it.
Reviewed by Avery Lang on 12 March.
Which of the three
Three components anchor a panel to something on the page, and they are not interchangeable.
| Opens on | For | |
|---|---|---|
ITooltip | Hover and focus | A short label naming a control |
IHoverCard | Hover and focus | A preview: rich, and safe to skip |
IPopover | Click | Content the reader has to be able to operate |
The line that matters is whether anything is lost by never seeing it. A hover card is summoned by hover or focus, so a touch user never gets one — nothing inside it may be the only route to an action or the only copy of a fact. Put a link in it by all means; do not put the only link in it.
Delays
openDelay is how long the pointer must rest before the card appears, and closeDelay is the grace period after it leaves. The second one is not padding: it is what lets the pointer travel from the trigger onto the card without the card disappearing under it.
The defaults are 700ms and 300ms. Zero is worth avoiding on anything in a list: every trigger the pointer crosses on its way somewhere else will fire.
Placement
side, align and sideOffset work as they do on IPopover, and arrow draws the pointer against the trigger.
Size
width and padding match the popover's, and width="none" lets the content size itself — for a preview image, or anything that already knows how wide it is.
Controlling it
v-model:open works if you need the state, though a hover card rarely does — it is the one overlay that manages itself.
<script setup lang="ts">
const open = ref(false)
</script>
<template>
<IHoverCard v-model:open="open">
…
</IHoverCard>
</template>Touch
enableTouch opens the card on a tap as well. It is off by default and worth leaving off: a tap has no hover before it, so the card ends up competing with whatever the trigger does when tapped — usually following a link. If the content matters on a phone, it belongs on the page rather than behind a gesture.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state; use v-model:open |
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Which side of the trigger to anchor to |
align | 'start' | 'center' | 'end' | 'center' | Alignment along that side |
sideOffset | number | 6 | Gap between trigger and card, in px |
arrow | boolean | false | Draw the pointer against the trigger |
openDelay | number | 700 | Rest time before opening, in ms |
closeDelay | number | 300 | Grace period after leaving, in ms |
enableTouch | boolean | false | Also open on a tap |
padding | 'none' | 'sm' | 'md' | 'lg' | 'md' | Inset around the content |
width | 'none' | 'sm' | 'md' | 'lg' | 'md' | Card width; none sizes to content |
unstyled | boolean | — | Drop built-in classes |
class | string | — | Classes for the card |
ui | { content?, arrow? } | — | Per-element class overrides |
Slots
| Slot | Description |
|---|---|
trigger | What the card hangs off. Rendered as-is — pass a link or a button |
| default | The card's content |