ComponentsLayout

Card

A bordered panel that groups related content. Two sizes, a flat or raised surface, and parts for a header, content, and a footer.

Playground

Change the size, surface, and parts of one card.

Meadow project
Spring planting plan · 12 beds
Active

Three tasks are ready to review.

Sizes

Default uses 16px spacing and a 16px title. Small uses 12px spacing and a 14px title for dense grids.

Meadow project

A fictional garden project · default
Active

Three tasks are ready to review.

Seed order

Due Friday · 4 suppliers · sm
Needs input

Two suppliers replied with new prices.

Surfaces

Default sits flat on the page. Raised lifts settings panels that hold their own lists and states.

Garden notes
Nested content inherits the standard page spacing.

Beds 1–4 water at 06:00. Beds 5–8 skip today after rain.

@alex-meadow

Connected

Personal and organization repositories you can access are available to import.

Settings panel

A raised card with only CardContent holds an account list and its loading, empty, error, and unavailable states.

  • @alex-meadow

    Connected
  • @meadow-labs

    Reconnect required

    Reconnect with this same GitHub login to restore access.

  • Unfinished integration

    Not connected

    GitHub sign-in was not completed. Finish connecting or dismiss this attempt.

Local demo · Sample GitHub data · No real GitHub changes

Content list

A raised card with a focusable heading, a bordered list, a stale-data alert, and an empty prompt.

Repositories in Knowledge

Import selected content so you can find it in Knowledge. Connecting an account does not import anything automatically.

  • alex-meadow/garden-plans

    Docs and issues · Synced 5 minutes ago

    Synced
  • meadow-labs/seed-catalog-with-a-very-long-repository-name

    Docs only · 120 of 340 files

    Syncing

Pending items

Small cards in an equal-height grid. The title is a full-width link and the footer stays at the bottom.

Inside page regions

Cards nest in PageContent and in side panels without extra wrappers.

This is the shared page content region.

Garden notes
Nested content inherits the standard page spacing.
Sample local content.
Garden planLocal example
Plant spring bulbs
Owner: Alex Meadow
Ready

Usage

Card usageTSX
import {
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@tulipfarm/sprout/card";

<Card>
  <CardHeader>
    <CardTitle render={<h3 />}>Meadow project</CardTitle>
    <CardDescription>Spring planting plan · 12 beds</CardDescription>
    <CardAction>
      <Badge variant="success">Active</Badge>
    </CardAction>
  </CardHeader>
  <CardContent>Three tasks are ready to review.</CardContent>
  <CardFooter>
    <Button variant="outline">Review tasks</Button>
  </CardFooter>
</Card>

size is "default" (16px padding and gaps, 16px title) or "sm" (12px, 14px title). Both are exposed as the--sprout-card-spacing variable for content that needs to line up with the card edges. surface is "default" or"raised", which tints the panel and adds a soft shadow in light mode for settings panels that sit on a surface of the same color.

The root and every part render a div and take the Base UIrender prop. CardTitle is not a heading by default; pass render={<h3 />} to place it in the document outline. The root exposes data-size and data-surface, and each part has a matching data-slot. cardVariants()returns the root classes for other elements.

Layout

CardHeader is a grid. A CardAction takes a second column and spans the title and description rows. Add aborder-b class to the header to divide it from the content. A CardFooter sits flush with the bottom edge with a tinted background and top border, even when it is wrapped in an element such as<div className="mt-auto"> that pushes it down in an equal-height grid. An image placed first or last runs edge to edge.

Small card in a gridTSX
<article aria-label={task.title} className="grid min-w-0">
  <Card size="sm">
    <CardHeader>
      <Button variant="ghost" size="card-title" nativeButton={false}
        render={<a href={task.href} />}>
        <CheckSquare size={14} aria-hidden="true" />
        <span className="line-clamp-2">{task.title}</span>
      </Button>
    </CardHeader>
    <div className="mt-auto">
      <CardFooter>…</CardFooter>
    </div>
  </Card>
</article>

Raised settings panelTSX
<Card surface="raised">
  <CardContent>
    <div className="space-y-4">…list, alerts, or a StatePanel…</div>
  </CardContent>
</Card>

Accessibility

A card is a plain container with no role and no focus stop. Name the region around it with section or article andaria-label when it stands alone, and render the title as a heading that fits the page outline. Links and buttons inside keep their own focus rings, and long text wraps instead of overflowing. Theme changes fade in 120ms and stop when reduced motion is requested.

Theme tokens

Cards use --sprout-surface, --sprout-line,--sprout-text, --sprout-muted, and--sprout-radius-panel. The footer tints with--sprout-hover. Raised cards use--sprout-card-raised and--sprout-card-raised-shadow, defined for light and dark modes and overridable like any other Sprõut token.