Hover Card
A card that appears when a user hovers over an element.
@grizzly_codes
Staff Software Engineer working at vivenu GmbH
Joined December 2011
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.
Examples
Learn how to use the HoverCard
component in your project. Let's take a look at the most basic example:
import { HoverCard } from '@ark-ui/react/hover-card'
import { Portal } from '@ark-ui/react/portal'
export const Basic = () => (
<HoverCard.Root>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
)
import { HoverCard } from '@ark-ui/solid/hover-card'
import { Portal } from 'solid-js/web'
export const Basic = () => (
<HoverCard.Root>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
)
<script setup lang="ts">
import { HoverCard } from '@ark-ui/vue/hover-card'
</script>
<template>
<HoverCard.Root>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Teleport to="body">
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Teleport>
</HoverCard.Root>
</template>
Controlled HoverCard
The controlled HoverCard
component provides an interface for managing the state of the hover card using the open
and
onOpenChange
props:
import { HoverCard } from '@ark-ui/react/hover-card'
import { Portal } from '@ark-ui/react/portal'
import { useState } from 'react'
export const Controlled = () => {
const [isOpen, setOpen] = useState(false)
return (
<>
<button type="button" onClick={() => setOpen(!isOpen)}>
click me
</button>
<HoverCard.Root open={isOpen} onOpenChange={() => setOpen(false)}>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
</>
)
}
import { HoverCard } from '@ark-ui/solid/hover-card'
import { createSignal } from 'solid-js'
import { Portal } from 'solid-js/web'
export const Controlled = () => {
const [isOpen, setOpen] = createSignal(false)
return (
<>
<button type="button" onClick={() => setOpen(!isOpen)}>
click me
</button>
<HoverCard.Root open={isOpen()} onOpenChange={() => setOpen(false)}>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
</>
)
}
<script setup lang="ts">
import { HoverCard } from '@ark-ui/vue/hover-card'
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<button @click="() => (open = true)">Open Dialog</button>
<HoverCard.Root v-model:open="open">
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Teleport to="body">
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Teleport>
</HoverCard.Root>
</template>
Custom Positioning
The HoverCard
component can be customized in its placement and distance from the trigger element through the
positioning
prop:
import { HoverCard } from '@ark-ui/react/hover-card'
import { Portal } from '@ark-ui/react/portal'
export const Positioning = () => (
<HoverCard.Root positioning={{ placement: 'right', gutter: 12 }}>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
)
import { HoverCard } from '@ark-ui/solid/hover-card'
import { Portal } from 'solid-js/web'
export const Positioning = () => (
<HoverCard.Root positioning={{ placement: 'right', gutter: 12 }}>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
)
<script setup lang="ts">
import { HoverCard } from '@ark-ui/vue/hover-card'
</script>
<template>
<HoverCard.Root
:positioning="{
placement: 'right',
gutter: 12,
}"
>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Teleport to="body">
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Teleport>
</HoverCard.Root>
</template>
Render Prop Usage
The HoverCard
component can also accept a render prop, giving the user more control over rendering behavior. This is
useful for dynamically updating the trigger based on the state of the HoverCard
:
import { HoverCard } from '@ark-ui/react/hover-card'
import { Portal } from '@ark-ui/react/portal'
export const RenderProp = () => (
<HoverCard.Root>
<HoverCard.Context>
{(hoverCard) => <HoverCard.Trigger>Hover me {hoverCard.open ? '▲' : '▼'} </HoverCard.Trigger>}
</HoverCard.Context>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
)
import { HoverCard } from '@ark-ui/solid/hover-card'
import { Portal } from 'solid-js/web'
export const RenderProp = () => (
<HoverCard.Root>
<HoverCard.Context>
{(context) => <HoverCard.Trigger>Hover me {context().open ? '▲' : '▼'} </HoverCard.Trigger>}
</HoverCard.Context>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.Root>
)
<script setup lang="ts">
import { HoverCard } from '@ark-ui/vue/hover-card'
</script>
<template>
<HoverCard.Root>
<HoverCard.Context v-slot="hoverCard">
<HoverCard.Trigger>Hover me {{ hoverCard.open ? '▲' : '▼' }}</HoverCard.Trigger>
</HoverCard.Context>
<Teleport to="body">
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Teleport>
</HoverCard.Root>
</template>
Using the Root Provider
The RootProvider
component provides a context for the hover-card. It accepts the value of the useHover-card
hook.
You can leverage it to access the component state and methods from outside the hover-card.
import { HoverCard, useHoverCard } from '@ark-ui/react/hover-card'
import { Portal } from '@ark-ui/react/portal'
export const RootProvider = () => {
const hoverCard = useHoverCard()
return (
<>
<button onClick={() => hoverCard.setOpen(true)}>Open</button>
<HoverCard.RootProvider value={hoverCard}>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.RootProvider>
</>
)
}
import { HoverCard, useHoverCard } from '@ark-ui/solid/hover-card'
import { Portal } from 'solid-js/web'
export const RootProvider = () => {
const hoverCard = useHoverCard()
return (
<>
<button onClick={() => hoverCard().setOpen(true)}>Open</button>
<HoverCard.RootProvider value={hoverCard}>
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Portal>
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Portal>
</HoverCard.RootProvider>
</>
)
}
<script setup lang="ts">
import { HoverCard, useHoverCard } from '@ark-ui/vue/hover-card'
const hoverCard = useHoverCard()
</script>
<template>
<button @click="hoverCard.setOpen(true)">Open</button>
<HoverCard.RootProvider :value="hoverCard">
<HoverCard.Trigger>Hover me</HoverCard.Trigger>
<Teleport to="body">
<HoverCard.Positioner>
<HoverCard.Content>
<HoverCard.Arrow>
<HoverCard.ArrowTip />
</HoverCard.Arrow>
Content
</HoverCard.Content>
</HoverCard.Positioner>
</Teleport>
</HoverCard.RootProvider>
</template>
If you're using the
RootProvider
component, you don't need to use theRoot
component.
API Reference
Root
Prop | Default | Type |
---|---|---|
closeDelay | 300 | number The duration from when the mouse leaves the trigger or content until the hover card closes. |
defaultOpen | boolean The initial open state of the hover card when rendered. Use when you don't need to control the open state of the hover card. | |
id | string The unique identifier of the machine. | |
ids | Partial<{ trigger: string; content: string; positioner: string; arrow: string }> The ids of the elements in the popover. Useful for composition. | |
lazyMount | false | boolean Whether to enable lazy mounting |
open | boolean The controlled open state of the hover card | |
openDelay | 700 | number The duration from when the mouse enters the trigger until the hover card opens. |
positioning | PositioningOptions The user provided options used to position the popover content | |
unmountOnExit | false | boolean Whether to unmount on exit. |
Emit | Event |
---|---|
focusOutside | [event: FocusOutsideEvent] Function called when the focus is moved outside the component |
interactOutside | [event: InteractOutsideEvent] Function called when an interaction happens outside the component |
openChange | [details: OpenChangeDetails] Function called when the hover card opens or closes. |
pointerDownOutside | [event: PointerDownOutsideEvent] Function called when the pointer is pressed down outside the component |
update:open | [open: boolean] The callback fired when the open state changes. |
Arrow
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
ArrowTip
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Content
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | hover-card |
[data-part] | content |
[data-state] | "open" | "closed" |
[data-placement] | The placement of the content |
Positioner
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
RootProvider
Prop | Default | Type |
---|---|---|
value | HoverCardApi<PropTypes> | |
lazyMount | false | boolean Whether to enable lazy mounting |
unmountOnExit | false | boolean Whether to unmount on exit. |
Trigger
Prop | Default | Type |
---|---|---|
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | hover-card |
[data-part] | trigger |
[data-placement] | The placement of the trigger |
[data-state] | "open" | "closed" |