Card

Simple Card

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.

Installation

pnpm dlx shadcn add @01orbital/simple-card
npx shadcn add @01orbital/simple-card
yarn shadcn add @01orbital/simple-card
bunx --bun shadcn add @01orbital/simple-card

Part 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-wash
npx shadcn add @01orbital/button @01orbital/color-field-wash
yarn shadcn add @01orbital/button @01orbital/color-field-wash
bunx --bun shadcn add @01orbital/button @01orbital/color-field-wash

Usage

"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>
  )
}

Anatomy

Simple Card is built from 6 parts. In the example they nest like this:

SimpleCard
├─ SimpleCardFrame
├─ SimpleCardHeader
│  ├─ SimpleCardTitle
│  └─ SimpleCardDescription
└─ SimpleCardFooter
  • SimpleCard: 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.

API reference

SimpleCard

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.

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.

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.

SimpleCardHeader

The padded block for a SimpleCardTitle and SimpleCardDescription, under the frame.

It accepts the HTML attributes of the element it renders.

SimpleCardTitle

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.

SimpleCardDescription

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.

Dependencies

npm: @base-ui/react, class-variance-authority, cn. The CLI installs them for you.

No other registry pieces.