Skip to content

HoverCard

A floating card that appears on hover or focus of a trigger element.

Account health

Hover cards can hold richer preview content than a tooltip.

<HoverCard {...args} content={previewContent}>
Account health
</HoverCard>

Workspace

12 members, 4 pending invites

<HoverCard
{...args}
content={
<VStack gap={2} style={{maxWidth: 260}}>
<Text as="p" type="label">
Workspace
</Text>
<Text as="p" color="secondary">
12 members, 4 pending invites
</Text>
</VStack>
}>
<Button label="Workspace" />
</HoverCard>

The patterned backdrop must not show through the hover card.

Hover to inspect the surface

Opaque panel

This content has the theme surface background.

<Card
padding={8}
style={{
backgroundImage:
'repeating-linear-gradient(135deg, var(--silver-colors-fg) 0 12px, var(--silver-colors-primary) 12px 24px)',
minHeight: 240,
}}>
<Card padding={4} style={{maxWidth: 320}}>
<VStack gap={3}>
<Text as="p">
The patterned backdrop must not show through the hover card.
</Text>
<HoverCard
content={
<VStack gap={1} style={{maxWidth: 240}}>
<Text as="p" type="label">
Opaque panel
</Text>
<Text as="p" color="secondary">
This content has the theme surface background.
</Text>
</VStack>
}
delay={0}
placement="below">
Hover to inspect the surface
</HoverCard>
</VStack>
</Card>
</Card>
Default background
Subtle background
<HStack gap={6} style={{alignItems: 'stretch', flexWrap: 'wrap'}}>
{(
[
['Default background', 'var(--silver-colors-bg)'],
['Subtle background', 'var(--silver-colors-bg-subtle)'],
] as const
).map(([label, background]) => (
<Card
key={label}
padding={8}
style={{
alignItems: 'center',
background,
display: 'flex',
justifyContent: 'center',
minHeight: 240,
minWidth: 320,
}}>
<HoverCard
content={previewContent}
delay={0}
label={`${label} preview`}
placement="above">
{label}
</HoverCard>
</Card>
))}
</HStack>
Above

Hover cards can hold richer preview content than a tooltip.

Start

Hover cards can hold richer preview content than a tooltip.

End

Hover cards can hold richer preview content than a tooltip.

Below

Hover cards can hold richer preview content than a tooltip.

<div
style={{
display: 'grid',
gap: 24,
justifyItems: 'center',
padding: '80px',
}}>
<HoverCard content={previewContent} placement="above">
Above
</HoverCard>
<HStack gap={6}>
<HoverCard content={previewContent} placement="start">
Start
</HoverCard>
<HoverCard content={previewContent} placement="end">
End
</HoverCard>
</HStack>
<HoverCard content={previewContent} placement="below">
Below
</HoverCard>
</div>
Start aligned

Hover cards can hold richer preview content than a tooltip.

Center aligned

Hover cards can hold richer preview content than a tooltip.

End aligned

Hover cards can hold richer preview content than a tooltip.

<VStack gap={4} style={{padding: 40}}>
<HoverCard alignment="start" content={previewContent} placement="below">
Start aligned
</HoverCard>
<HoverCard alignment="center" content={previewContent} placement="below">
Center aligned
</HoverCard>
<HoverCard alignment="end" content={previewContent} placement="below">
End aligned
</HoverCard>
</VStack>
Hover me (disabled)

Hover cards can hold richer preview content than a tooltip.

<HoverCard {...args} content={previewContent} isEnabled={false}>
Hover me (disabled)
</HoverCard>

Jane Smith

Product Designer at Acme Corp

<HoverCard
{...args}
content={
<VStack gap={3} style={{maxWidth: 280}}>
<VStack gap={1}>
<Text as="p" type="label">
Jane Smith
</Text>
<Text as="p" color="secondary">
Product Designer at Acme Corp
</Text>
</VStack>
<HStack gap={2}>
<Button label="View profile" size="sm" variant="secondary" />
<Button label="Message" size="sm" variant="primary" />
</HStack>
</VStack>
}>
<Button label="Jane Smith" variant="ghost" />
</HoverCard>
No underline on hover

Hover cards can hold richer preview content than a tooltip.

Always underline on hover

Hover cards can hold richer preview content than a tooltip.

Auto (text triggers only)

Hover cards can hold richer preview content than a tooltip.

<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'start',
gap: 16,
}}>
<HoverCard content={previewContent} hoverIndication="never">
No underline on hover
</HoverCard>
<HoverCard content={previewContent} hoverIndication="always">
Always underline on hover
</HoverCard>
<HoverCard content={previewContent} hoverIndication="auto">
Auto (text triggers only)
</HoverCard>
</div>

Without a label the surface is exposed as a plain group; with one it becomes a named dialog that screen reader users can find in the dialog list.

Unlabelled (role="group")

Hover cards can hold richer preview content than a tooltip.

Labelled (role="dialog")
<VStack gap={4} style={{alignItems: 'start'}}>
<Text as="p" color="secondary">
Without a label the surface is exposed as a plain group; with one it
becomes a named dialog that screen reader users can find in the dialog
list.
</Text>
<HoverCard {...args} content={previewContent}>
Unlabelled (role=&quot;group&quot;)
</HoverCard>
<HoverCard
{...args}
content={previewContent}
label="Account health details">
Labelled (role=&quot;dialog&quot;)
</HoverCard>
</VStack>
Slow open (800ms), slow close (500ms)

Hover cards can hold richer preview content than a tooltip.

<HoverCard {...args} content={previewContent} delay={800} hideDelay={500}>
Slow open (800ms), slow close (500ms)
</HoverCard>

A floating card that appears on hover or focus of a trigger element.

PropTypeDefaultDescription
alignment"center" | "start" | "end"'center'Alignment along the placement axis.
children*ReactNodeTrigger content.
classNamestringAdditional class names applied to the trigger wrapper for text triggers.
content*ReactNodeContent shown in the floating hover card.
data-testidstringTest ID applied to the trigger wrapper for text triggers.
delaynumber300Delay before opening on hover, in milliseconds.
focusTrigger"auto" | "always" | "never"'auto'Controls focus-trigger behavior.
hideDelaynumber200Delay before closing after hover/focus leaves, in milliseconds.
hoverIndication'always' | 'auto' | 'never''auto'Dashed underline display for text triggers.
isEnabledbooleantrueWhether hover/focus interactions are enabled.
labelstringAccessible name for the hover card surface, applied as aria-label. When provided the surface is exposed as role="dialog"; without it the surface is exposed as role="group" so that assistive technology is not given an unnamed dialog. The trigger keeps its aria-describedby link to the surface either way.
placement"start" | "end" | "above" | "below"'above'Position relative to the trigger.
refRef<HTMLSpanElement>Ref forwarded to the text trigger wrapper.
styleCSSPropertiesInline styles applied to the text trigger wrapper.