Application recipes built from existing components — filter bars, inline calls to action, and an index of every recipe on the component pages.

Last updated

Patterns are compositions, not components: copy the markup and change it. Each one uses only components you already have.

Recipe index

Recipe Where
Page header (breadcrumbs, back link, actions, search) SectionHeader
Card header with actions and a menu Card
Table card (title, table, pagination footer) Table
Metric card Stat
Dialog bodies (confirm, form, media, drawer) Dialog
Activity feed Timeline
Conversation and composers Message
Sidebar groups, headings, featured card Sidebar
Table footer with page size Pagination
Date inputs Input
Upload list FileUpload
Tabbed install commands Code
Notification count on an icon button Button
Account switcher crumb Breadcrumbs

Filter bar

Search, a period switch and a Filters popover holding a GET form: the filters submit with zero JS and the server renders the filtered page. Clear is a link to the unfiltered URL, not a reset button: a reset would restore the values the server just rendered. The badge on the trigger counts the applied filters.

Clear
Show code
<div class="flex flex-wrap items-end gap-3">
<div class="min-w-48 flex-1"><Input aria-label="Search projects" placeholder="Search"><Search slot="start" /></Input></div>
<SegmentedControl aria-label="Period" options={['7d', '30d', '12m']} value="30d" />
<Popover id="filters" width="20rem" placement="bottom-end">
  <Button slot="anchor" popovertarget="filters" variant="outline" color="neutral">
    <Filter slot="start" />Filters<Badge slot="end" size="small" rounded>2</Badge>
  </Button>
  <form method="get" class="flex flex-col gap-3">
    <Select label="Status" name="status">…</Select>
    <Select label="Owner" name="owner">…</Select>
    <div class="flex justify-end gap-2">
      <Button href="?" variant="ghost" color="neutral" size="small">Clear</Button>
      <Button type="submit" size="small">Apply</Button>
    </div>
  </form>
</Popover>
</div>

Inline calls to action

Primary action on top on phones (flex-col-reverse), side by side from sm; a media card; an email capture whose button lines up with the field; a checklist.

Upgrade to Pro

Unlimited projects and priority support.

Invite your team

Projects move faster with more hands.

  • Shared boards
  • Comments and mentions
  • Role-based access

Get the changelog

Show code
<Card>
<Heading as="h3" size="h4">Upgrade to Pro</Heading>
<Text size="small" color="neutral-faded">Unlimited projects and priority support.</Text>
<div class="mt-4 flex flex-col-reverse gap-3 sm:flex-row sm:justify-end">
  <Button variant="outline" color="neutral">Compare plans</Button>
  <Button>Upgrade</Button>
</div>
</Card>
<Card mediaPosition="start">
<img slot="media" src="…" alt="" />
<Heading as="h3" size="h4">Invite your team</Heading>
<Text size="small" color="neutral-faded">Projects move faster with more hands.</Text>
<ul class="mt-3 flex flex-col gap-1.5 text-sm">
  <li class="flex items-center gap-2"><CircleCheck class="size-4 text-positive" aria-hidden="true" />Shared boards</li>
  …
</ul>
<Button class="mt-4" size="small">Send invites</Button>
</Card>
<Card>
<Heading as="h3" size="h4">Get the changelog</Heading>
<form class="mt-3 flex flex-col gap-3 sm:flex-row sm:items-end">
  <div class="flex-1"><Input label="Email" type="email" placeholder="you@example.com" /></div>
  <Button type="submit">Subscribe</Button>
</form>
</Card>