Containment
Card
MD3 card — elevated, filled, or outlined.
import { Card } from 'omaris' Examples
Basic
Header, body, footer. The body is the part that grows, so a row of cards with different amounts to say still lines its footers up.
Invoice #4021
Due in 14 days
<script lang="ts"> import { Button, Card, CardContent, CardFooter, CardHeader } from 'omaris';</script><Card class="w-80 max-w-full"> <CardHeader heading="Invoice #4021" description="Due in 14 days" /> <CardContent>Kurdistan Coffee Roasters — 24 kg green Arabica, delivered 3 March.</CardContent> <CardFooter> <Button variant="text">Dismiss</Button> <Button>Pay now</Button> </CardFooter></Card> Variants
outlined is the default. elevated lifts — a grid of cards on a page wants it; filled sits in a tinted well, for a card inside another surface.
elevated
filled
outlined
<script lang="ts"> import { Card, CardContent, CardHeader } from 'omaris';</script><Card variant="elevated" class="w-56 max-w-full"> <CardHeader heading="elevated" /> <CardContent>The same card, three surfaces.</CardContent></Card><Card variant="filled" class="w-56 max-w-full"> <CardHeader heading="filled" /> <CardContent>The same card, three surfaces.</CardContent></Card><Card variant="outlined" class="w-56 max-w-full"> <CardHeader heading="outlined" /> <CardContent>The same card, three surfaces.</CardContent></Card> With media
bleed cancels the card's padding so the picture reaches the edges, and rounds only the corners it actually touches.
Erbil citadel
Six thousand years, still occupied
<script lang="ts"> import { Card, CardContent, CardHeader, CardMedia } from 'omaris';</script><Card variant="elevated" class="w-72 max-w-full"> <CardMedia ratio="16/9"> <div class="size-full bg-linear-to-br from-primary-container to-tertiary-container" aria-hidden="true" ></div> </CardMedia> <CardHeader heading="Erbil citadel" description="Six thousand years, still occupied" /> <CardContent>One of the longest continuously inhabited sites on earth.</CardContent></Card> Interactive
A picker — plans, delivery options. interactive makes the whole card pressable, with a ripple, and selected marks the chosen one.
<script lang="ts"> import { Card, CardContent, CardHeader } from 'omaris'; let chosen = $state('standard');</script><Card interactive selected={chosen === 'standard'} class="w-52 max-w-full" onclick={() => (chosen = 'standard')} aria-pressed={chosen === 'standard'}> <CardHeader heading="Standard" description="3–5 days" /> <CardContent>Delivered by our own drivers.</CardContent></Card><Card interactive selected={chosen === 'express'} class="w-52 max-w-full" onclick={() => (chosen = 'express')} aria-pressed={chosen === 'express'}> <CardHeader heading="Express" description="Next day" /> <CardContent>Delivered by our own drivers.</CardContent></Card> Header slots
start and end take an avatar, a badge, a menu button — anything. The header of a card about a person, or a record with a status.
Omer Chetin
Opened this pull request
<script lang="ts"> import { Avatar, Badge, Card, CardContent, CardHeader, IconButton } from 'omaris';</script><Card class="w-full max-w-96"> <CardHeader heading="Omer Chetin" description="Opened this pull request"> {#snippet start()} <Avatar name="Omer Chetin" /> {/snippet} {#snippet end()} <div class="flex items-center gap-2"> <Badge tone="success" variant="tonal">Open</Badge> <IconButton aria-label="More actions" size="sm"> <svg viewBox="0 0 24 24" fill="currentColor"> <circle cx="12" cy="5" r="1.6" /><circle cx="12" cy="12" r="1.6" /><circle cx="12" cy="19" r="1.6" /> </svg> </IconButton> </div> {/snippet} </CardHeader> <CardContent>Adds the docs site and moves Storybook to /storybook.</CardContent></Card> Overridden
A footer defaults to putting its actions at the end, which MD3 asks for. align moves them, and class on the card wins over its own padding.
Storage
8.2 GB of 10 GB used
<script lang="ts"> import { Button, Card, CardContent, CardFooter, CardHeader } from 'omaris';</script><Card class="w-full max-w-96 rounded-shape-2xl"> <CardHeader heading="Storage" description="8.2 GB of 10 GB used" /> <CardContent>Older exports are removed automatically after 90 days.</CardContent> <CardFooter align="between"> <Button variant="text" tone="destructive">Delete all</Button> <Button variant="tonal">Upgrade</Button> </CardFooter></Card> When to use it
Use it for
- One thing with a heading, a body and its actions: an invoice, an order, a project.
CardHeader,CardContent,CardFooter. The body grows, so a row of cards with different amounts of content still lines its footers up. - A grid of pressable tiles. Give the card
hreforonclickand it becomes a real target with a ripple and a focus ring, with no wrapper<a>. - A picker, like plans or delivery options.
interactiveandselected, witharia-pressedon each so the choice is read out. - An image-led card.
CardMediawith aratio;bleedis on by default so the picture reaches the edges and rounds only the corners it touches.
Not for
- Rows of the same shape you read down → List. Several columns you compare or sort → Table.
- Grouping a form's fields → whitespace and a Text heading. A card around every fieldset is a page of boxes.
- Pictures of unequal height in a wall → Masonry around the cards, not a grid of cards with cropped images.
Do
- Pick the variant by what is underneath.
outlined(the default) reads well on a plain page. A dashboard grid usually wantselevated, so cards read as separate objects without a hairline each.filledis for a card inside another surface, like a sheet or a dialog. - Set
levelonCardHeaderto fit the page outline. The default3assumes the page has anh2above it. - Leave
CardFooteractions at the end.align="between"is only for keeping a destructive action apart from the safe one. - Put a menu or a badge in the header's
endslot, an avatar or icon instart.
Don't
- Nest a card in a card. Use
CardContentwith aDivideror aListinside it. - Put a button, a link or a menu inside an
interactivecard. Make the whole card the target, or none of it. - Give a card more than one
filledbutton. One action commits; the rest aretext. - Add a
borderclass to make anelevatedcard visible on a busy surface. Switch tooutlinedinstead.
Quick reference
variant elevatedfilledoutlined(default)
size md(default)lg
API
Card
MD3 card — elevated, filled, or outlined.
A plain card is a passive container. Give it href or onclick and it becomes a real target: it picks up the state layer, a ripple, a focus ring, and lifts a step on hover. That's the whole difference, so a grid of clickable cards doesn't need a wrapper <a> around each one.
import { Card } from 'omaris' Props
variant Defaults to 'outlined'
CardVariant elevatedfilledoutlined
size Defaults to 'md'
CardSize mdlg
interactive boolean Force the interactive treatment on a card that handles its own press.
selected Defaults to false
boolean Chosen state — border and ring in the primary color.
ripple Defaults to true
boolean Ripple on press. Interactive cards only.
class string children Snippet tone ButtonTone Color role the fill style paints with.
shape ButtonShape Pill (round) or MD3 rounded rectangle (square).
icon boolean Square, label-less button. Requires an aria-label.
confetti boolean | ConfettiOptions Confetti on press. true for the default burst, or any ConfettiOptions — confetti={{ preset: 'fireworks' }}.
loading boolean Grows a spinner in at the start of the button and blocks interaction. The label stays put; only an icon button swaps its icon out.
toggle boolean Turns the button into a two-state toggle driven by pressed. Ignored when href is set — a link has no pressed state.
pressed bindableboolean Selected state of a toggle button. Bindable.
CardContent
A card's body — the text and controls between its header and its footer.
It is the part that grows, so a row of cards with different amounts to say still line their footers up.
import { CardContent } from 'omaris' Props
class string children Snippet CardFooter
A card's actions, laid out in a row that wraps.
MD3 puts card actions at the end, which is the default here; align moves them for the cases where that reads wrong.
import { CardFooter } from 'omaris' Props
align Defaults to 'end'
'start' | 'end' | 'between' Where the actions sit. MD3 puts card actions at the end.
class string children Snippet CardHeader
The heading row of a card: a leading slot, a title block, a trailing slot.
The row wraps rather than crushes. An end slot holding a couple of buttons is wider than a phone leaves over once the icon and the title have had their share, and a shrink-0 trailing slot in a row that cannot wrap takes that width from the title instead — which is how a heading ends up reading one word per line down a 60px column. basis on the body is the threshold: while the title can keep 12rem the row stays on one line and nothing moves, and below that the trailing slot drops to a line of its own.
import { CardHeader } from 'omaris' Parts
Every element this renders is reachable from outside. Pass Tailwind for one part as classes={{ part: '…' }}; class covers the root and is merged last, so it always wins.
root- No description in the source yet.
start- An avatar or icon before the title.
body- Title and supporting line, stacked.
title- No description in the source yet.
description- No description in the source yet.
end- An overflow menu or badge after the title.
Props
heading string Heading text. Use the title snippet instead for rich markup.
description string Supporting line under the heading.
level Defaults to 3
2 | 3 | 4 | 5 | 6 Heading level, so cards nest correctly in a page outline.
class string classes CardHeaderClasses Per-part Tailwind overrides. class still covers the root.
start Snippet Leading slot — an avatar or icon.
end Snippet Trailing slot — an overflow menu, a badge.
title Snippet Rich heading, in place of heading.
supporting Snippet Rich supporting line, in place of description.
CardMedia
The image at the top of a card.
bleed is the one worth knowing: it cancels the card's padding so the picture reaches the edges, and rounds only the corners it actually touches.
import { CardMedia } from 'omaris' Props
src string alt Defaults to ''
string ratio Defaults to '16/9'
'16/9' | '4/3' | '1/1' | '3/2' | 'auto' Common MD3 media ratios.
bleed Defaults to true
boolean Cancels the card's padding so the media reaches the edges, and keeps only the corners it actually touches rounded.
class string children Snippet Overlaid content — a play button, a gradient caption.