Card
A flexible content container for a title, description, media, and actions.

Golden hour in the valley
Three nights in a timber cabin at the treeline, with meadow trails and the peaks at your door.
Usage
Card is a layout container, not a widget - it has no state, no interaction, and stays renderable from a Server Component. Compose it from its parts, all under @appica/ui-react/card:
Card- the root. Owns theframe, theinset, and the radius every other corner scales from. It renders two elements: the outer frame and the inner content wrapper, a flex column that holds the slots.CardMedia- a clipped box for an image or video. Place it above the header or below the footer.CardHeader- the text column. It stretches, which is what pinsCardFooterto the bottom of a fixed-height card.CardTitle- the headline (<h3>).CardDescription- the supporting text (<p>).CardFooter- a row for actions that stacks on narrow viewports.
Every part is optional. A card can be nothing but a CardMedia, or nothing but a CardHeader.
One radius, everywhere
--card-radius is the card's own corner (the one on the content wrapper) and the only number you ever set:
The frame and the inset media scale off it proportionally: the frame rounds at ×4/3 and inset media at ×3/4. That's deliberate - subtracting the padding instead would leave inset media on a hairline corner at the default radius, and collapse it entirely below that. Retune one value and the whole nest stays in proportion.
Set the radius through --card-radius rather than a rounded-* utility. A rounded-* class only paints the element
you put it on; the variable is what the frame and media scale from.
Examples
Default
The most basic setup - no props, just a header and a footer.
Frame
frame="solid" wraps the content in a band of background-subtle and softens the inner hairline to border-muted. Leave it off (the default) unless the card needs that extra separation from the page.
Glass frame
frame="glass" swaps the band for a translucent, blurred one and drops the inner border. Glass only exists relative to what's behind it - put the card over a photo, a gradient, or a colored section, never on flat page background.
Media
CardMedia clips whatever you put in it, above the header or below the footer. With the default inset, media floats inside the content wrapper with all four corners rounded. With inset={false}, the header and footer take the full gutter themselves and media runs edge to edge - the content wrapper's own overflow-hidden clips it, so a top image rounds only its top corners and a bottom image only its bottom ones, in either writing direction.
Video
Anything inside CardMedia is clipped the same way. Direct <img> and <video> children are stretched and object-cover'd for you, so a fixed height on CardMedia is all the sizing you need.
Horizontal layout (Next.js Image / Link)
There's no orientation prop - the content wrapper is a flex column, so turning a card sideways is one Tailwind class on it via contentProps. Wrap the header and footer in a plain div so they keep stacking while the media sits alongside.
CardMedia is already position: relative, so a next/image with fill drops straight in. The whole card renders as an <article> via render, and the title wraps a next/link so only the headline is clickable - see Accessibility for why that beats an onClick on the root.
Overlay
For a card that is an image, position CardMedia absolutely - inset-2 when the card is inset, inset-0 when it isn't - and let CardHeader stack above it. Add a scrim inside the media for legible text.
Profile
Any content is welcome inside CardHeader; it's a plain flex column. Here an Avatar leads a centered profile card.
Empty state
Reach contentProps to restyle the surface itself - a dashed border and a subtle fill turn a card into a placeholder. A Thumbnail in an icon variant carries the visual weight.
Product card
CardHeader is a plain flex column, so anything can live in it - here a price row, a ToggleGroup of sizes, and a NumberField. The badge and wishlist toggle are positioned inside CardMedia, which is already relative.
Form in a card
render={<form />} makes the card itself the form element, so Fields and the submit button need no extra wrapper.
Radius
Changing --card-radius retunes the card and its inset media together, in one place.
RTL
Every Appica UI component supports right-to-left layouts out of the box. Set the dir attribute on a container (commonly your <html> element) so CSS logical properties resolve correctly, and wrap your tree in DirectionProvider so direction-aware behavior follows the same direction.
Card is built entirely from logical padding and flex ordering, so the footer's actions flow from the right and text aligns to the start edge with no direction-specific classes. Flush media is clipped by the content wrapper rather than by fixed top/bottom radii, so it follows the writing direction too. For setup details and caveats, see the RTL guide.

ساعة ذهبية في الوادي
ثلاث ليالٍ في كوخ خشبي عند حد الأشجار، مع مسارات المروج والقمم على بابك.
API reference
Card
The root. Renders the outer frame plus an inner content wrapper, and publishes the one custom property the other parts scale from.
Any other <div> attribute is forwarded to the root.
--card-radius
The card's corner radius, defaulting to var(--radius-xl). Set it with an arbitrary-property class on Card (or anywhere above it) and the frame (×4/3) and inset media (×3/4) scale with it.
CardMedia
A clipped box for an image or video. Renders a <div>; direct <img> and <video> children get size-full object-cover.
CardHeader
The text column. Renders a <div> that stretches to fill the content wrapper, which is what pins the footer down.
CardTitle
The headline. Renders an <h3>.
CardDescription
The supporting text. Renders a <p> styled text-foreground-muted text-sm to pair with CardTitle; override with className.
CardFooter
A row for actions. Renders a <div> that stacks in reverse order below the sm breakpoint, so the primary action sits on top on narrow screens.
Accessibility
Cardrenders a plain<div>with no implicit role - it's a visual grouping, not a landmark. Userender={<article />}when the card is self-contained content, orrender={<li />}inside a list, so the structure is exposed to assistive tech.CardTitleis an<h3>so a page of cards reads as a coherent outline. If<h3>is the wrong level for your page, change it withrender={<h2 />}rather than restyling a<div>.- Make the whole card clickable only if you also give it a real control: put an
<a>or<button>on the title and stretch its hit area (after:absolute after:inset-0) instead of addingonClickto the root - that keeps the link keyboard-reachable and announced. - Decorative media should carry
alt=""so screen readers skip it; describe meaningful imagery in thealttext, not in the card copy alone. - A video that autoplays in
CardMediamust bemuted,playsInline, short, and purely decorative - Safari won't even paint a frame otherwise. Anything the user is meant to actually watch needscontrolsand noautoPlay. - The card adds no animation, so there is nothing to suppress for users who prefer reduced motion.




