Card · stat · media
Cards with media, header actions, footers, folding, selection and loading placeholders — plus stat cards whose numbers count up, deltas that know which way is good, and sparklines that draw themselves.
Stats · numbers count to their new value · sparklines draw in
Revenue
$48,210
12.4%vs last month
Active users
2,931
4.1%this week
Churn
2.4%
0.8%lower is better
Orders
612
3.2%vs yesterday
Media · the whole card is a link · hover lifts it
🏔️
Dolomites loop
Popular
6 days · 84 km
Hut to hut under the pale peaks — via ferratas optional.
$1,240★ 4.9
🌊
🌲
A choice · Space or Enter picks it
Free
For trying things out
$0
Team
Per member, billed yearly
$12
Enterprise
SSO, audit logs, SLA
Talk to us
Header actions · a footer · folding · loading · looks
Team members
3 of 5 seats used
AAda Lovelace
Owner
GGrace Hopper
Admin
AAlan Turing
Member
Loading body
Placeholders while it fetches
Loaded — press “Refresh data” above to see the placeholders again.
Filled
variant: "filled"
For grouping on a busy page, without a border.
🎧
Horizontal
media on the left
Rows of results, a cart line, a notification with a picture.
Usage
import { signal, html } from "./index.js";import { Card, StatCard } from "./components/card.js"; Card({ title: "Team", subtitle: "3 of 5 seats", icon, actions: inviteButton, children: list, footer: html`…`, collapsible: true, variant: "outlined" | "elevated" | "filled" | "ghost" })Card({ media: "/cover.jpg", title: "Dolomites", href: "/trips/dolomites", badge }) // one big linkCard({ title: "Team plan", selected: isTeam }) // a checkable choiceCard({ title: "Report", loading: busy, children: () => table }) // placeholders while busy StatCard({ label: "Revenue", value: revenue, format: { style: "currency", currency: "USD" }, delta: 12.4, deltaLabel: "vs last month", spark: last30, loading: busy })StatCard({ label: "Churn", value: churn, suffix: "%", delta: -0.8, invert: true }) // a fall is good