Display
Card.
A panel with header, content and footer slots, plus the grid-patterned art banner from the Lantern directory.
Sign in to the Hub
Publish sites that stay up while your server sleeps.
import { Button } from "@/components/ui/button";
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export default function CardDemo() {
return (
<Card className="w-full max-w-sm">
<CardHeader>
<CardTitle>Sign in to the Hub</CardTitle>
<CardDescription>Publish sites that stay up while your server sleeps.</CardDescription>
<CardAction>
<Button variant="link" size="sm">
Sign up
</Button>
</CardAction>
</CardHeader>
<CardContent className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor="card-email">Email</Label>
<Input id="card-email" type="email" placeholder="you@example.com" />
</div>
<div className="grid gap-2">
<Label htmlFor="card-password">Password</Label>
<Input id="card-password" type="password" />
</div>
</CardContent>
<CardFooter className="flex-col gap-2">
<Button className="w-full">Sign in</Button>
<Button variant="secondary" className="w-full">
Continue with GitHub
</Button>
</CardFooter>
</Card>
);
}Installation#
With the CLI
$npx lanterncn add cardThis also installs the Lantern theme and any Lantern UI components it depends on. The shadcn CLI works directly too: npx shadcn@latest add httptim/lantern-ui/card. See Installation if your project is not set up yet.
Manually
Copy the source into your project
components/ui/card.tsximport * as React from "react"; import { cn } from "@/lib/utils"; function Card({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card" className={cn("flex flex-col gap-6 overflow-hidden rounded-lg border bg-card py-6 text-card-foreground", className)} {...props} /> ); } /** Grid-patterned banner for the top of a card, as on the Lantern directory. */ function CardArt({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-art" className={cn( "relative -mt-6 flex h-40 items-center justify-center border-b bg-accent bg-grid text-[#b7ca9e] [&_svg:not([class*='size-'])]:size-14 [&_svg]:stroke-[1.25]", 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.5 px-6 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("font-display text-xl leading-tight font-medium tracking-tight", className)} {...props} />; } function CardDescription({ className, ...props }: React.ComponentProps<"div">) { return <div data-slot="card-description" className={cn("text-sm text-muted-foreground", 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("px-6", className)} {...props} />; } function CardFooter({ className, ...props }: React.ComponentProps<"div">) { return <div data-slot="card-footer" className={cn("flex items-center px-6 [.border-t]:pt-6", className)} {...props} />; } export { Card, CardArt, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };Update the import paths to match your project
The source imports
cnfrom@/lib/utils.
Usage#
import {
Card,
CardArt,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
} from "@/components/ui/card";<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Content</CardContent>
</Card>Examples#
Directory card with art
hub://guestbook/
Community
Lantern Guestbook
Leave a little warmth for the next traveler.
LuaHub
import { ArrowUpRight, Diamond } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Card, CardArt, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Eyebrow } from "@/components/ui/eyebrow";
export default function CardArtDemo() {
return (
<Card className="w-full max-w-sm gap-4 transition-transform hover:-translate-y-1">
<CardArt>
<Diamond />
<span className="absolute bottom-3 left-4 font-mono text-[8px] tracking-[0.15em] uppercase">hub://guestbook/</span>
</CardArt>
<CardHeader>
<Eyebrow>Community</Eyebrow>
<CardTitle className="flex items-center justify-between">
Lantern Guestbook <ArrowUpRight className="size-4 text-primary" />
</CardTitle>
<CardDescription>Leave a little warmth for the next traveler.</CardDescription>
<div className="mt-2 flex gap-1.5">
<Badge variant="outline">Lua</Badge>
<Badge variant="outline">Hub</Badge>
</div>
</CardHeader>
</Card>
);
}