Pattern gallery

Entrance cards

A run of small cards, one per destination, each saying in a sentence why you would go there; the navigation rides the card toolbar.

What this solves

A list of links tells you where you can go; it does not tell you why you would. An entrance card gives each destination its own icon, its name, and one sentence of purpose, so a reader who has never seen the place can pick a door by what they came to do. Grouped under a kicker that names the group and says what it is for, the runs read as a map rather than a menu.
Use it when
  • A home or index page that hands out several documents or sections by intentthe docs home's repo-docs band: Start here, Working here, Canon, Reference, each a kicker with a phrase and three to six cards
  • A group of destinations that differ in purpose more than in kinda README, an install page and a docs map are all markdown; the sentence is what tells them apart
  • Never for a long homogeneous listthirty-four contract docs are a list card with rows, not thirty-four entrance cards

Rendered

Fixture data; check both themes.

Start here

The front door: what this is, how to install the kit, and the map of everything written.

README

The repo's front door. What each layer is, who reads what, and how work happens here.

Install the kit

Prerequisites, the registry line and token, install and pin, the theme import, the bundler contract.

Docs map

What the docs can do, where truth lives for a component, what is on disk where.

patterns/entrance-cards/example.tsxCopy this into a fresh route and it renders as above.
"use client";
import { Button, Card, Kicker, RenderIcon, type IconKeys } from "@versable-git/ui";
// One entrance per destination: a compact card with the destination's icon
// and name, one sentence on why a reader would go there, and the navigation
// in the toolbar with its arrow trailing. A kicker with the group's own icon
// and a phrase saying what the group is for sits above each run of cards.
interface Entrance {
Icon: IconKeys;
title: string;
card: string;
}
const GROUP = {
Icon: "Home" as IconKeys,
label: "Start here",
phrase: "The front door: what this is, how to install the kit, and the map of everything written",
items: [
{ Icon: "Document", title: "README", card: "The repo's front door. What each layer is, who reads what, and how work happens here." },
{ Icon: "Download", title: "Install the kit", card: "Prerequisites, the registry line and token, install and pin, the theme import, the bundler contract." },
{ Icon: "Globe", title: "Docs map", card: "What the docs can do, where truth lives for a component, what is on disk where." },
] satisfies Entrance[],
};
export function EntranceCards() {
return (
<section className="flex flex-col gap-3">
<div className="flex flex-col gap-1">
<Kicker as="h2" className="flex items-center gap-1.5">
<RenderIcon Icon={GROUP.Icon} size={13} className="shrink-0" />
{GROUP.label}
</Kicker>
<p className="text-base-content/70 text-sm">{GROUP.phrase}.</p>
</div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{GROUP.items.map((item) => (
<Card
key={item.title}
compact
noAnimate
className="hover:border-primary/50 transition-colors"
bodyClassName="gap-2"
title={
<span className="flex items-center gap-2">
<RenderIcon Icon={item.Icon} size={16} className="text-primary shrink-0" />
<span className="truncate">{item.title}</span>
</span>
}
toolbar={
<Button href="#" variant="text" size="sm" Icon="Right" iconRight onClick={(e) => e.preventDefault()}>
Open
</Button>
}
>
<p className="text-base-content/70 text-xs">{item.card}</p>
</Card>
))}
</div>
</section>
);
}

Where it ships

  • apps/playground/src/app/docs/repo-docs-band.tsxthe docs home's entrance band: grouped by the rail's sections, the Reference group carrying a callout
  • apps/playground/src/app/landing-sections.tsxthe landing's section cards, the same card-plus-toolbar-arrow shape at a larger size

App-specific: The sentence on each card is written once, beside the destination's registry entry, and read by every surface that shows the card, so the docs home and the rail never describe a document two ways. The card's icon is the destination's own, the one its page title and its sidebar row wear.

@versable-git/ui · composites proven in the apps