ComponentsLayout Blocks
Card
A flexible surface container for grouping related content. Four variants (elevated/outlined/filled/ghost), five intents, six rounded options, five sizes, horizontal layout, interactive states, and LTR/RTL support.
Playground
Installation
pnpm add @tessinaui/uiUsage
import {
Card,
CardMedia,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
CardDivider,
} from "@tessinaui/ui";{/* Basic card */}
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Content</CardContent>
<CardFooter>
<Button variant="primary">Action</Button>
</CardFooter>
</Card>
{/* Outlined with intent */}
<Card variant="outlined" intent="success">
<CardHeader>
<CardTitle>Success</CardTitle>
</CardHeader>
</Card>
{/* Card with media */}
<Card rounded="lg" className="overflow-hidden w-72">
<CardMedia src="/image.jpg" alt="Cover" aspectRatio="video" position="top" />
<CardHeader>
<CardTitle>Article title</CardTitle>
</CardHeader>
</Card>
{/* Interactive card */}
<Card interactive onClick={() => navigate('/details')}>
<CardContent>Click me</CardContent>
</Card>
{/* Horizontal layout */}
<Card horizontal className="max-w-lg overflow-hidden">
<CardMedia position="start" className="w-32 bg-secondary" />
<div className="flex flex-col flex-1">
<CardHeader>
<CardTitle>Horizontal card</CardTitle>
</CardHeader>
<CardContent>Content beside media</CardContent>
</div>
</Card>
{/* RTL */}
<Card dir="rtl" variant="outlined">
<CardHeader>
<CardTitle>عنوان البطاقة</CardTitle>
</CardHeader>
</Card>Showcase
API Reference
Card Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "elevated" | "outlined" | "filled" | "ghost" | "elevated" | Visual surface style |
intent | "none" | "error" | "warning" | "success" | "info" | "none" | Semantic intent color applied to the card surface |
size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Controls padding of all inner sections |
rounded | "none" | "sm" | "md" | "lg" | "xl" | "full" | "md" | Corner radius |
width | "narrow" | "default" | "wide" | "full" | "default" | Max-width constraint |
shadow | "none" | "sm" | "md" | "lg" | "md" for elevated, "none" otherwise | Drop shadow depth |
interactive | boolean | false | Adds hover / active / focus-ring states |
disabled | boolean | false | Dims the card and disables pointer events |
horizontal | boolean | false | Switches internal flex direction to row |
dir | "ltr" | "rtl" | "ltr" | Text direction |
className | string | — | Additional class on the root element |
CardMedia Props
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | Image source URL |
alt | string | "" | Image alt text |
aspectRatio | "auto" | "video" | "4/3" | "1/1" | "2/1" | "3/4" | "video" | Aspect ratio of the media container |
position | "top" | "bottom" | "start" | "end" | "fill" | "top" | Edge the media abuts — determines which corners are rounded |
children | ReactNode | — | Custom media content (video, iframe, etc.) replaces the default <img> |
CardHeader Props
| Prop | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | — | Icon / illustration rendered above (or inline with) the title |
inlineIcon | boolean | false | Lays out icon and title text in a horizontal row |
CardFooter Props
| Prop | Type | Default | Description |
|---|---|---|---|
vertical | boolean | false | Stacks footer items vertically |
align | "start" | "center" | "end" | "between" | "start" | Alignment of footer items |
Variants
| Value | Style |
|---|---|
"elevated" | bg-card with drop shadow (default shadow-md) |
"outlined" | bg-background with border-border — flat with visible border |
"filled" | bg-secondary (or intent-light color) — tinted surface |
"ghost" | Transparent — no border, no shadow |
Notes
- Section padding —
CardHeader,CardContent, andCardFooterall readsizefrom context and apply consistent padding. Override per-section withclassName. - CardMedia rounding — use
positionto control which corners are rounded on the media figure. Setposition="start"for the left edge of horizontal cards; it uses logical CSS properties so it flips automatically in RTL. - Interactive cards — when
interactiveis set and the card contains nested buttons or links, prefer the stretched-link pattern (absolute-positioned<a>) rather thanonClickon the card root to avoid nested interactive element accessibility issues. - Horizontal layout — set
horizontalon theCardroot, then useCardMediawithposition="start"(or"end") and wrap remaining sections in a<div className="flex flex-col flex-1">. - RTL —
dir="rtl"is applied to the root and propagates to all children. Logical CSS properties (rounded-s-*,rounded-e-*) ensure media rounding flips correctly.
Spacer
A decorative gap-filler. Three axis modes, eight sizes, optional grow-to-fill behaviour, and polymorphic render. Accessibility-hidden by default — screen readers skip it.
Carousel
Touch-friendly slider with multiple variants — slide, card/3D, fade, and free-scroll. Built on Embla Carousel with autoplay, loop, RTL, and vertical orientation support.