HoverCard
Use CHoverCard to preview supplementary profile, document, or destination details on hover and keyboard focus. Essential information and actions must remain available without the preview.
HoverCard at a glance
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class HoverCardAtAGlance(Component):
template = """
<p>Meet
<c-CHoverCard>
<c-fill name="activator" data="{ activator_attrs }">
<a href="#maya" c-bind="activator_attrs">Maya Chen</a>
</c-fill>
<c-fill name="default">
<c-CStack gap="sm">
<c-CAvatar>MC</c-CAvatar>
<strong>Maya Chen</strong>
<span>Field researcher ยท 18 shared observations</span>
</c-CStack>
</c-fill>
</c-CHoverCard>
</p>
"""
preview = HoverCardAtAGlance()
preview # noqa: B018
Preview a document
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class DocumentHoverCard(Component):
template = """
<c-CHoverCard placement="top-start">
<c-fill name="activator" data="{ activator_attrs }">
<a href="#survey" c-bind="activator_attrs">Northern reef survey</a>
</c-fill>
<c-fill name="default">
<c-CStack gap="sm">
<strong>Northern reef survey</strong>
<span>Updated today ยท 42 observations</span>
<c-CProgress c-value="68" label="Review progress" />
</c-CStack>
</c-fill>
</c-CHoverCard>
"""
preview = DocumentHoverCard()
preview # noqa: B018
Control visibility
Show code
# ruff: noqa: E501
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class ControlledHoverCard(Component):
template = """
<div x-data>
<c-CHoverCard $c-props="{open:$store.hoverExample.open,onOpenChange:(next)=>$store.hoverExample.open=next}">
<c-fill name="activator" data="{ activator_attrs }">
<a href="#atlas" c-bind="activator_attrs">Atlas workspace</a>
</c-fill>
<c-fill name="default"><strong>Atlas</strong><p>12 collaborators ยท Active now</p></c-fill>
</c-CHoverCard>
<c-CButton variant="outline" @click="$store.hoverExample.open=!$store.hoverExample.open">Toggle preview</c-CButton>
</div>
"""
js = "Alpine.store('hoverExample',{open:false});"
preview = ControlledHoverCard()
preview # noqa: B018
Tune delays
Show code
# ruff: noqa: E501
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class HoverCardDelays(Component):
template = """
<c-CGroup>
<c-CHoverCard c-delay="0" c-close_delay="0">
<c-fill name="activator" data="{ activator_attrs }"><a href="#instant" c-bind="activator_attrs">Instant</a></c-fill>
<c-fill name="default">No opening or closing delay.</c-fill>
</c-CHoverCard>
<c-CHoverCard c-delay="900" c-close_delay="500">
<c-fill name="activator" data="{ activator_attrs }"><a href="#deliberate" c-bind="activator_attrs">Deliberate</a></c-fill>
<c-fill name="default">A slower, forgiving preview.</c-fill>
</c-CHoverCard>
</c-CGroup>
"""
preview = HoverCardDelays()
preview # noqa: B018
Choose placement
Show code
# ruff: noqa: E501
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class HoverCardPlacements(Component):
template = """
<c-CGroup style="padding-block:8rem">
<c-CHoverCard placement="top-start">
<c-fill name="activator" data="{ activator_attrs }"><a href="#top" c-bind="activator_attrs">Top start</a></c-fill>
<c-fill name="default">Collision-aware top preview.</c-fill>
</c-CHoverCard>
<c-CHoverCard placement="bottom-end">
<c-fill name="activator" data="{ activator_attrs }"><a href="#bottom" c-bind="activator_attrs">Bottom end</a></c-fill>
<c-fill name="default">Collision-aware bottom preview.</c-fill>
</c-CHoverCard>
</c-CGroup>
"""
preview = HoverCardPlacements()
preview # noqa: B018
Choose size and arrow
Show code
# ruff: noqa: E501
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class HoverCardSizes(Component):
template = """
<c-CGroup>
<c-CHoverCard size="sm">
<c-fill name="activator" data="{ activator_attrs }"><a href="#small" c-bind="activator_attrs">Small</a></c-fill>
<c-fill name="default">A compact preview card.</c-fill>
</c-CHoverCard>
<c-CHoverCard size="lg" c-arrow="False">
<c-fill name="activator" data="{ activator_attrs }"><a href="#large" c-bind="activator_attrs">Large without arrow</a></c-fill>
<c-fill name="default">A generous preview without a pointer arrow.</c-fill>
</c-CHoverCard>
</c-CGroup>
"""
preview = HoverCardSizes()
preview # noqa: B018
Nested color schemes
Show code
# ruff: noqa: E501
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class HoverCardThemes(Component):
template = """
<c-CGroup>
<div style="color-scheme:light;background:Canvas;color:CanvasText;padding:2rem">
<c-CHoverCard>
<c-fill name="activator" data="{ activator_attrs }"><a href="#day" c-bind="activator_attrs">Day profile</a></c-fill>
<c-fill name="default"><strong>Light scheme</strong><p>Follows its anchor context.</p></c-fill>
</c-CHoverCard>
</div>
<div style="color-scheme:dark;background:Canvas;color:CanvasText;padding:2rem">
<c-CHoverCard>
<c-fill name="activator" data="{ activator_attrs }"><a href="#night" c-bind="activator_attrs">Night profile</a></c-fill>
<c-fill name="default"><strong>Dark scheme</strong><p>Follows its anchor context.</p></c-fill>
</c-CHoverCard>
</div>
</c-CGroup>
"""
preview = HoverCardThemes()
preview # noqa: B018
Customize HoverCard
Show code
# ruff: noqa: E501
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CustomizedHoverCard(Component):
template = """
<c-CHoverCard
style="--cui-hover-card-background:#fff8eb;--cui-hover-card-foreground:#7a2e0e;
--cui-hover-card-border-color:#f79009;--cui-hover-card-radius:1.25rem"
>
<c-fill name="activator" data="{ activator_attrs }"><a href="#coral" c-bind="activator_attrs">Coral study</a></c-fill>
<c-fill name="default"><strong>Coral study</strong><p>Warm brand adaptation.</p></c-fill>
</c-CHoverCard>
"""
preview = CustomizedHoverCard()
preview # noqa: B018
Accessibility and interaction
The activator keeps its authored accessible name, navigation, and click behavior. The preview is aria-hidden supplementary content and cannot contain focusable or interactive descendants. Focus opens it visually; Escape and blur close it without moving focus. Touch contact does not open it.
Use CTooltip for a concise accessible description and CPopover when people must interact with the overlay.
API reference
Inputs
CHoverCard server inputs
Server inputs are passed in a template through <c-CHoverCard ... /> or in Python through CHoverCard(...).
| Input | Type | Default | Effect |
|---|---|---|---|
id | str | None | generated | Sets private surface identity and exposes it as slot data. |
open | bool | False | Sets the server-visible initial state and uncontrolled fallback. |
disabled | bool | False | Suppresses visual opening without changing the activator itself. |
delay | int | 600 | Sets the first fine-pointer hover delay in milliseconds from 0 through 60000. Focus remains immediate. |
close_delay | int | 300 | Sets the pointer bridge delay in milliseconds from 0 through 60000. |
placement | "top-start" | "top" | "top-end" | "bottom-start" | "bottom" | "bottom-end" (CHoverCardPlacement) | "bottom-start" | Sets the preferred logical placement. Collision fallback may choose another rendered side. |
arrow | bool | True | Shows the owned decorative pointer arrow. |
size | "sm" | "md" | "lg" (CHoverCardSize) | "md" | Selects preview width padding and text scale. |
class_ | str | Mapping[str, bool] | Sequence[CClassValue] | None (CClassValue) | None | Adds surface classes and merges them with attrs. |
style | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] | None (CStyleValue) | None | Adds surface inline styles and merges them with attrs; Citry retains anchor ownership. |
attrs | Mapping[str, object] | None | None | Adds allowed native, Alpine, and data attributes to the HoverCard surface. Owned presence, semantics, focus, and relationships are rejected. |
CHoverCard client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CHoverCard />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
open | boolean | null | Releases control and preserves the current committed state. null has the same effect. | Controls visual visibility while supplied as a Boolean. Disabled still dominates. |
disabled | boolean | Uses the server input. | Controls HoverCard-local availability. |
delay | integer | Uses the server input. | Controls future first-hover delay from 0 through 60000 milliseconds. |
closeDelay | integer | Uses the server input. | Controls the pointer bridge from 0 through 60000 milliseconds. |
placement | "top-start" | "top" | "top-end" | "bottom-start" | "bottom" | "bottom-end" (CHoverCardPlacement) | Uses the server input. | Controls requested placement and data-placement. |
arrow | boolean | Uses the server input. | Reactively shows or hides the decorative arrow. |
size | CHoverCardSize | Uses the server input. | Reactively changes card geometry. |
onOpenChange | function | Does not notify a component callback. | Receives hover, focus, dismissal, peer, press, and external-native visibility requests. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CHoverCard slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
activator | yes | {activator_attrs: dict[str, object], hover_card_id: str} (CHoverCardActivatorSlotData) | none |
default | yes | {} (CHoverCardDefaultSlotData) | none |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CHoverCard events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onOpenChange | (requestedOpen: boolean, detail: CHoverCardOpenChangeDetail) => void (CHoverCardOpenChangeDetail) | Hover, focus, pointer departure, blur, Escape, trigger press, a peer HoverCard, or external native visibility requests another state. | {reason: "hover" | "focus" | "pointer-leave" | "blur" | "escape" | "press" | "peer" | "native" | "ancestor" | "modal", controlled: boolean, forced: boolean, source: EventTarget | null} (CHoverCardOpenChangeDetail) | Uncontrolled requests commit before notification. Controlled requests wait for the owner. Owner commits do not notify. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CHoverCard CSS variables
Apply these variables to CHoverCard or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-hover-card-background | color | Surface background. | Canvas |
--cui-hover-card-foreground | color | Surface text. | CanvasText |
--cui-hover-card-border-color | color | Surface boundary. | Subtle currentColor mix. |
--cui-hover-card-radius | length | Surface corner radius. | 0.75rem |
--cui-hover-card-shadow | shadow | Top-layer elevation. | Scheme-aware layered shadow. |
--cui-hover-card-inline-size | length | Preferred preview width. | Size-derived. |
--cui-hover-card-max-inline-size | length | Maximum preview width. | 22rem |
--cui-hover-card-padding | length | Content padding. | Size-derived. |
--cui-hover-card-offset | length | Gap between activator and surface. | 0.375rem |
--cui-hover-card-duration | time | Entry and exit duration; reduced motion resolves to zero. | 100ms |
--cui-hover-card-easing | easing | Entry and exit easing. | cubic-bezier(0.2, 0.8, 0.2, 1) |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CHoverCard attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
popover | Surface | "manual" | Uses native top-layer presence while Citry owns timing and dismissal. |
aria-hidden | Surface | "true" | Keeps supplementary visual content outside the accessibility tree. |
data-open | Surface | present | absent | Mirrors logical visual visibility; absent during exit. |
data-placement | Surface | six placement strings (CHoverCardPlacement) | Mirrors requested placement, not the collision fallback result. |
data-side | Surface | "top" | "bottom" | Mirrors the collision-settled physical block side. |
data-size | Surface | CHoverCardSize | Reflects preview geometry. |
data-arrow | Surface | present | absent | Reflects decorative arrow visibility. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CHoverCard selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="host"] | Host div | Activator and surface ownership boundary. |
[data-citry-ui-part="hover-card"] | Surface | Visual surface and attrs destination. |
[data-citry-ui-part="content"] | Content div | Supplementary flow content wrapper. |
[data-citry-ui-part="arrow"] | Decorative span | Collision-side pointer mark. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] |
CHoverCardPlacement | Literal["top-start", "top", "top-end", "bottom-start", "bottom", "bottom-end"] |
CHoverCardSize | Literal["sm", "md", "lg"] |
CHoverCardActivatorSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
activator_attrs | dict[str, object] | - | Owned trigger marker and CSS anchor style. |
hover_card_id | str | - | Generated or authored surface identity. |
CHoverCardDefaultSlotData
Empty dataclass: {}.
CHoverCardOpenChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
reason | "hover" | "focus" | "pointer-leave" | "blur" | "escape" | "press" | "peer" | "native" | "ancestor" | "modal" | - | Source of the requested visibility change. |
controlled | boolean | - | Whether a valid client open Boolean currently owns state. |
forced | boolean | - | Whether structural or modal safety required the component to close regardless of controlled ownership. |
source | EventTarget | null | - | Browser source associated with the request. |
Translation keys
-