Item Card
A versatile list card with icon, title, description, and optional trailing actions like switches or selects.
Usage
Anatomy
Import the ItemCard component and access all parts using dot notation.
import { ItemCard } from "@blakeui/pro-react";
<ItemCard>
<ItemCard.Icon />
<ItemCard.Content>
<ItemCard.Title />
<ItemCard.Description />
</ItemCard.Content>
<ItemCard.Action />
</ItemCard>;Device List
Email Setting
Pressable
There is no pressable variant — render swaps the root element for a button, and the hover, press, and focus treatment comes from utility classes on className.
Title Only
Variants
Vertical Stack
Wallet Card
With Multi Select
With Select
With Switch
Without Icon
CSS Classes
Base Class
.item-card— The row itself.display: flexwithalign-items: center, a--spacing * 3gap,border-radius: --radius * 2, and--spacing * 4inline /--spacing * 3block padding. It carries no background of its own — that is the variant's job — and no hover, press, or focus rule, which is why a pressable row supplies its own.
Variant Classes
.item-card--default—background-color: --surfaceplus1px solid --border. Bordered and flat, like every variant below it..item-card--secondary—background-color: --surface-secondaryplus1px solid --border..item-card--tertiary—background-color: --surface-tertiaryplus1px solid --border..item-card--outline—1px solid --borderover a transparent background. It differs fromdefaultonly in the fill..item-card--transparent— Transparent background, no border, andbox-shadow: none, for a row that sits inside a surface that is already painted. The only variant with no stroke.
Element Classes
.item-card__icon— Leading square:--spacing * 9on both axes,border-radius: --radius * 1,background-color: --default,color: --foreground, andflex-shrink: 0so it survives a crowded row. A descendantsvgis forced to--spacing * 4on both axes, so the icon size is the slot's decision rather than the icon's..item-card__content—flex: 1withflex-direction: columnandmin-width: 0. Thatmin-widthis what makes this column the part that yields when the row runs out of room, instead of the action being pushed out of the card..item-card__title— 0.875rem / 1.25rem at weight 500 in--foreground,white-space: nowrapwithoverflow: hiddenandtext-overflow: ellipsis— andwidth: fit-content. Note that thefit-contentresolves to the text's full max-content width rather than to the column, so the ellipsis does not engage on its own: long text keeps its full width and runs underneath the action. Addmax-w-fullto clamp it to the content column and get real truncation. Every demo on this page does..item-card__description— 0.75rem / 1rem in--muted,margin-top: --spacing * 0.5, with the same truncation rules as the title — and the same need formax-w-full..item-card__action—margin-left: autopins it to the trailing edge,flex-shrink: 0keeps it at its natural size while the content column absorbs the squeeze, andpadding-left: --spacing * 2holds it off the content.
Descendant Rule
:is(.item-card--secondary, .item-card--tertiary) > [data-slot="item-card-icon"]— On the two filled non-default variants the icon square repaints tocolor-mix(in oklab, var(--surface) 50%, transparent), because--defaulthas too little contrast against those surfaces.
Data Attributes
[data-slot="item-card"],[data-slot="item-card-icon"],[data-slot="item-card-content"],[data-slot="item-card-title"],[data-slot="item-card-description"],[data-slot="item-card-action"]— One per part, so any of them can be targeted without depending on its BEM class. The icon rule above is the component's own use of them.
API Reference
ItemCard
The root. A div by default, rendered through the shared DOM-render helper so render can swap the element.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "secondary" | "tertiary" | "outline" | "transparent" | "default" | Which surface the row paints. Every variant except transparent carries a 1px border, and none is elevated. It also decides the icon square's background — see the descendant rule under CSS Classes. |
render | (props, renderProps) => ReactElement | — | Replaces the root div with an element of your own — a link, a button, a router component. Pass the supplied props and the ref straight through; render exactly one element, not a fragment. Name the element you are rendering as a type argument (<ItemCard<"button">>) so the props handed to your callback are typed for it. There is no pressable state of its own, so any hover or press treatment goes on className. |
children | ReactNode | — | The parts. All of them are optional and order is yours — omit ItemCard.Icon for a row with no leading square, omit ItemCard.Description for a single-line row. |
className | string | — | Merged onto .item-card, alongside the variant modifier. |
Also accepts every native div attribute — or, when render retargets the element, that element's attributes.
ItemCard.Icon
The leading square. A div that centres whatever it is given and forces a descendant svg to 16px.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The icon. Its own width and height are overridden by the slot, so an icon set's default size does not change the row. |
className | string | — | Merged onto .item-card__icon. |
Also accepts every native div attribute.
ItemCard.Content
The text column. Takes the remaining width and, because it sets min-width: 0, is the part that yields when the row runs out of room.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Normally ItemCard.Title and ItemCard.Description, stacked. The description is optional. |
className | string | — | Merged onto .item-card__content. |
Also accepts every native div attribute.
ItemCard.Title
The primary label. A span, single-line and ellipsised.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The label. It never wraps. To make long text ellipsise rather than run under the action, pass className="max-w-full" — the part sets width: fit-content, which otherwise keeps its full max-content width. |
className | string | — | Merged onto .item-card__title. |
Also accepts every native span attribute.
ItemCard.Description
The supporting line. A span in --muted, truncated like the title.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The secondary text. Omit the whole part rather than passing an empty string — the top margin belongs to the element, so an empty one still adds height. Truncation needs className="max-w-full", exactly as on the title. |
className | string | — | Merged onto .item-card__description. |
Also accepts every native span attribute.
ItemCard.Action
The trailing slot, pushed to the far edge and held at its natural size.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The trailing control — a Switch, a Select, a Button, a Chip, a chevron. It never shrinks, so give an interactive control here its own accessible name: the title is not associated with it. Leave it out when the root is itself the control. |
className | string | — | Merged onto .item-card__action. |
Also accepts every native div attribute.