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.
pnpm dlx shadcn add @01orbital/headline-cardnpx shadcn add @01orbital/headline-cardyarn shadcn add @01orbital/headline-cardbunx --bun shadcn add @01orbital/headline-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/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/sectionnpx shadcn add @01orbital/avatar @01orbital/button @01orbital/sectionyarn shadcn add @01orbital/avatar @01orbital/button @01orbital/sectionbunx --bun shadcn add @01orbital/avatar @01orbital/button @01orbital/sectionThe example also imports @phosphor-icons/react from npm, which the install does not add:
pnpm add @phosphor-icons/reactnpm install @phosphor-icons/reactyarn add @phosphor-icons/reactbun add @phosphor-icons/reactimport { 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>
)
}Headline Card is built from 7 parts. In the example they nest like this:
HeadlineCard
├─ HeadlineCardHeader
│ ├─ HeadlineCardTitle
│ ├─ HeadlineCardDescription
│ └─ HeadlineCardAction
└─ HeadlineCardFooterHeadlineCard: 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.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.
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.
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.
The text under the headline, in the card's text color at 75%.
It accepts the HTML attributes of the element it renders.
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.
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.
npm: @base-ui/react, cn. The CLI installs them for you.
Registry pieces it installs with it:
cardfont-hanken-groteskgridGlow Card
Frosted glass card tinted by the surrounding lamp color, with a corner highlight and either a deep floating shadow with light spill or a short contact shadow. Follows a GlowSection's bulb when nested.
Limned Surface
Dark panel lit at its rim by inset light, with a halo or top-cast glow derived from a ground and glow palette, optional overlay grain and a hover or focus bloom that drops its transition under reduced motion.