Preview Card
A hover/focus link preview (hovercard). Behavior from Base UI, look from Silica's .preview-card CSS.
Real use · hover a link to preview the profile
Reviewed by @ada on the pull request.
Using Preview Card
Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.
Plain HTML — CSS classes
The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path ships no JavaScript, so Preview Card is styled but inert: its behavior comes from popover. For that behavior with no framework, use the node-tree path below.
/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";Root class preview-card, with 1 modifier:
.preview-card.preview-card-arrow
React
Typed components over those same classes, with behavior and accessibility from Base UI.
npm i @wizeworks/silicaui-reactimport { PreviewCard } from "@wizeworks/silicaui-react";Props
| Prop | Type | Required | Description |
|---|---|---|---|
| children | React.ReactElement | yes | The trigger (usually a link). Base UI merges hover/focus behavior onto it. |
| content | React.ReactNode | yes | The card body shown on hover/focus. |
| side | PreviewCardSide | no | Preferred side. Default bottom (flips to avoid collisions). |
| align | PreviewCardAlign | no | Alignment along that side. Default center. |
| sideOffset | number | no | Gap between trigger and card, in px. Default 8. |
| delay | number | no | Hover-open delay in ms. |
| closeDelay | number | no | Close delay in ms. |
| open | boolean | no | Controlled open state. |
| defaultOpen | boolean | no | Uncontrolled initial open state. |
| onOpenChange | (open: boolean) => void | no | — |
| arrow | boolean | no | Show the little arrow. Default false. |
| className | string | no | Extra class on the card surface. |
| anchor | BasePositionerProps["anchor"] | no | What to position against. Defaults to the component's own trigger. |
| positionMethod | BasePositionerProps["positionMethod"] | no | absolute (default) or fixed. Use fixed to escape a clipping ancestor. |
| alignOffset | BasePositionerProps["alignOffset"] | no | Offset along the alignment axis, in px. Pairs with align. |
| collisionBoundary | BasePositionerProps["collisionBoundary"] | no | The element the popup must stay inside. Defaults to the viewport — set it to a scroll container so the popup collides with the panel, not the window. |
| collisionPadding | BasePositionerProps["collisionPadding"] | no | Inset from the collision boundary, in px. |
| collisionAvoidance | BasePositionerProps["collisionAvoidance"] | no | Which collision strategy runs per axis (flip, shift, none). |
| sticky | BasePositionerProps["sticky"] | no | Keep the popup glued to the anchor while it scrolls out of view. |
| arrowPadding | BasePositionerProps["arrowPadding"] | no | Minimum distance from the popup's corner to the arrow, in px. |
| disableAnchorTracking | BasePositionerProps["disableAnchorTracking"] | no | Stop re-measuring when the anchor moves. Cheaper, but goes stale. |
Source of the demo above
The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.
Show source
import { PreviewCard, Link, Avatar } from "@wizeworks/silicaui-react";
import { Section } from "../lib/Section";
export function PreviewCardDemo() {
return (
<Section title="Real use · hover a link to preview the profile">
<p className="max-w-md text-sm">
Reviewed by{" "}
<PreviewCard
content={
<div className="flex items-center gap-3">
<Avatar color="primary" alt="Ada Lovelace">
AL
</Avatar>
<div>
<div className="font-medium">Ada Lovelace</div>
<div className="text-xs opacity-60">
Founding engineer · @ada
</div>
</div>
</div>
}
arrow
>
<Link href="#" color="primary">
@ada
</Link>
</PreviewCard>{" "}
on the pull request.
</p>
</Section>
);
}Vanilla — node tree to HTML
PreviewCard — same shape as Tooltip (hover trigger), rich card content rather than a short text label. Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.
npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviorsimport { atom, toHtml } from "@wizeworks/silicaui-html";
const node = atom("PreviewCard", "preview-card", { /* props */ }, [/* children */]);
const markup = toHtml(node);Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "preview-card preview-card-primary" rather than passing a colour as a prop.
- Takes children
- yes
- Hydrated by
popover
Load @wizeworks/silicaui-behaviors on the page or this markup renders correctly and does nothing.
The full API for Preview Card, on every path, is available through the Silica MCP server.