Skip to content
Dethink Components

ComponentsCard

Card

Group related content and actions in a single panel.

On this page

Install component source from the public registry, or use the local workspace package. Follow the setup guide first. The npm package is not published yet.

View registry files

Implemented with React and browser APIs, without an additional behavior or rendering library.

Shared foundation: React, clsx for conditional classes, tailwind-merge for resolving utility-class conflicts. Styles use Tailwind CSS and Dethink CSS variables.

Based on this component’s source and registry composition. Libraries used only in showcase examples are excluded.

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"