Tessina UI
ConfiguratorGitHubIntroduction
InstallationUsageTheming
ComponentsAccordionAction SheetAlertAlertDialogArea ChartAspectRatioAvatarBadgeBannerBar ChartBottom NavBreadcrumbButtonButtonGroupCalendarCardCarouselChartChatBubbleCheckboxChipCodeBlockCollapsibleColor PickerComboboxCommandContainerContextMenuDate PickerDividerDrawerDropdown MenuEmptyStateFABFieldFieldsetFile UploadFile Upload 2FlexFormGridHoverCardIconButtonLabelLine ChartLinkMenubarMeterModalNavigation MenuNumberFieldOTP InputPaginationPie ChartPopoverProgressPromptInputRadar ChartRadial ChartRadioRatingScroll AreaSearchSegmentedControlSelectShortcutSidebarSkeletonSliderSpacerSpinnerSplit ButtonStackStatusStepperSurfaceSwitchTableTabsTextareaTime PickerToastToggleButtonToggleGroupToolbarTooltipTop Header DesktopTop Header Mobile
Contributing
Components

HoverCard

A floating card that appears when a trigger is hovered or focused. Use for lightweight previews โ€” user profiles, link previews, citations, or footnote definitions. Built on Base UI's preview-card primitive.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import {
  HoverCard,
  HoverCardTrigger,
  HoverCardContent,
  HoverCardHeader,
  HoverCardTitle,
  HoverCardDescription,
  HoverCardBody,
  HoverCardFooter,
  HoverCardArrow,
} from "@tessinaui/ui";
<HoverCard>
  <HoverCardTrigger render={<button>@blaz</button>} />
  <HoverCardContent side="bottom" align="start">
    <HoverCardHeader leading={<Avatar initials="BZ" />}>
      <HoverCardTitle>Blaz Zorcic</HoverCardTitle>
      <HoverCardDescription>Designer ยท Building TessinaUI.</HoverCardDescription>
    </HoverCardHeader>
    <HoverCardFooter>
      <Button variant="outline" size="xs">Message</Button>
      <Button size="xs">Follow</Button>
    </HoverCardFooter>
    <HoverCardArrow />
  </HoverCardContent>
</HoverCard>

Examples

Default

A user profile preview with an avatar, description, metadata, and footer actions.

Sizes

Four widths โ€” sm, md, lg, and xl โ€” each pairing a fixed width with a text scale.

Rounded

Corner radius from none to full, matched to the trigger for visual cohesion.

Intent border

Opt into a coloured border with intent + showIntentBorder for status previews.

Positioning

Place the card on any side of the trigger โ€” top, right, bottom, or left.

Loading

HoverCardSkeleton mirrors the card's avatar, text, and optional stats while content loads.

When to use HoverCard vs. Tooltip vs. Popover

Use HoverCard whenโ€ฆUse Tooltip whenโ€ฆUse Popover whenโ€ฆ
The preview is rich (avatar, description, actions)You only need short informational textThe user needs interactive controls (forms, lists)
Trigger is hover/focus (mouse + keyboard)Trigger is hover/focus and content is non-interactiveTrigger is click
Touch users gracefully don't see the previewTouch users gracefully don't see the tipWorks equally on touch + mouse
Examples: user profile, link preview, citationExamples: button label, icon meaningExamples: filter dropdown, rename input

Touch behaviour. HoverCard is mouse/keyboard-only. On touch devices Base UI swallows the hover gesture so the trigger just behaves like a normal button. If you need an equivalent on touch, pair it with a Popover triggered by click, or surface the same content elsewhere.

Anatomy

Only HoverCard, HoverCardTrigger, and HoverCardContent are required. Everything else composes optionally inside HoverCardContent.

<HoverCard>
  <HoverCardTrigger>โ€ฆ</HoverCardTrigger>
  <HoverCardContent>
    <HoverCardHeader>
      <HoverCardTitle />
      <HoverCardDescription />
    </HoverCardHeader>
    <HoverCardBody />
    <HoverCardFooter />
    <HoverCardArrow />
  </HoverCardContent>
</HoverCard>

Size

SizeWidthText
"sm"w-64 (16rem)xs
"md" (default)w-72 (18rem)sm
"lg"w-80 (20rem)sm
"xl"w-96 (24rem)base

Intent

intent drives the optional border colour (when showIntentBorder is on) and the arrow's stroke. The popup keeps a neutral border by default โ€” opt in with showIntentBorder for status previews.

ValueBorder with showIntentBorder
"none" (default)border-border
"error"border-error
"warning"border-warning
"success"border-success
"info"border-info

Rounded

ValueCSS
"none"rounded-none
"sm"rounded-md
"md" (default)rounded-lg
"lg"rounded-xl
"full"rounded-3xl

Positioning

HoverCardContent accepts side (top | right | bottom | left), align (start | center | end), sideOffset (px gap from trigger, default 8), and alignOffset (px shift along the side, default 0).

<HoverCardContent side="right" align="start" sideOffset={12}>
  โ€ฆ
</HoverCardContent>

Delays

Pass delay (open) and closeDelay (close) on the root, in milliseconds. Defaults match Base UI: delay = 600, closeDelay = 300.

<HoverCard delay={300} closeDelay={150}>
  โ€ฆ
</HoverCard>

The values propagate to HoverCardTrigger via context โ€” override per-trigger if you have multiple triggers in one card group.

Header slots

HoverCardHeader takes optional leading (avatar / icon) and trailing (badge / status) slots in addition to its title + description children.

<HoverCardHeader
  leading={<Avatar initials="BZ" />}
  trailing={<Badge variant="dot" color="success" />}
>
  <HoverCardTitle>Blaz Zorcic</HoverCardTitle>
  <HoverCardDescription>Online now</HoverCardDescription>
</HoverCardHeader>

Matching button corners to the card

HoverCardFooter is a generic slot โ€” buttons inside don't auto-inherit the card's rounded. Pass rounded explicitly on each button to keep its corners flowing into the card edge:

<HoverCard rounded="none">
  <HoverCardTrigger render={<button>@blaz</button>} />
  <HoverCardContent>
    โ€ฆ
    <HoverCardFooter>
      {/* match the HoverCard's rounded prop */}
      <Button variant="outline" size="xs" rounded="none">Message</Button>
      <Button variant="primary" size="xs" rounded="none">Follow</Button>
    </HoverCardFooter>
  </HoverCardContent>
</HoverCard>

Controlled

HoverCard accepts open, defaultOpen, and onOpenChange.

const [open, setOpen] = React.useState(false);

<HoverCard open={open} onOpenChange={setOpen}>
  โ€ฆ
</HoverCard>

Accessibility

  • Built on @base-ui/react/preview-card โ€” opens on hover or keyboard focus of the trigger.
  • The card's content is announced when focus moves into it; otherwise it remains presentational while the trigger is hovered.
  • Pressing Escape closes the card.
  • On touch input the card does not open โ€” the trigger is announced as a normal button.
  • Use intent="error" or "warning" with showIntentBorder to give status previews a visual signal that complements text content.

RTL

Pass dir="rtl" to the root. Header alignment, the leading/trailing slots, and footer button order all flip to follow the reading direction.

<HoverCard dir="rtl">
  <HoverCardTrigger render={<button>@blaz</button>} />
  <HoverCardContent>
    <HoverCardHeader>
      <HoverCardTitle>ุจู„ุงุฒ ุฒูˆุฑุชุดูŠุชุด</HoverCardTitle>
      <HoverCardDescription>ู…ุตู…ู… ยท ูŠุจู†ูŠ TessinaUI.</HoverCardDescription>
    </HoverCardHeader>
    <HoverCardArrow />
  </HoverCardContent>
</HoverCard>

API Reference

HoverCard (root)

PropTypeDefaultDescription
size"sm" | "md" | "lg" | "xl""md"Width + text size of the popup
rounded"none" | "sm" | "md" | "lg" | "full""md"Corner radius
intent"none" | "error" | "warning" | "success" | "info""none"Used by the optional intent border
showIntentBorderbooleanfalseWhen true, the popup border picks up the intent colour
dir"ltr" | "rtl""ltr"Reading direction
delaynumber600 (Base UI)Open delay in ms (forwarded to Trigger)
closeDelaynumber300 (Base UI)Close delay in ms (forwarded to Trigger)
openbooleanโ€”Controlled open state
defaultOpenbooleanfalseUncontrolled initial state
onOpenChange(open, event) => voidโ€”Fired when open state changes

HoverCardContent

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""bottom"Which side of the trigger to position on
align"start" | "center" | "end""center"Alignment along the side axis
sideOffsetnumber8Distance in px from the trigger
alignOffsetnumber0Shift along the side axis
portalbooleantrueRender inside a portal
containerHTMLElement | nulldocument.bodyPortal target
size, rounded, intent, showIntentBorderโ€”inheritedOverride the root's variant

HoverCardHeader

PropTypeDefaultDescription
leadingReactNodeโ€”Avatar or icon rendered beside the title
trailingReactNodeโ€”Slot for badge, status dot, or follow button

HoverCardTrigger

Renders a <button>. Use render={<a href="โ€ฆ" />} to swap in a link, or render={<MyComponent />} for any element. Accepts delay / closeDelay to override the values inherited from the root.

Sub-components

HoverCardTitle, HoverCardDescription, HoverCardBody, HoverCardFooter, HoverCardArrow, HoverCardBackdrop โ€” all accept className and any HTML props.

Notes

  • Built on @base-ui/react/preview-card โ€” Base UI's name for the HoverCard primitive.
  • Enter/exit animations use Base UI's data-[starting-style] / data-[ending-style] plus position-aware data-[side=*] attributes, so the popup "lifts off" from whichever side it opens on.
  • The arrow is drawn as a single rotated square โ€” no SVG โ€” so it inherits the surface colour and (when showIntentBorder is on) the intent border colour automatically.

Grid

A CSS-grid layout primitive with static and responsive column counts, gap presets, flow control, and per-cell placement via GridItem. Polymorphic render, RTL, and no hard-coded tokens.

IconButton

A square button that renders a single icon, with optional external label and notification badge.

On this page

PlaygroundInstallationUsageExamplesDefaultSizesRoundedIntent borderPositioningLoadingWhen to use HoverCard vs. Tooltip vs. PopoverAnatomySizeIntentRoundedPositioningDelaysHeader slotsMatching button corners to the cardControlledAccessibilityRTLAPI ReferenceHoverCard (root)HoverCardContentHoverCardHeaderHoverCardTriggerSub-componentsNotes