Item Card

A versatile list card with icon, title, description, and optional trailing actions like switches or selects.

Usage

Mobile dataRoaming is currently active
Active
Dark modeMatch the system appearance
BackupLast synced 2 hours ago

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

MacBook Pro 16”macOS 15.3 · Portland
This device
iPhone 15 ProiOS 18.3 · Portland
2 hours ago
iPad AiriPadOS 18.2 · Seattle
5 days ago
Apple Watch Series 10watchOS 11.3 · Portland
Update

Email Setting

jane.doe@example.comVerified · all notifications
Primary
j.doe@work.example.comVerified · billing only
jdoe@old.example.comUnverified · added 3 days ago

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

Language
English
Time zone
GMT+1
Appearance
System

Variants

defaultSurface background with a 1px border
secondarySecondary surface with a 1px border
tertiaryTertiary surface with a 1px border
outline1px border over a transparent background
transparentNo background and no border

Vertical Stack

Wi-FiBlake-Office-5G · 802.11ax · signal excellent
Connected
BluetoothAirPods Pro, Magic Mouse
2 devices
Location Services12 apps have access
While using
Touch IDUnlock and Apple Pay
Enabled

Wallet Card

Visa •••• 4242Expires 08 / 2028
Default
Mastercard •••• 8319Expires 02 / 2027
Chase •••• 6610ACH direct debit
Verifying

With Multi Select

Alert channelsWhere incidents are delivered
Second factorsMethods your team may enrol

With Select

LanguageUsed across the dashboard
Time zoneTimestamps and schedules
AppearanceFollow the system or pin one

With Switch

Dark modeMatch the system appearance
Push notificationsAlerts on this device
LocationAllow apps to use your location

Without Icon

PlanRenews 12 Aug 2026
Pro
Seats8 of 10 used
InvoicesNext charge on 12 Aug 2026

CSS Classes

Base Class

  • .item-card — The row itself. display: flex with align-items: center, a --spacing * 3 gap, border-radius: --radius * 2, and --spacing * 4 inline / --spacing * 3 block 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--defaultbackground-color: --surface plus 1px solid --border. Bordered and flat, like every variant below it.
  • .item-card--secondarybackground-color: --surface-secondary plus 1px solid --border.
  • .item-card--tertiarybackground-color: --surface-tertiary plus 1px solid --border.
  • .item-card--outline1px solid --border over a transparent background. It differs from default only in the fill.
  • .item-card--transparent — Transparent background, no border, and box-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 * 9 on both axes, border-radius: --radius * 1, background-color: --default, color: --foreground, and flex-shrink: 0 so it survives a crowded row. A descendant svg is forced to --spacing * 4 on both axes, so the icon size is the slot's decision rather than the icon's.
  • .item-card__contentflex: 1 with flex-direction: column and min-width: 0. That min-width is 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: nowrap with overflow: hidden and text-overflow: ellipsis — and width: fit-content. Note that the fit-content resolves 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. Add max-w-full to 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 for max-w-full.
  • .item-card__actionmargin-left: auto pins it to the trailing edge, flex-shrink: 0 keeps it at its natural size while the content column absorbs the squeeze, and padding-left: --spacing * 2 holds 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 to color-mix(in oklab, var(--surface) 50%, transparent), because --default has 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.

PropTypeDefaultDescription
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) => ReactElementReplaces 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.
childrenReactNodeThe 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.
classNamestringMerged 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.

PropTypeDefaultDescription
childrenReactNodeThe icon. Its own width and height are overridden by the slot, so an icon set's default size does not change the row.
classNamestringMerged 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.

PropTypeDefaultDescription
childrenReactNodeNormally ItemCard.Title and ItemCard.Description, stacked. The description is optional.
classNamestringMerged onto .item-card__content.

Also accepts every native div attribute.

ItemCard.Title

The primary label. A span, single-line and ellipsised.

PropTypeDefaultDescription
childrenReactNodeThe 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.
classNamestringMerged onto .item-card__title.

Also accepts every native span attribute.

ItemCard.Description

The supporting line. A span in --muted, truncated like the title.

PropTypeDefaultDescription
childrenReactNodeThe 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.
classNamestringMerged 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.

PropTypeDefaultDescription
childrenReactNodeThe 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.
classNamestringMerged onto .item-card__action.

Also accepts every native div attribute.

On this page