Cardcomponent

Card({ as: Element = "article", children, href, onClick, title = "Open", ...props }: CardProps): ReactElement
ParamType
propsCardProps
Props for Card — combines ClickableProps (for navigable cards) with colour, status, padding, space, typography, width, and shadow variants. required
    .asBlockElement
Element this <Card> renders as, e.g. "header" to output a "<header>" Defaults to "article"
Return
ReactElement

Cards are boxed areas for content to sit within.

  • Rendered as <article> since each card represents a self-contained piece of content (override with props.as).
  • When href or onClick is set the card becomes navigable: a stretched overlay <a> / <button> covers the entire card while the children render normally inside.
  • Real interactive elements inside the card (e.g. inline <a> links) stay clickable thanks to position: relative; z-index: 2 rules in the stylesheet.
  • Accepts a status colour and raw ColorProps — the card styles the box; lay out its contents however the use case needs.
  • Carries a normal drop shadow by default — set shadow="none" to flatten a card, or shadow="small" / shadow="large" to adjust its elevation.

A boxed surface that groups a self-contained piece of content. Rendered as an <article>, painted from the tint ladder (surface, border, text) and styled with rounded corners and padding by default.

Things to know:

  • Set href or onClick to make the whole card navigable — a stretched, visually-hidden overlay <a> / <button> covers the card while the children render normally inside. Real interactive elements inside the card (inline links, buttons) stay clickable and keyboard-focusable.
  • color= and status= move the tint anchor for the card's scope, so the surface, border, text, and hover shade all re-derive together — and nested components (<Tag>, <Preformatted>, <Button>) inherit the same tint.
  • A card styles only the box. Lay out its contents with the usual block components (<Subheading>, <Paragraph>, <Row>, …).
  • Cards carry a normal drop shadow by default — set shadow="none" to flatten a given card, or shadow="small" / shadow="large" to adjust its elevation.
  • Composes the standard styling variants: color, status, padding, space, width, shadow, plus typography.

Usage

Static card

tsx
import { Card, Subheading, Paragraph } from "shelving/ui";

<Card>
  <Subheading>Storage</Subheading>
  <Paragraph>1.2 GB of 5 GB used.</Paragraph>
</Card>
tsx
import { Card, Subheading, Paragraph } from "shelving/ui";

// The entire card is a link; `title` labels the overlay for screen readers.
<Card href="/projects/shelving" title="Open Shelving">
  <Subheading>Shelving</Subheading>
  <Paragraph>TypeScript data toolkit.</Paragraph>
</Card>

Status and colour

tsx
import { Card, Subheading } from "shelving/ui";

<Card status="error"><Subheading>Couldn't load</Subheading></Card>
<Card color="purple" padding="large" space="none"><Subheading>Featured</Subheading></Card>

Shadow

tsx
import { Card, Subheading } from "shelving/ui";

// Flatten one card; raise another.
<Card shadow="none"><Subheading>Flat</Subheading></Card>
<Card shadow="large"><Subheading>Raised</Subheading></Card>

Styling

Card paints from the tint ladder; override these hooks at :root (or any ancestor scope) to retheme. Apply color= / status= (on the card or an ancestor scope) to recolour everything at once — surface, border, text, and hover shade re-derive together; reach for a per-property hook for a single surgical change.

VariableStylesDefault
--card-backgroundSurface fillvar(--tint-90)
--card-hover-backgroundSurface fill when a navigable card is hoveredvar(--tint-95)
--card-colorText colourvar(--tint-00)
--card-borderBorder shorthandvar(--card-stroke) solid var(--tint-80)
--card-strokeBorder / outline thicknessvar(--stroke-normal) (2px)
--card-radiusCorner radiusvar(--radius-normal) (16px)
--card-paddingInner paddingvar(--space-normal) (16px)
--card-spaceOuter block margin (top + bottom)var(--space-paragraph) (16px)
--card-shadowDrop shadowvar(--shadow-normal)
--card-transitionTransitionall var(--duration-fast) (150ms)
--card-focus-borderFocus outlinevar(--stroke-focus) solid var(--color-focus)

Global tokens it reads — move these to retheme broadly rather than overriding ladder steps directly: the tint ladder --tint-00 / --tint-80 / --tint-90 / --tint-95, plus --space-normal, --space-paragraph, --radius-normal, --shadow-normal, --stroke-normal, --stroke-focus, --color-focus, and --duration-fast.

css
/* Theme: flat cards with tighter corners. */
:root {
  --card-shadow: none;
  --card-radius: var(--radius-small);
}

The --card-shadow hook sets the app-wide default; the shadow= variant prop wins over it on a per-card basis.

To recolour cards, apply color= / status= to the card (or a tinted ancestor scope) — e.g. <Card color="purple"> — rather than a per-component tint hook.