Skip to content
Dethink Components

ComponentsCard

Card

Group related content and actions in a single panel.

On this page

Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.

View registry files

Import the component into your page or component file.

Usage
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@dethink/components";

export function Example() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Team plan</CardTitle>
        <CardDescription>Everything your team needs.</CardDescription>
      </CardHeader>
      <CardContent>Invite members and work on projects together.</CardContent>
      <CardFooter>Includes up to 10 members.</CardFooter>
    </Card>
  );
}

Try the examples, then open the code to use them in your app.

Anatomy

Header, title, description, content, and a footer with justified actions.

Usage this month

Track how your workspace is consuming its plan.

12,480 / 20,000 requests

Show sourceexamples/card/basic.tsx
examples/card/basic.tsx
"use client";

import {
  Button,
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@dethink/components";

export function CardBasic() {
  return (
    <Card className="w-full max-w-sm">
      <CardHeader>
        <CardTitle>Usage this month</CardTitle>
        <CardDescription>
          Track how your workspace is consuming its plan.
        </CardDescription>
      </CardHeader>
      <CardContent>
        <p className="font-heading text-3xl font-semibold">
          12,480{" "}
          <span className="text-muted-foreground text-sm font-normal">
            / 20,000 requests
          </span>
        </p>
      </CardContent>
      <CardFooter justify="end">
        <Button variant="ghost">Dismiss</Button>
        <Button variant="soft">Upgrade plan</Button>
      </CardFooter>
    </Card>
  );
}

Header action

CardAction pins controls to the end of the header โ€” icon buttons, menus, or badges โ€” while the title and description keep their column.

Team members

People with access to this project.

  • Amara OseiOwner
  • Jonas WeberEditor
  • Priya NairViewer
Show sourceexamples/card/action.tsx
examples/card/action.tsx
"use client";

import {
  Button,
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@dethink/components";
import { Settings2 } from "lucide-react";

const members = [
  { name: "Amara Osei", role: "Owner" },
  { name: "Jonas Weber", role: "Editor" },
  { name: "Priya Nair", role: "Viewer" },
];

export function CardWithAction() {
  return (
    <Card className="w-full max-w-sm">
      <CardHeader>
        <CardTitle>Team members</CardTitle>
        <CardDescription>People with access to this project.</CardDescription>
        <CardAction>
          <Button size="icon" variant="ghost" aria-label="Manage team settings">
            <Settings2 className="size-4" />
          </Button>
        </CardAction>
      </CardHeader>
      <CardContent>
        <ul className="divide-border divide-y">
          {members.map((member) => (
            <li
              key={member.name}
              className="flex items-center justify-between py-2.5 text-sm"
            >
              <span className="font-medium">{member.name}</span>
              <span className="text-muted-foreground">{member.role}</span>
            </li>
          ))}
        </ul>
      </CardContent>
    </Card>
  );
}

Surfaces, borders, and spacing

Mix surface, border, shadow, radius, and spacing to move between elevated cards, quiet sections, and dense dashboard tiles.

shadow="md"

Elevated surface.

surface="muted"

Quiet, recessed section.

spacing="sm"

Dense dashboards.

surface="transparent"

Structure without chrome.

Show sourceexamples/card/options.tsx
examples/card/options.tsx
"use client";

import { Card, CardContent } from "@dethink/components";

export function CardOptions() {
  return (
    <div className="grid w-full gap-4 sm:grid-cols-2">
      <Card surface="default" shadow="md">
        <CardContent className="text-sm">
          <code className="text-primary font-mono text-xs">
            shadow=&quot;md&quot;
          </code>
          <p className="text-muted-foreground mt-1">Elevated surface.</p>
        </CardContent>
      </Card>
      <Card surface="muted" border="muted" shadow="none">
        <CardContent className="text-sm">
          <code className="text-primary font-mono text-xs">
            surface=&quot;muted&quot;
          </code>
          <p className="text-muted-foreground mt-1">Quiet, recessed section.</p>
        </CardContent>
      </Card>
      <Card radius="md" spacing="sm">
        <CardContent className="text-sm">
          <code className="text-primary font-mono text-xs">
            spacing=&quot;sm&quot;
          </code>
          <p className="text-muted-foreground mt-1">Dense dashboards.</p>
        </CardContent>
      </Card>
      <Card surface="transparent" border="none" shadow="none">
        <CardContent className="text-sm">
          <code className="text-primary font-mono text-xs">
            surface=&quot;transparent&quot;
          </code>
          <p className="text-muted-foreground mt-1">
            Structure without chrome.
          </p>
        </CardContent>
      </Card>
    </div>
  );
}

Composition

Cards compose naturally with other Dethink components โ€” here a sign-in form built from Input and Button.

Sign in

Use your work email to continue.

Show sourceexamples/card/form.tsx
examples/card/form.tsx
"use client";

import {
  Button,
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
  Input,
} from "@dethink/components";

export function CardSignInForm() {
  return (
    <Card className="w-full max-w-sm" shadow="md">
      <CardHeader>
        <CardTitle>Sign in</CardTitle>
        <CardDescription>Use your work email to continue.</CardDescription>
      </CardHeader>
      <CardContent className="space-y-4">
        <div className="space-y-1.5">
          <label htmlFor="signin-email" className="text-sm font-medium">
            Email
          </label>
          <Input
            id="signin-email"
            type="email"
            placeholder="you@company.com"
            autoComplete="email"
          />
        </div>
        <div className="space-y-1.5">
          <label htmlFor="signin-password" className="text-sm font-medium">
            Password
          </label>
          <Input
            id="signin-password"
            type="password"
            autoComplete="current-password"
          />
        </div>
      </CardContent>
      <CardFooter>
        <Button className="w-full">Continue</Button>
      </CardFooter>
    </Card>
  );
}

Card and its section components accept all native attributes of the element they render.

Card props
PropWhat it doesDefault
surface"default" | "muted" | "transparent"Sets the card background."default"
border"default" | "muted" | "none"Sets the card border style."default"
radius"md" | "lg"Sets how rounded the corners are."lg"
shadow"none" | "sm" | "md"Sets the shadow below the card."sm"
spacing"sm" | "md" | "lg"Sets the padding and gaps inside each card section. Follows the app density setting."md"
as"div" | "article" | "section" | "aside" | "li"The HTML element to render."div"
asChildbooleanApplies the card styles to its single child instead of adding a wrapper.false

Section components

Card subcomponent props
PropWhat it doesDefault
CardHeaderas: "div" | "header" | "section"Groups the title, description, and optional action."div"
CardTitleas: "div" | "h2"โ€“"h6"Heading of the card. Pick the level that fits the page outline."h3"
CardDescriptionas: "p" | "div" | "span"Adds supporting text below the title."p"
CardActionas: "div" | "span"Places a button, menu, or badge beside the title."div"
CardContentas: "div" | "section"Main body of the card."div"
CardFooteras + justify: "start" | "between" | "end"Places actions at the bottom. Use justify to align them."div", "start"