Kanzo UI
Data display

Card

A bordered surface for grouping related content.

Something is eating the bell-ropes

Q-1041 · Thornmarch · 16 gold
Posted by The Amber Hall.

Usage

import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@kanzo-tech/ui";

Anatomy

Card
├── CardHeader
│   ├── CardTitle
│   └── CardDescription
├── CardContent
└── CardFooter

Variants

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

No media. A surface with content on it.
Forty-four contracts, five halls, one board.

Icon

Sizes the glyph and keeps the card's padding.
For a card that is about a thing with a type.

Image

Bleeds to the edges and clips to the radius.
VariantWhat it does
defaultTransparent. The slot holds whatever you put in it.
iconSizes the glyph and keeps the card's own padding.
imageBleeds 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

Thornmarch · due 1312-10-15
Open
Grade 2Nuisance. Pays 16 gold.

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.

Open contracts

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.

On the board

44

contracts, all halls

Members ready

16

who can be sent today

Parties afield

3

out, no word expected

Overdue

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.

Open contracts

Open contracts

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

PropTypeDefault
variant"default" | "icon" | "image""default"

Mirrored to data-variant, which is how Card knows to drop its own top padding for image.

CardHeader

PropTypeDefault
titlestring
descriptionstring

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.

On this page