CardDesign system
ComponentSite and product

Card

Content container with product and site variants.

npx context-ds add card
On the site
In the product

Usage

Use it for

Grouping related content. default in the product, ring on the site.

Avoid

  • Gray card backgrounds
  • Heavy drop shadows
  • Cards inside cards

Dependencies: class-variance-authority

Example

examples/card.tsx
import { Button } from "@/components/ui/button";import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";export function Product() {  return (    <Card className="w-full max-w-sm">      <CardHeader>        <CardTitle>API usage</CardTitle>        <CardDescription>Requests this billing period.</CardDescription>        <CardAction>          <Button variant="ghost" size="sm" asChild><a href="/preview/usage-card/Product">Details</a></Button>        </CardAction>      </CardHeader>      <CardContent>        <p className="font-data text-h4 tabular-nums">48,210</p>      </CardContent>    </Card>  );}export function Site() {  return (    <Card variant="ring" className="w-full max-w-md">      <CardTitle className="text-h4">Search</CardTitle>      <CardDescription className="text-body">Search the web or the news and get ranked results with clean page content, not just links.</CardDescription>    </Card>  );}

Source

components/ui/card.tsx
import * as React from "react";import { cva, type VariantProps } from "class-variance-authority";import { cn } from "@/lib/utils";// The product's card (.glass-card): white, its hairline drawn into the shadow. The site's card sits in a soft blue ring (the ring is// a spread shadow, so it adds no layout size).const cardVariants = cva("flex flex-col bg-surface text-fg", {  variants: {    variant: {      default: "gap-4 rounded-card px-5 py-4 shadow-card",      ring: "gap-4 rounded-card p-6 shadow-[0_0_0_1px_var(--ds-color-border-hairline),0_0_0_var(--ds-space-2)_var(--ds-color-ring-tint)] md:p-8",    },  },  defaultVariants: { variant: "default" },});function Card({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof cardVariants>) {  return <div data-slot="card" className={cn(cardVariants({ variant }), className)} {...props} />;}function CardHeader({ className, ...props }: React.ComponentProps<"div">) {  return <div data-slot="card-header" className={cn("grid auto-rows-min grid-rows-[auto_auto] items-start gap-1 has-data-[slot=card-action]:grid-cols-[1fr_auto]", className)} {...props} />;}function CardTitle({ className, ...props }: React.ComponentProps<"div">) {  return <div data-slot="card-title" className={cn("text-h5 leading-snug font-normal text-fg", className)} {...props} />;}function CardDescription({ className, ...props }: React.ComponentProps<"div">) {  return <div data-slot="card-description" className={cn("text-body-sm leading-relaxed text-fg-muted", className)} {...props} />;}function CardAction({ className, ...props }: React.ComponentProps<"div">) {  return <div data-slot="card-action" className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)} {...props} />;}function CardContent({ className, ...props }: React.ComponentProps<"div">) {  return <div data-slot="card-content" className={cn("text-body-sm text-fg", className)} {...props} />;}function CardFooter({ className, ...props }: React.ComponentProps<"div">) {  return <div data-slot="card-footer" className={cn("flex items-center gap-2", className)} {...props} />;}export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, cardVariants };

Reference: context-dashboard c0ddf7a src/app/globals.css; website src/styles/globals.css (.brand-glass-ring); src/components/sections/home/product-grid.tsx.