Skip to main content

A hover card lets sighted users preview content behind a link.

Loading...

Features

  • Customize side, alignment, offsets
  • Optionally render a pointing arrow
  • Supports custom open and close delays
  • Opens on hover only
  • Ignored by screen readers

Installation

Install the hover card package:

npm install @zag-js/hover-card @zag-js/vue # or yarn add @zag-js/hover-card @zag-js/vue

Anatomy

To set up the hover card correctly, you'll need to understand its anatomy and how we name its parts.

Each part includes a data-part attribute to help identify them in the DOM.

Usage

Import the hover card package:

import * as hoverCard from "@zag-js/hover-card"

The hover card package exports two key functions:

  • machine - State machine logic.
  • connect - Maps machine state to JSX props and event handlers.

Then use the framework integration helpers:

<script setup> import * as hoverCard from "@zag-js/hover-card" import { normalizeProps, useMachine } from "@zag-js/vue" import { computed, Teleport } from "vue" const service = useMachine(hoverCard.machine, { id: "1" }) const api = computed(() => hoverCard.connect(service, normalizeProps)) </script> <template> <a href="https://twitter.com/zag_js" target="_blank" v-bind="api.getTriggerProps()" > Twitter </a> <Teleport to="body" v-if="api.open"> <div v-bind="api.getPositionerProps()"> <div v-bind="api.getContentProps()"> <div v-bind="api.getArrowProps()"> <div v-bind="api.getArrowTipProps()" /> </div> Twitter Preview </div> </div> </Teleport> </template>

Setting the initial state

Set defaultOpen to true to start with the hover card open.

const service = useMachine(hoverCard.machine, { defaultOpen: true, })

Controlled open state

Use open and onOpenChange to control visibility externally.

const service = useMachine(hoverCard.machine, { open, onOpenChange(details) { setOpen(details.open) }, })

Customizing open and close delays

Use openDelay and closeDelay to control hover timing.

const service = useMachine(hoverCard.machine, { openDelay: 300, closeDelay: 150, })

Positioning the hover card

Use positioning to control placement and offsets.

const service = useMachine(hoverCard.machine, { positioning: { placement: "bottom-start", offset: { mainAxis: 8, crossAxis: 4 }, }, })

Disabling the hover card

Set disabled to true to prevent it from opening.

const service = useMachine(hoverCard.machine, { disabled: true, })

Listening for open state changes

When the hover card is opened or closed, the onOpenChange callback is invoked.

const service = useMachine(hoverCard.machine, { onOpenChange(details) { // details => { open: boolean } console.log("hovercard is:", details.open ? "opened" : "closed") }, })

Styling guide

Each part includes a data-part attribute you can target in CSS.

[data-part="trigger"] { /* styles for trigger */ } [data-part="content"] { /* styles for content */ }

Open and closed state

The hover card exposes a data-state attribute that can be used to style the hover card based on its open-close state.

[data-part="trigger"][data-state="open|closed"] { /* styles for open or closed state */ } [data-part="content"][data-state="open|closed"] { /* styles for open or closed state */ }

Arrow

You can use CSS variables to style the arrow.

[data-part="arrow"] { /* styles for arrow */ --arrow-background: white; --arrow-size: 8px; }

Methods and Properties

Machine Context

The hover card machine exposes the following context properties:

  • idsPartial<{ trigger: string; content: string; positioner: string; arrow: string; }>The ids of the elements in the popover. Useful for composition.
  • onOpenChange(details: OpenChangeDetails) => voidFunction called when the hover card opens or closes.
  • openDelaynumberThe duration from when the mouse enters the trigger until the hover card opens.
  • closeDelaynumberThe duration from when the mouse leaves the trigger or content until the hover card closes.
  • disabledbooleanWhether the hover card is disabled
  • openbooleanThe controlled open state of the hover card
  • defaultOpenbooleanThe initial open state of the hover card when rendered. Use when you don't need to control the open state of the hover card.
  • positioningPositioningOptionsThe user provided options used to position the popover content
  • dir"ltr" | "rtl"The document's text/writing direction.
  • idstringThe unique identifier of the machine.
  • getRootNode() => ShadowRoot | Node | DocumentA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.
  • onPointerDownOutside(event: PointerDownOutsideEvent) => voidFunction called when the pointer is pressed down outside the component
  • onFocusOutside(event: FocusOutsideEvent) => voidFunction called when the focus is moved outside the component
  • onInteractOutside(event: InteractOutsideEvent) => voidFunction called when an interaction happens outside the component

Machine API

The hover card api exposes the following methods:

  • openbooleanWhether the hover card is open
  • setOpen(open: boolean) => voidFunction to open the hover card
  • reposition(options?: Partial<PositioningOptions>) => voidFunction to reposition the popover

Data Attributes

Trigger
data-scope
hover-card
data-part
trigger
data-placement
The placement of the trigger
data-state
"open" | "closed"
Content
data-scope
hover-card
data-part
content
data-state
"open" | "closed"
data-nested
popover
data-has-nested
popover
data-placement
The placement of the content

CSS Variables

Arrow
--arrow-size
The size of the arrow
--arrow-size-half
Half the size of the arrow
--arrow-background
Use this variable to style the arrow background
--arrow-offset
The offset position of the arrow
Positioner
--reference-width
The width of the reference element
--reference-height
The height of the root
--available-width
The available width in viewport
--available-height
The available height in viewport
--x
The x position for transform
--y
The y position for transform
--z-index
The z-index value
--transform-origin
The transform origin for animations
Content
--layer-index
The index of the dismissable in the layer stack
--nested-layer-count
The number of nested hover-cards
Backdrop
--layer-index
The index of the dismissable in the layer stack

Accessibility

Keyboard Interactions

The hover card is intended for mouse users only so will not respond to keyboard navigation.

Edit this page on GitHub