Meowland docs
Workbench

Component reference

CardContent

The body of a card.

Preview

CardContent has no story of its own; this one draws it as part of Card.

Project and embedded checks

One project record whose internal checks share a reading surface; standalone items can use their own surface. Actions only echo locally.

packages/meowtail/stories/card.stories.tsxline 35tsx
render: () => (
  <Measure>
    <Stack gap="relaxed" data-card-example>
      <Card as="article" aria-labelledby="card-project-title">
        <CardHeader>
          <CardTitle id="card-project-title">Component checks before release</CardTitle>
          <CardDescription>
            Meowland · This check keeps two changes that need your confirmation.
          </CardDescription>
          <CardAction>
            <IconButton
              label="View project record"
              data-card-action="Selected this project record"
            >
              <Icon name="eye" />
            </IconButton>
          </CardAction>
        </CardHeader>
        <CardContent>
          <Card as="section" aria-labelledby="card-reading-title">
            <CardHeader>
              <CardTitle as="h3" id="card-reading-title">
                Message reading and long code previews
              </CardTitle>
              <CardDescription>
                Body text wrapping and local code scrolling are handled separately.
              </CardDescription>
              <CardAction>
                <Status state="warning" label="Pending" />
              </CardAction>
            </CardHeader>
            <CardContent>
              <p>
                Read a full reply on a narrow screen, then decide whether to adopt the new
                paragraph spacing.
              </p>
            </CardContent>
            <CardFooter>
              <Button
                variant="quiet"
                size="small"
                data-card-action="Opened the reading check record"
              >
                View check record
              </Button>
            </CardFooter>
          </Card>
          <Card as="section" aria-labelledby="card-recovery-title">
            <CardHeader>
              <CardTitle as="h3" id="card-recovery-title">
                Draft recovery after continuous input and a failed submit
              </CardTitle>
              <CardDescription>
                The submitted content and the latest draft are kept separately; editing can
                continue after a failure.
              </CardDescription>
            </CardHeader>
            <CardContent>
              <p>
                When reviewing, use long input and confirm the error message does not cover the
                primary action.
              </p>
              <Card variant="surface">
                <CardHeader>
                  <CardTitle as="h4">A separate verification environment</CardTitle>
                  <CardDescription>
                    This resource needs its own boundary, so the surface is explicit.
                  </CardDescription>
                </CardHeader>
              </Card>
            </CardContent>
          </Card>
        </CardContent>
        <CardFooter>
          <Button data-card-action="Saved the local check conclusion">
            Save check conclusion
          </Button>
          <Button variant="quiet" data-card-action="Kept the record to continue later">
            Continue later
          </Button>
        </CardFooter>
      </Card>
      <Card as="section" aria-labelledby="card-reference-title">
        <CardHeader>
          <CardTitle id="card-reference-title">Related references</CardTitle>
          <CardDescription>
            Standalone items keep their own boundary and are not merged into the project record
            above.
          </CardDescription>
        </CardHeader>
        <CardContent>
          <p>
            The theme only changes visual expression; content structure and actions stay
            available.
          </p>
        </CardContent>
      </Card>
      <Note role="status" data-card-feedback>
        Actions only report back to the local example.
      </Note>
    </Stack>
  </Measure>
)

Installation

bun add meowtail

Usage

Taken from the examples on this page.

usage.tsxtsx
import { CardContent } from "meowtail";

<CardContent>
  <p>
    Read a full reply on a narrow screen, then decide whether to adopt the new
    paragraph spacing.
  </p>
</CardContent>

Examples

Other stories that draw CardContent.

Title, actions, and real container width

A wide card and a narrow sidebar in the same window share the title layout; nested cards, intrinsic button cards, and optional descriptions keep their native structure.

packages/meowtail/stories/card-responsive.stories.tsxline 27tsx
render: () => (
  <Measure width="wide">
    <Stack gap="relaxed">
      <Card data-card-responsive="wide">
        <CardHeader>
          <CardTitle>
            Workspace settings and access rules to verify — A long workspace configuration title
          </CardTitle>
          <CardDescription>
            Changes keep existing content; save after the review is complete.
          </CardDescription>
          <CardAction>
            <Button>View full configuration</Button>
            <Button variant="quiet">Copy configuration link</Button>
          </CardAction>
        </CardHeader>
        <CardContent>
          <Card data-card-responsive="nested">
            <CardHeader>
              <CardTitle>Default nested check item</CardTitle>
              <CardDescription>
                Embedded relationships still share the parent surface.
              </CardDescription>
            </CardHeader>
            <CardContent>
              <Field label="Kept draft" htmlFor="card-responsive-draft">
                <Input id="card-responsive-draft" />
              </Field>
            </CardContent>
          </Card>
        </CardContent>
      </Card>
      <div style={{ width: "300px", maxWidth: "100%" }}>
        <Card data-card-responsive="sidebar">
          <CardHeader>
            <CardAction>
              <Button>View details</Button>
              <Button variant="quiet">Copy link</Button>
            </CardAction>
            <CardTitle>A long sidebar card title with meaningful information</CardTitle>
            <CardDescription>
              A narrow region in the same wide window; actions precede the title in the DOM.
            </CardDescription>
          </CardHeader>
        </Card>
      </div>
      <Inline align="start">
        <Card as="button" data-card-responsive="button">
          <CardHeader>
            <CardTitle>Header-only button card</CardTitle>
            <CardDescription>Content decides the natural width.</CardDescription>
          </CardHeader>
        </Card>
        <Card data-card-responsive="intrinsic">
          <CardHeader>
            <CardTitle>Intrinsic inline card</CardTitle>
            <CardDescription>No hand-written width.</CardDescription>
          </CardHeader>
        </Card>
      </Inline>
      <Card data-card-responsive="title-only">
        <CardHeader>
          <CardTitle>No empty description row when there is only a title</CardTitle>
          <CardAction>
            <Button>Check results</Button>
          </CardAction>
        </CardHeader>
      </Card>
    </Stack>
  </Measure>
)

Preserve existing content

Light defaults to editable and dark to loading; input nodes and drafts stay unchanged across the switch. Actions sit outside the boundary.

packages/meowtail/stories/skeleton-boundary.stories.tsxline 51tsx
render: () => (
  <SchemePair>
    {(scheme) => {
      const active = signal(scheme === "dark");
      const appended = signal(false);
      const id = scheme === "light" ? "skeleton-boundary-demo" : "skeleton-boundary-other";
      return (
        <Stack gap="normal">
          <SkeletonBoundary id={id} active={active} label={copy.loading}>
            <Card>
              <CardHeader>
                <CardTitle>{copy.project}</CardTitle>
              </CardHeader>
              <CardContent>
                <Stack gap="normal">
                  <Inline align="center">
                    <img
                      src={image}
                      width={96}
                      height={72}
                      alt="Project cover"
                      style={{ borderRadius: "10px" }}
                    />
                    <Stack gap="compact">
                      <Inline align="center" gap="compact">
                        <Icon name="folder" />
                        <span>Design resources</span>
                      </Inline>
                      <span>{copy.note}</span>
                    </Stack>
                  </Inline>
                  <Field label={copy.name} htmlFor={`${id}-name`}>
                    <Input id={`${id}-name`} value={copy.project} />
                  </Field>
                  {mapSignal(appended, (value) =>
                    value ? <p data-testid={`${id}-extra`}>{copy.extra}</p> : null,
                  )}
                </Stack>
              </CardContent>
            </Card>
          </SkeletonBoundary>
          <ActionRow>
            <Button
              data-testid={`${id}-start`}
              variant="outline"
              onClick={() => {
                active.value = true;
              }}
            >
              {copy.start}
            </Button>
            <Button
              data-testid={`${id}-finish`}
              variant="outline"
              onClick={() => {
                active.value = false;
              }}
            >
              {copy.finish}
            </Button>
            <Button
              data-testid={`${id}-append`}
              variant="quiet"
              onClick={() => {
                appended.value = true;
              }}
            >
              {copy.append}
            </Button>
          </ActionRow>
        </Stack>
      );
    }}
  </SchemePair>
)

API reference

Props

Also takes className, children and the attributes and events of its root element.

DOM parts

root

Registry

The component is registered as card-content in the meowtail component registry.