Lightweight card shell with an 8px inset that seats a bevelled preview frame, followed by header, title, description and footer. The default variant has a shadow and ring; subtle uses a faint tint.
The source comes with full access.
One payment of $149 ($49 for now) opens the source right here and lets the CLI install every paid component, with lifetime updates.
pnpm dlx shadcn add @01orbital/simple-cardnpx shadcn add @01orbital/simple-cardyarn shadcn add @01orbital/simple-cardbunx --bun shadcn add @01orbital/simple-cardPart of the 01orbital library. With a license, put ORBITAL_TOKEN in .env.local and the same command installs it (licensed install, pricing).
It lands at components/card/simple-card.tsx, as source you own and edit.
The example also uses button and color-field-wash. Install them too:
pnpm dlx shadcn add @01orbital/button @01orbital/color-field-washnpx shadcn add @01orbital/button @01orbital/color-field-washyarn shadcn add @01orbital/button @01orbital/color-field-washbunx --bun shadcn add @01orbital/button @01orbital/color-field-wash"use client"
import { useState } from "react"
import {
SimpleCard,
SimpleCardDescription,
SimpleCardFooter,
SimpleCardFrame,
SimpleCardHeader,
SimpleCardTitle,
} from "@/components/card/simple-card"
import { ColorFieldWash } from "@/components/scene/color-field-wash"
import { Button } from "@/components/ui/button"
// Every word on the page. Change copy here, not in the markup.
const COPY = {
title: "A frame for your work.",
body: "An inset preview, a short introduction, and an action when you need one.",
cta: "Change palette",
title2: "Another perspective.",
body2:
"A second palette in the same frame, with room for the work to speak for itself.",
} as const
const PALETTES = ["navy", "descent", "ember"] as const
export default function SimpleCardDemo() {
const [palette, setPalette] = useState(0)
return (
<div className="grid w-full max-w-4xl place-items-center gap-6 p-6 sm:grid-cols-2">
<SimpleCard className="surface-cardstock surface-depth [--cardstock-color:var(--card)] not-dark:shadow-[inset_0_0_0_1px_color-mix(in_oklab,var(--foreground)_10%,transparent),inset_0_1px_0_color-mix(in_oklab,var(--foreground)_12%,transparent),0_4px_12px_-6px_color-mix(in_oklab,var(--scene)_14%,transparent)]! dark:[--card:oklch(0.22_0.008_260)]">
<SimpleCardFrame className="h-64" aria-hidden="true">
<ColorFieldWash palette={PALETTES[palette]} blur={[20, 22]} />
</SimpleCardFrame>
<SimpleCardHeader>
<SimpleCardTitle>{COPY.title}</SimpleCardTitle>
<SimpleCardDescription className="text-foreground/70">
{COPY.body}
</SimpleCardDescription>
</SimpleCardHeader>
<SimpleCardFooter>
<Button
onClick={() => setPalette((value) => (value + 1) % PALETTES.length)}
>
{COPY.cta}
</Button>
</SimpleCardFooter>
</SimpleCard>
<SimpleCard className="surface-cardstock surface-depth [--cardstock-color:var(--card)] not-dark:shadow-[inset_0_0_0_1px_color-mix(in_oklab,var(--foreground)_10%,transparent),inset_0_1px_0_color-mix(in_oklab,var(--foreground)_12%,transparent),0_4px_12px_-6px_color-mix(in_oklab,var(--scene)_14%,transparent)]! dark:[--card:oklch(0.22_0.008_260)]">
<SimpleCardFrame className="h-64" aria-hidden="true">
<ColorFieldWash palette="descent" blur={[20, 22]} />
</SimpleCardFrame>
<SimpleCardHeader>
<SimpleCardTitle>{COPY.title2}</SimpleCardTitle>
<SimpleCardDescription className="text-foreground/70">
{COPY.body2}
</SimpleCardDescription>
</SimpleCardHeader>
</SimpleCard>
</div>
)
}Simple Card is built from 6 parts. In the example they nest like this:
SimpleCard
├─ SimpleCardFrame
├─ SimpleCardHeader
│ ├─ SimpleCardTitle
│ └─ SimpleCardDescription
└─ SimpleCardFooterSimpleCard: A plain card with an 8px inset around its contents: a SimpleCardFrame preview, then a SimpleCardHeader and SimpleCardFooter. It is its own shell rather than a Card, so the spacing comes from that inset and the parts' own padding, not from a gap between them.SimpleCardFrame: The preview area inside a SimpleCard, with small rounded corners and an inner shadow that sets it into the card like a bevel. It clips what is inside it.SimpleCardHeader: The padded block for a SimpleCardTitle and SimpleCardDescription, under the frame.SimpleCardTitle: The card's title, an h3 in medium weight. Pass render to use another heading level.SimpleCardDescription: Muted supporting text under the SimpleCardTitle.SimpleCardFooter: The bottom row of a SimpleCard, pushed to the bottom of the card, for a link or button.A plain card with an 8px inset around its contents: a SimpleCardFrame preview, then a SimpleCardHeader and SimpleCardFooter. It is its own shell rather than a Card, so the spacing comes from that inset and the parts' own padding, not from a gap between them.
variant="subtle" drops the shadow and ring and uses a faint tint of the text color instead of the card background.
Prop
Type
It also accepts the HTML attributes of the element it renders.
The preview area inside a SimpleCard, with small rounded corners and an inner shadow that sets it into the card like a bevel. It clips what is inside it.
Give it a height or an aspect ratio. A scene placed with absolute inset-0 adds no height of its own.
It accepts the HTML attributes of the element it renders.
The padded block for a SimpleCardTitle and SimpleCardDescription, under the frame.
It accepts the HTML attributes of the element it renders.
The card's title, an h3 in medium weight. Pass render to use another heading level.
It accepts the props of the Base UI part it wraps, and the HTML attributes of the element it renders.
Muted supporting text under the SimpleCardTitle.
It accepts the HTML attributes of the element it renders.
The bottom row of a SimpleCard, pushed to the bottom of the card, for a link or button.
It accepts the HTML attributes of the element it renders.
npm: @base-ui/react, class-variance-authority, cn. The CLI installs them for you.
No other registry pieces.
Metal Card
Linked feature card on a paper metal face in silver, gold or graphite, with a top-right light pool, a frosted glass icon chip, title and description. Also exports the finish alone as MetalFace.
Split Card
Rounded two-column card with copy on one side and a picture or scene on the other, stacking until the Section is 48rem wide. Flip swaps the sides and the hairline divider beside the media is optional.