Skip to content
Nizivo UI

Card

A surface with optional header, title, description, action, body and footer parts. The inverse tone flips every token inside it; brand and accent are the tinted surfaces of the dashboard widgets (KpiTile's tone), with no stroke.

Server component, no client JS

Import

import { Card } from '@nizivo/react/card';

// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css
import '@nizivo/react/css/card.css';

Static or interactive

Server. It ships no client JavaScript when a Server Component renders it, in every Next.js build mode; its code is bundled only when a client component (a 'use client' file) imports it. Every part is server-safe; a child you put in Card.Action ships whatever its own component ships. How to choose.

In a client app (a Vite or React Router single-page app, or a 'use client' file) it is an ordinary React component: event handlers, refs and state work as usual. In a client app.

Tones

tone="brand" and tone="accent" are new in 0.2.0; 0.1.0 has surface, subtle and inverse only. In dark mode bg/brand-subtle and bg/accent-subtle are both green-950, so the two tints look the same there. That is Figma's design, and the code follows it for now (Figma 04 issue 5; the maintainer's decision M42).

On brand and accent, a Delta inside the Card is drawn as a bg/surface pill, so it shows on the tint: Figma's bg/success-subtle pill is the same colour as bg/brand-subtle (green-50 in light, and all three are green-950 in dark), so it would show no fill. This is a deviation from Figma 04 (gap 4) that the maintainer chose (M42). The pill's text keeps its colour, at least 5.68:1 on bg/surface in light and 5.96:1 in dark (text/critical; CONTRAST.md). The nearest Card decides: a Delta inside an untinted Card nested in a tinted one keeps its own pill. A --nz-delta-bg you set still wins.

The surface variable

Card declares --nz-surface, the colour it paints, in every tone (and so do KpiTile and TrendCard, which are Cards). Any child can read it to match the surface it sits on, for example a ring or a gap that should look cut out of the card:

.my-marker {
  box-shadow: 0 0 0 2px var(--nz-surface, var(--nz-bg-surface));
}
  • It is read-only: Card sets it; set --nz-card-bg to change the surface, and --nz-surface follows.
  • It is not a token. Outside a Card it is undefined, so always read it with a fallback.
  • Inside tone="inverse" it resolves in the inverse colour scheme, as every token there does.
  • @nizivo/charts reads it with a fallback: a Sparkline's end-dot halo, for example, takes the tinted tile's colour instead of a white ring, and still works on a page without @nizivo/react.

Examples

Basic

Top products

Last 30 days

Stoneware mug In stock

Plan

Grow, billed monthly
Share your store to get your first order.
import type { JSX } from 'react';
import { Badge } from '@nizivo/react/badge';
import { Button } from '@nizivo/react/button';
import { Card } from '@nizivo/react/card';

export function CardExample(): JSX.Element {
  return (
    <div>
      <Card.Root>
        <Card.Header>
          <Card.Title>Top products</Card.Title>
          <Card.Description>Last 30 days</Card.Description>
          <Card.Action>
            <Button variant="tertiary" size="sm">
              View all
            </Button>
          </Card.Action>
        </Card.Header>
        <Card.Body>
          Stoneware mug <Badge tone="success">In stock</Badge>
        </Card.Body>
        <Card.Footer>
          <Button size="sm">Export</Button>
        </Card.Footer>
      </Card.Root>
      <Card.Root tone="subtle">
        <Card.Title level={2}>Plan</Card.Title>
        <Card.Body>Grow, billed monthly</Card.Body>
      </Card.Root>
      <Card.Root tone="inverse" render={<section aria-label="Tip" />}>
        <Card.Body>Share your store to get your first order.</Card.Body>
      </Card.Root>
    </div>
  );
}

Tones

The tinted surfaces (M41): a row of related widgets shares one tint; it never encodes data.

Holiday drop is ready

Brand: bg/brand-subtle, no stroke.

Restock soon

Accent: bg/accent-subtle, no stroke.
import type { JSX } from 'react';
import { Card } from '@nizivo/react/card';

export function CardTonesExample(): JSX.Element {
  return (
    <div>
      <Card.Root tone="brand">
        <Card.Title>Holiday drop is ready</Card.Title>
        <Card.Body>Brand: bg/brand-subtle, no stroke.</Card.Body>
      </Card.Root>
      <Card.Root tone="accent">
        <Card.Title>Restock soon</Card.Title>
        <Card.Body>Accent: bg/accent-subtle, no stroke.</Card.Body>
      </Card.Root>
    </div>
  );
}

Parts

Use the parts through the namespace (Card.Root) or by their flat names (CardRoot); both work from Server Components.

Card.Root

Server component Renders data-slot="card" with the class nz-card. Props: CardRootProps. Source: src/card/card.tsx.

NameTypeDefaultDescription
elevationCardElevation
01
0

No shadow at rest until design says otherwise (decision 8j).

paddingCardPadding
"sm""md"
'md'
renderRenderProp<CardRootState>–
toneCardTone
"surface""subtle""inverse""brand""accent"
'surface'

inverse sets data-nz-scheme="inverse", so every token inside resolves in the inverse scheme. Every tone declares --nz-surface, the colour the card paints, for children to read with a fallback (var(--nz-surface, var(--nz-bg-surface))); on brand and accent a Delta pill inside is bg/surface, so it shows on the tint (M42).

  • Also takes every attribute of <div>. (ComponentPropsWithRef<"div">)

render takes an element, or, in client code, a function of the props and this state (CardRootState):

NameTypeDefaultDescription
elevationrequiredCardElevation
01
–
paddingrequiredCardPadding
"sm""md"
–
tonerequiredCardTone
"surface""subtle""inverse""brand""accent"
–

Card.Header

Server component Renders data-slot="card-header" with the class nz-card-header. Props: CardHeaderProps. Source: src/card/card.tsx.

NameTypeDefaultDescription
renderRenderProp<Record<string, never>>–
  • Also takes every attribute of <div>. (ComponentPropsWithRef<"div">)

render takes an element, or, in client code, a function of the props and no state.

Card.Title

Server component Renders data-slot="card-title" with the class nz-card-title. Props: CardTitleProps. Source: src/card/card.tsx.

NameTypeDefaultDescription
levelCardTitleLevel
23456
3

The heading level; its look is Heading/H4 at every level.

renderRenderProp<Record<string, never>>–
  • Also takes every attribute of <h3>. (ComponentPropsWithRef<"h3">)

render takes an element, or, in client code, a function of the props and no state.

Card.Description

Server component Renders data-slot="card-description" with the class nz-card-description. Props: CardDescriptionProps. Source: src/card/card.tsx.

NameTypeDefaultDescription
renderRenderProp<Record<string, never>>–
  • Also takes every attribute of <p>. (ComponentPropsWithRef<"p">)

render takes an element, or, in client code, a function of the props and no state.

Card.Action

Server component Renders data-slot="card-action" with the class nz-card-action. Props: CardActionProps. Source: src/card/card.tsx.

NameTypeDefaultDescription
renderRenderProp<Record<string, never>>–
  • Also takes every attribute of <div>. (ComponentPropsWithRef<"div">)

render takes an element, or, in client code, a function of the props and no state.

Card.Body

Server component Renders data-slot="card-body" with the class nz-card-body. Props: CardBodyProps. Source: src/card/card.tsx.

NameTypeDefaultDescription
renderRenderProp<Record<string, never>>–
  • Also takes every attribute of <div>. (ComponentPropsWithRef<"div">)

render takes an element, or, in client code, a function of the props and no state.

Server component Renders data-slot="card-footer" with the class nz-card-footer. Props: CardFooterProps. Source: src/card/card.tsx.

NameTypeDefaultDescription
renderRenderProp<Record<string, never>>–
  • Also takes every attribute of <div>. (ComponentPropsWithRef<"div">)

render takes an element, or, in client code, a function of the props and no state.

Other exports

CardActionProps type

import type { CardActionProps } from '@nizivo/react/card'

Figma "Show action": the control at the end of the header, for example an IconButton.

The props of Card.Action, listed above.

CardBodyProps type

import type { CardBodyProps } from '@nizivo/react/card'

Figma's "Slot" frame.

The props of Card.Body, listed above.

CardDescriptionProps type

import type { CardDescriptionProps } from '@nizivo/react/card'

The props of Card.Description, listed above.

CardElevation type

import type { CardElevation } from '@nizivo/react/card'

0 draws no shadow (the rest elevation); 1 draws --nz-elevation-1.

type CardElevation = 0 | 1

CardFooterProps type

import type { CardFooterProps } from '@nizivo/react/card'

The props of Card.Footer, listed above.

CardHeaderProps type

import type { CardHeaderProps } from '@nizivo/react/card'

The props of Card.Header, listed above.

CardPadding type

import type { CardPadding } from '@nizivo/react/card'

24 px (md, Figma) or 20 px (sm).

type CardPadding = "sm" | "md"

CardRootProps type

import type { CardRootProps } from '@nizivo/react/card'

The props of Card.Root, listed above.

CardRootState type

import type { CardRootState } from '@nizivo/react/card'

The render state of Card.Root, listed above.

CardTitleLevel type

import type { CardTitleLevel } from '@nizivo/react/card'

type CardTitleLevel = 2 | 3 | 4 | 5 | 6

CardTitleProps type

import type { CardTitleProps } from '@nizivo/react/card'

The props of Card.Title, listed above.

CardTone type

import type { CardTone } from '@nizivo/react/card'

Figma "Style": Surface | Subtle | Inverse, plus the tinted surfaces of the dashboard widgets (KPI Tile "Tinted", Insight Card Brand and Accent; figma/04 §2/§3, M41): brand (bg/brand-subtle) and accent (bg/accent-subtle).

type CardTone = "surface" | "subtle" | "inverse" | "brand" | "accent"

Data attributes and slots

Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.

SlotRendered byData attributes
card
.nz-card
Card.Root
root (takes render)
  • data-elevation: "1" ← elevation
    The elevation prop; values in each component manifest (Card: 1; absent at rest)
  • data-nz-scheme: "inverse"
    Inverse surface scheme for the subtree
  • data-padding: "sm""md" ← padding
    The padding prop, or the fixed padding of a part drawn on Card's surface, which has no padding prop; values in each component manifest (Card: sm, md; KpiTile: sm; TrendCard: md)
  • data-tone: "surface""subtle""inverse""brand""accent" ← tone
    The tone prop; values in each component manifest
card-action
.nz-card-action
Card.Action
root (takes render)
none
card-body
.nz-card-body
Card.Body
root (takes render)
none
card-description
.nz-card-description
Card.Description
root (takes render)
none
card-footer
.nz-card-footer
Card.Footer
root (takes render)
none
card-header
.nz-card-header
Card.Header
root (takes render)
none
card-title
.nz-card-title
Card.Title
root (takes render)
none

CSS hooks

Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.

HookDefaultRead as
--nz-card-bg
  • default: var(--nz-bg-surface)
  • data-tone="accent": var(--nz-bg-accent-subtle)
  • data-tone="brand": var(--nz-bg-brand-subtle)
  • data-tone="subtle": var(--nz-bg-subtle)
  • --nz-surface on .nz-card
  • background on .nz-card
--nz-card-border
  • default: var(--nz-border-subtle)
  • data-tone="accent": transparent
  • data-tone="brand": transparent
  • data-tone="inverse": transparent
  • data-tone="subtle": transparent
  • border on .nz-card
--nz-card-gap--nz-space-5
  • gap on .nz-card
--nz-card-padding
  • default: var(--nz-space-6)
  • data-padding="sm": var(--nz-space-5)
  • padding on .nz-card
--nz-card-radius--nz-radius-xl
  • border-radius on .nz-card
--nz-card-shadow
  • default: none
  • data-elevation="1": var(--nz-elevation-1)
  • box-shadow on .nz-card
--nz-card-title-font--nz-font-heading-h4
  • font on .nz-card-title

Layers: nz.components. Classes: .nz-card, .nz-card-action, .nz-card-body, .nz-card-description, .nz-card-footer, .nz-card-header, .nz-card-title, .nz-delta.

Tokens this stylesheet reads (19)

--nz-bg-accent-subtle, --nz-bg-brand-subtle, --nz-bg-subtle, --nz-bg-surface, --nz-border-subtle, --nz-border-width-default, --nz-elevation-1, --nz-font-body-m, --nz-font-heading-h4, --nz-icon-secondary, --nz-radius-xl, --nz-space-1, --nz-space-2, --nz-space-3, --nz-space-5, --nz-space-6, --nz-text-primary, --nz-text-secondary, --nz-tracking-heading-h4

Accessibility

Nothing in this component takes focus or keyboard input.

Keyboard

None.

Figma

Node ids from design/component-map.json, which nz gen writes from component.json. The links open the Nizivo Figma library, which may ask you to sign in.

On this page