Card

Headline Card

Card preset with wider spacing, a display title, muted description and bottom-pinned footer, plus a group that aligns title, description and footer rows across neighbouring cards with subgrid.

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/headline-card
npx shadcn add @01orbital/headline-card
yarn shadcn add @01orbital/headline-card
bunx --bun shadcn add @01orbital/headline-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/headline-card.tsx, as source you own and edit.

The example also uses avatar, button and section. Install them too:

pnpm dlx shadcn add @01orbital/avatar @01orbital/button @01orbital/section
npx shadcn add @01orbital/avatar @01orbital/button @01orbital/section
yarn shadcn add @01orbital/avatar @01orbital/button @01orbital/section
bunx --bun shadcn add @01orbital/avatar @01orbital/button @01orbital/section

The example also imports @phosphor-icons/react from npm, which the install does not add:

pnpm add @phosphor-icons/react
npm install @phosphor-icons/react
yarn add @phosphor-icons/react
bun add @phosphor-icons/react

Usage

import { ArrowRightIcon } from "@phosphor-icons/react/dist/ssr"
import { cn } from "cn"

import {
  HeadlineCard,
  HeadlineCardAction,
  HeadlineCardDescription,
  HeadlineCardFooter,
  HeadlineCardHeader,
  HeadlineCardTitle,
} from "@/components/card/headline-card"
import {
  Section,
  SectionColumns,
  SectionContent,
} from "@/components/editorial/section"
import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { buttonVariants } from "@/components/ui/button"

const COPY = {
  title: "Headlines that earn the scroll",
  body: "Name what you do in the words your customers already use, then cut every word that does not move them to read on.",
  author: "Mae Jemison",
  role: "Copywriting",
  title2: "Small words that carry a product",
  body2:
    "Labels, errors and empty states decide whether people know what to do next.",
  author2: "Ellen Ochoa",
  role2: "UX writing",
} as const

export default function HeadlineCardDemo() {
  return (
    <Section>
      <SectionContent className="items-center">
        <SectionColumns className="max-w-4xl items-stretch gap-6 @xl/section:grid-cols-2 @5xl/section:max-w-4xl">
          <HeadlineCard>
            <HeadlineCardHeader>
              <HeadlineCardTitle>{COPY.title}</HeadlineCardTitle>
              <HeadlineCardDescription>{COPY.body}</HeadlineCardDescription>
              <HeadlineCardAction>
                <a
                  href="#"
                  data-slot="button"
                  className={cn(
                    buttonVariants({ variant: "secondary", size: "icon-lg" })
                  )}
                  aria-label={`Read: ${COPY.title}`}
                >
                  <ArrowRightIcon aria-hidden="true" />
                </a>
              </HeadlineCardAction>
            </HeadlineCardHeader>
            <HeadlineCardFooter>
              {/* The byline sits on the card's own padding, in its ink. */}
              <div className="flex items-center gap-3 text-sm/5">
                <Avatar aria-hidden="true">
                  <AvatarFallback>{COPY.author[0]}</AvatarFallback>
                </Avatar>
                <div>
                  <p className="font-medium">{COPY.author}</p>
                  <p>{COPY.role}</p>
                </div>
              </div>
            </HeadlineCardFooter>
          </HeadlineCard>
          <HeadlineCard className="dark surface-paper">
            <HeadlineCardHeader>
              <HeadlineCardTitle>{COPY.title2}</HeadlineCardTitle>
              <HeadlineCardDescription>{COPY.body2}</HeadlineCardDescription>
            </HeadlineCardHeader>
            <HeadlineCardFooter>
              {/* The byline sits on the card's own padding, in its ink. */}
              <div className="flex items-center gap-3 text-sm/5">
                <Avatar aria-hidden="true">
                  <AvatarFallback>{COPY.author2[0]}</AvatarFallback>
                </Avatar>
                <div>
                  <p className="font-medium">{COPY.author2}</p>
                  <p>{COPY.role2}</p>
                </div>
              </div>
            </HeadlineCardFooter>
          </HeadlineCard>
        </SectionColumns>
      </SectionContent>
    </Section>
  )
}

Anatomy

Headline Card is built from 7 parts. In the example they nest like this:

HeadlineCard
├─ HeadlineCardHeader
│  ├─ HeadlineCardTitle
│  ├─ HeadlineCardDescription
│  └─ HeadlineCardAction
└─ HeadlineCardFooter
  • HeadlineCard: A Card for a headline, such as an article or a case study. It is at least 320px tall, with padding that grows from 32px to 40px on screens 42rem and wider. Put a HeadlineCardHeader and a HeadlineCardFooter inside.
  • HeadlineCardHeader: The top of a HeadlineCard, holding the HeadlineCardTitle, HeadlineCardDescription and an optional HeadlineCardAction. The copy is capped at 28rem wide and the action sits at the card's far edge.
  • HeadlineCardTitle: The card's headline, an h3 in the display font that steps up a size from the sm breakpoint. Pass render to use another heading level.
  • HeadlineCardDescription: The text under the headline, in the card's text color at 75%.
  • HeadlineCardAction: A place at the far edge of the HeadlineCardHeader for a button or link. It is the stock CardAction.
  • HeadlineCardFooter: The bottom row of a HeadlineCard, pushed to the bottom of the card. It holds a byline, such as an author's avatar and name, or a client name.
  • HeadlineCardGroup: A grid of HeadlineCards that line up across each row. The cards share their title, description and footer rows, so when one title wraps to an extra line, the descriptions beside it still start at the same height.

API reference

HeadlineCard

A Card for a headline, such as an article or a case study. It is at least 320px tall, with padding that grows from 32px to 40px on screens 42rem and wider. Put a HeadlineCardHeader and a HeadlineCardFooter inside.

It uses the card background unless you pass a surface utility, such as surface-frost, in className.

Prop

Type

It also accepts the HTML attributes of the element it renders.

HeadlineCardHeader

The top of a HeadlineCard, holding the HeadlineCardTitle, HeadlineCardDescription and an optional HeadlineCardAction. The copy is capped at 28rem wide and the action sits at the card's far edge.

Unlike the stock CardHeader, it is not a @container, so inside a HeadlineCardGroup it can share the group's rows.

It accepts the HTML attributes of the element it renders.

HeadlineCardTitle

The card's headline, an h3 in the display font that steps up a size from the sm breakpoint. 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.

HeadlineCardDescription

The text under the headline, in the card's text color at 75%.

It accepts the HTML attributes of the element it renders.

HeadlineCardAction

A place at the far edge of the HeadlineCardHeader for a button or link. It is the stock CardAction.

It accepts the HTML attributes of the element it renders.

The bottom row of a HeadlineCard, pushed to the bottom of the card. It holds a byline, such as an author's avatar and name, or a client name.

It accepts the HTML attributes of the element it renders.

HeadlineCardGroup

A grid of HeadlineCards that line up across each row. The cards share their title, description and footer rows, so when one title wraps to an extra line, the descriptions beside it still start at the same height.

It is a Grid with the small gap. cols sets the column count, 2 by default, and the columns step down on narrow widths as Grid's do.

Prop

Type

It also accepts the HTML attributes of the element it renders.

Dependencies

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

Registry pieces it installs with it:

  • card
  • font-hanken-grotesk
  • grid