Card
A bordered surface for grouping related content.
Something is eating the bell-ropes
Usage
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@kanzo-tech/ui";Anatomy
Card
├── CardHeader
│ ├── CardTitle
│ └── CardDescription
├── CardContent
└── CardFooterVariants
The variants live on CardMedia, not on Card. That is why they were hard to find: the
card itself is just a surface, and what changes is how the media slot at its top behaves.
Plain
Icon
Image
| Variant | What it does |
|---|---|
default | Transparent. The slot holds whatever you put in it. |
icon | Sizes the glyph and keeps the card's own padding. |
image | Bleeds to the edges, clips to the radius, and fills. |
Actions
CardAction and CardFooter both hold controls, and both exist because "an action on a card"
means two different placements: CardAction sits in the header opposite the title — for a badge,
a menu, a single icon button — while CardFooter sits at the bottom, for the actions the card
is for.
Something is eating the bell-ropes
A metric tile, composed
Reach for StatTile first. A dashboard KPI — a figure, a delta
with its comparison period, a sparkline — is a shipped component in the root barrel, and
re-composing one from Card to get it back is work the library already did.
This section is the other case: a tile StatTile does not cover, here one with a status tint and a
whole-card link. It is a composition, not an import, and the point is the three decisions it takes
rather than the parts themselves.
16
waiting for a party
Status belongs on the root, as a data attribute. It is state, not content, and the icon disc
has to read it — off data-status rather than through context, so the part needs no client
boundary. A theme change then re-skins a whole dashboard row without touching a call site.
44
contracts, all halls
16
who can be sent today
3
out, no word expected
3
past the due date
Loading belongs on the two parts that actually swap. The label and the icon are known before the figure is, so they keep rendering; only the value and the description become skeletons, sized to the text they replace so the tile does not jump when the number arrives.
16
waiting for a party
A linked tile is one tab stop, not four. Card takes asChild, so the anchor is the
card: one link target wrapping the whole tile, which is what a tile should be. That is also the
router seam — put your framework's link in there instead of an <a>. See
Link.
API Reference
Card
No props of its own. Extends React.ComponentProps<typeof ark.article> — it renders
<article>, and asChild swaps that for an <a> when the whole card is a link. It owns the
--space padding variable the parts read, so retuning the card's rhythm is one class on the
root.
CardMedia
| Prop | Type | Default |
|---|---|---|
variant | "default" | "icon" | "image" | "default" |
Mirrored to data-variant, which is how Card knows to drop its own top padding for image.
CardHeader
| Prop | Type | Default |
|---|---|---|
title | string | — |
description | string | — |
Both are shorthands: they render a CardTitle and a CardDescription for you. A lone string
child is treated as the title. Extends React.ComponentProps<typeof ark.div>.
Other parts
CardTitle renders <h3> — asChild for another level, so a card contributes to the document
outline at the right depth. CardDescription, CardAction, CardContent and CardFooter
render a div and take that element's props.