Card headers
The title bar of a card: title, badge, description, avatar, and two trailing slots that differ below desktop. Extracted from the vendored table per ADR-0001.
Card headers
The title bar of a card: title, badge, description, avatar, and two trailing slots that differ below desktop. Extracted from the vendored table per ADR-0001.
Demo
One component, ten props. Turn on the avatar for the primary axis, and both trailing slots for the pair the sheet draws.
Team members
10/20 seatsManage your team members and their account permissions here.
The card around it is yours
CardHeader renders bg-primary, its padding and an optional bottom rule — the border, the radius and the shadow belong to the shell you compose it into, which is what makes the same component work inside a table card, a modal and a plain panel.Contextual demo
The title bar of something: a data card, a conversation, a content card, a dashboard. The preview shows all four.
The family
What the module exports, and the adapter in the table that now renders it.
| Component | Description | Import from |
|---|---|---|
| CardHeader | The whole family. One component, ten props, two slots that differ only at Mobile. Everything the sheet draws is here except the card around it. | @/components/application/card-header/card-header |
| TableCard.Header | The adapter. Reads the table's size context, passes it down, turns the divider on. Its public API is unchanged from before the extraction; reach for CardHeader directly anywhere outside a Table. | @/components/application/table/table |
Anatomy
A row: optional avatar, a text block taking the remaining width, up to two trailing slots. Below, every part at once.
Olivia Rhye
New userolivia@untitledui.com
Part | What it is | What it measures |
|---|---|---|
| Root | The header box. Wraps below `md` so the actions can drop to a second row; from `md` up it is one centered row, so the actions and the trailing control share one axis (ruled 2026-08-26). | flex-wrap, items-start, 16px gap, md:flex-nowrap md:items-center |
| Padding | Vertical padding is fixed per size; the side inset is the axis that moves at the breakpoint. | md: 20 vertical, 16 → 24 sides; sm: 16 vertical, 16 → 20 sides |
| Avatar | The family's primary axis. Present, it inserts a row wrapper between the root and the text — top-aligned with a description, centered without one. | 48px, 8px to the text; items-start → items-center when description is absent |
| Text block | Title row over description, and the one place the sheet contradicted itself. | 2px gap, min-w-0, flex-1 |
| Title and badge | A `h2` by default, with the badge beside it. | 6px gap, items-center |
| Description | Wraps. The sheet truncates this at Desktop only; that was normalised away. | text-sm, text-tertiary |
| Actions | The button row. `basis-full` below `md` is what makes it wrap; from `md` up `basis-auto` puts it back on the row, before the trailing slot. | 12px gap, order-3, basis-full → md:basis-auto |
| Content trailing | Rendered bare — the component adds no classes to it. Its order comes from the root's last-child selector, so a content-sized control stays beside the title at every width. | order-2 → md:order-4, set on the root |
| Divider | Off by default. The table turns it on. | 1px border-secondary, bottom |
The avatar axis
The family's primary axis, the one thing TableCard.Header could not express. Two of the four symbols, one wrapper apart.
Team members
10/20 seatsManage your team members and their account permissions here.
Olivia Rhye
New userolivia@untitledui.com
The two trailing slots
actions and contentTrailing behave identically from md up, differently below — the whole reason there are two slots.
Team members
10/20 seatsManage your team members and their account permissions here.
Property | Below md | From md up |
|---|---|---|
| Root direction | one wrapping row | one row, no wrapping |
| Row alignment | items-start — the wrap layout | items-center — actions and the trailing control share one center axis |
| Side padding (md) | 16px | 24px |
| Side padding (sm) | 16px | 20px |
| Actions | own row beneath the text, left-aligned at natural width | beside the text, before the trailing slot |
| Content trailing | beside the title | beside the title, last |
| Vertical padding | 20px (md) / 16px (sm) | unchanged |
Sizes
Two, and only md is the sheet's. sm exists because the table's size context needs a smaller header.
Team members
10/20 seatsManage your team members and their account permissions here.
Team members
10/20 seatsManage your team members and their account permissions here.
Composition
The card is yours: a shell owning border, radius and shadow, a CardHeader with divider on, and the body below the rule.
Team members
10/20 seatsManage your team members and their account permissions here.
Whatever the card is about starts here, under the rule — rows, a chart, a form, a list of members.
The header contributes the rule and nothing else below itself. The body owns its own padding, which is why it can match the header’s inset or deliberately break it, as a full-bleed table does.
TableCard.Headeris an adapter over this exact component: it reads the table’s size from context, passes it down, and sets divider. The whole story — what moved, the adapter’s unchanged API, and when to reach past it — is the Code tab’s “Extracted out of the table” section.
Built from
The pieces with their own docs page. This family re-authors none of them — every part is a slot or rendered unchanged.
Component | Where it’s used here |
|---|---|
| Avatar | The primary axis, passed as a slot. The sheet draws size=“lg” with border and no status dot. |
| Badge | What a string badge becomes: gray, modern, sm — the sheet’s badge exactly. |
| Button | Every action, at size sm — the 36px the frame heights resolve to. |
| Dropdown | The overflow menu. Pass aria-label naming the card it acts on. |
| Table | TableCard.Header is an adapter over this component — one code path for both. |