Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

Marketing page

The bands a marketing page is made of, from heroes and bento grids to the footer.

A marketing page is a Page of bands on the page grid: a hero, a strip of logos or numbers, a bento grid of features, an article, and a footer. Use these patterns for a product's site. Each band lays itself out by the room it has, in a window or a narrow frame.

The bands

  • Heroes

    SplitHero and CenteredHero open the page: a two-tone headline, a line and actions beside or above a visual that assembles as it arrives.

  • Strips

    LogoStrip lines up partner marks in equal cells, quietly, and StatStrip shows headline numbers that count up once.

  • A bento grid

    Bento lays feature cards on a 12-column grid, each spanning 4, 6, 8 or 12 columns. A card can open into a dialog.

  • An article and a footer

    ArticleLayout sets an article beside a sticky aside, and Footer ends the page with links and small print.

A home page that opens with a split hero:

src/Home.tsx

import type { ReactElement } from "react";
import { Button, Page, SplitHero } from "@butteryui/react";

export function Home(): ReactElement {
  return (
    <Page>
      <SplitHero
        title="Coffee roasted to order."
        titleMore="Every bag ships the week it's roasted."
        actions={
          <Button variant="primary" arrow="forward">
            Shop coffee
          </Button>
        }
        visual={<div className="bag-photo" />}
      />
    </Page>
  );
}

SplitHero

When to use it

Use it for

  • The top of a landing or product page with a product picture or a living demo

Not for

  • Words alone or a very wide visual: use CenteredHero
  • Bands further down a page: use Section

Examples

Hero with a live slide

An opening band whose visual is a slide to try: pick a theme under it and the slide takes it.

Deckhand

Decks that look designed. Pick a theme and see the slide take it.

Quarterly review

Theme 路 Paper

Product hero

A product's opening band with one call to action and a visual of two pieces.

Decks that look designed. Write the slides, pick a theme, and present.

Quarterly review

Theme 路 Ink

Tinted hero

A roastery's home page opening on the palette tint, which sets the band apart from the page under it.

Halfmoon Roastery

Coffee roasted on Thursday. At your door by Saturday.

Small batches from three farms we visit every year.

Guji, Ethiopia

Roasted Thursday 路 Light

Visual first

The visual on the start side, for a band that answers the one above it.

Tilt it. Turn a picture in 3D with one small pad.

Quarterly review

Variants and states

Words and a visual

Seven columns of words beside five of visual, stacked under 1024px of page. The visual's pieces assemble as it arrives.

Deckhand

Decks that look designed. Write the slides, pick a theme, and present from any screen.

Quarterly review

Theme 路 Lilac

Tinted

The band on bg-tint, a soft fill from the palettes, which the headline, its continuation and the body keep AA contrast on in both themes.

Deckhand

Decks that look designed. Write the slides, pick a theme, and present from any screen.

Quarterly review

Theme 路 Lilac

Props

SplitHero

PropTypeDefaultDescription
eyebrowReactNodeA short line above the headline, such as what the product is.
title

required

ReactNodeThe headline's first clause, in the strong color.
titleAs"h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p""h1"What the headline renders as. Defaults to "h1"; use "h2" for a band further down the page.
titleMoreReactNodeThe headline's continuation, in the secondary color.
bodyReactNodeA line or two under the headline.
actionsReactNodeButtons under the body, such as a primary call to action with arrow="forward".
visual

required

ReactNodeThe visual beside the words. Mark its pieces with Stagger.Item and they assemble one after another.
visualSide"start" | "end""end"Which side the visual sits on once there's room for both: "end" (the default) or "start".
variant"plain" | "tinted""plain"How the band is drawn: "plain" (the default) on the surface, or "tinted" on bg-tint, a soft fill from the palettes that the words keep AA contrast on, to set the band apart from the page.

It also takes Omit<ComponentPropsWithRef<"section">, "title">.

Accessibility

A region named by its headline, the page's h1, or an h2 with titleAs="h2" for a band further down. The visual's pieces arrive with a rise and a fade; with reduced motion they simply show.

It takes no keyboard input of its own.

Motion

It appears with a `Presence` preset and leaves faster than it came, in about 60% of the time.

With reduced motion: The visual's pieces are in place from the start, without rising or fading in.

Layout

Its own size container, it fills its parent's width in a Container with 96px of room above and below (64 under 640px wide, 128 from 1024). From 1024px the words take 7 of 12 columns and the visual 5, centered on each other; narrower, the visual sits 48px under the words. The headline wraps at 22ch and the body at 60ch, the actions wrap 24px under the body, and its only hit areas are the actions' own. The band is the surface, or with variant="tinted" bg-tint, a fill from the palettes the words keep AA contrast on.

See it in the Halfmoon shop demo.

CenteredHero

When to use it

Use it for

  • The top of a page with a wide visual, such as a whole app screen
  • A short page with words alone

Not for

  • A tall or narrow visual beside the words: use SplitHero
  • Bands further down a page: use Section

Examples

Launch hero

A launch page's opening band: a link to start, and a button that swaps the sample deck in the visual.

Deckhand

One deck. Ready for the room and the inbox.

Write the slides once, then present them full screen or send them as a PDF.

Start a deck

Spring launch

Tinted band

A closing band on the palette tint, its headline an h2 under the page's own h1.

Your next deck. Ready before the meeting starts.

Words only

A short page's opening band, words alone.

Changelog

What's new. Everything that changed this month.

Variants and states

Words over a wide visual

The words are centered on at most 8 of 12 columns; the visual takes the column's width under them.

One deck. Every screen it plays on.

Wide for a talk, square for a post, tall for a phone.

Your title slide here

Tinted

The band on bg-tint, a soft fill from the palettes, which the words keep AA contrast on in both themes: here a closing band with an h2.

Your next deck. Ready before the meeting starts.

Pick a theme, write the slides and share a link.

Props

CenteredHero

PropTypeDefaultDescription
eyebrowReactNodeA short line above the headline.
title

required

ReactNodeThe headline's first clause, in the strong color.
titleAs"h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p""h1"What the headline renders as. Defaults to "h1"; use "h2" for a band further down the page.
titleMoreReactNodeThe headline's continuation, in the secondary color.
bodyReactNodeA line or two under the headline.
actionsReactNodeButtons under the body.
visualReactNodeThe visual under the words, as wide as the page's column. Mark its pieces with Stagger.Item to assemble them.
variant"plain" | "tinted""plain"How the band is drawn: "plain" (the default) on the surface, or "tinted" on bg-tint, a soft fill from the palettes that the words keep AA contrast on, to set the band apart from the page.

It also takes Omit<ComponentPropsWithRef<"section">, "title">.

Accessibility

A region named by its headline, the page's h1, or an h2 with titleAs="h2" for a band further down. The visual's pieces arrive with a rise and a fade; with reduced motion they simply show.

It takes no keyboard input of its own.

Motion

It appears with a `Presence` preset and leaves faster than it came, in about 60% of the time.

With reduced motion: The visual's pieces show at once instead of rising into place one after another.

Layout

It's its own size container. The words are centered on at most 8 of the page's 12 columns (the whole width under 640px), the headline wrapping at 22ch and the body at 60ch, and the visual takes the column's width 48px under them (64 from 1024px), with 96px above and below the band (64 under 640px, 128 from 1024px). The band is the surface, or with variant="tinted" bg-tint, a fill from the palettes the words keep AA contrast on.

See it in the Halfmoon shop demo.

HeroText

SplitHero and CenteredHero both lay out HeroText, a hero's words, and you can use it in a hero of your own. It takes these props:

PropWhat it is
eyebrowAn optional short line over the headline
titleThe headline's first clause, in display and the strong color
titleMoreThe rest of the headline, in the secondary color
bodyA line under the headline, at most 60 characters wide
actionsButtons 24px under the body, 8px apart
align"start", the default, or "center"
titleAs"h1" by default; "h2" suits a band further down the page
titleIdThe headline's id, so the band it opens can be named by it

src/RoasteryHero.tsx

import type { ReactElement } from "react";
import { Button, HeroText } from "@butteryui/react";

export function RoasteryHero(): ReactElement {
  return (
    <HeroText
      eyebrow="Halfmoon Roastery"
      title="Coffee roasted on Thursday."
      titleMore="At your door by Saturday."
      body="Small batches from three farms we visit every year."
      actions={
        <Button variant="primary" size="cta" arrow="forward">
          Choose a coffee
        </Button>
      }
    />
  );
}

LogoStrip

When to use it

Use it for

  • Showing who uses a product, under a hero or near pricing

Not for

  • Clickable partner links in a list: use a Grid of links
  • Marks you don't have permission to show

Examples

Customer marks

Customers' wordmarks drawn as svgs in currentColor, so they take the strip's quiet color.

  • Tidewater
  • Bramble
  • Quillwork
  • Halcyon

Shaped marks

Under a landing page's opening: a heading, the first four marks, and a button that shows the rest.

Teams that make their decks with us

  • Halcyon
  • Ferro
  • Saltmarsh
  • Copperleaf

Variants and states

Six marks

Each fits a 120 by 24 box in text-tertiary; the cells wrap as the page narrows.

  • Tidewater
  • Bramble
  • Quillwork
  • Halcyon
  • Ferro
  • Lumen

Props

LogoStrip

PropTypeDefaultDescription
label

required

stringNames the row for screen readers, such as "Teams that present with Deckhand".

It also takes ComponentPropsWithRef<"ul">.

LogoStrip.Mark

It also takes ComponentPropsWithRef<"li">.

Accessibility

A list named by label; each mark names itself (alt on an image, aria-label on an svg).

It takes no keyboard input of its own.

Motion

It doesn't move.

With reduced motion: Nothing changes.

Layout

It takes its container's width as a grid of equal cells at least 120px wide, as many to a row as fit and 24px apart, wrapping onto more rows as it narrows. Each mark is fitted into a 120 by 24 box and drawn in text-tertiary, pictures in grayscale, and nothing in it takes presses.

See it in the Halfmoon shop demo.

StatStrip

When to use it

Use it for

  • A few proud numbers on a marketing page: people, countries, things made
  • Numbers in a narrow column beside an article (layout="stacked")

Not for

  • Numbers people work with in an app: use MetricCard
  • Values someone set: never count those up

Examples

Deckhand numbers

Four numbers in equal columns, each counting up once as the strip comes into view.

38templates to start from
12slide layouts
2,400+decks presented a day
98%of exports ready in a second

Launch numbers

A band of four numbers on a launch page.

Presented every day

1.2M+decks presented
48countries
99.9%of exports under a second
6slide sizes

Money stat

Two columns of numbers written your own way: a currency sign and compact figures.

$4.2Mpaid to creators
310creators

Numbers on cards

A roastery's year in numbers, large, each on a card of its own.

312caf茅s we roast for
18farms we buy from
4.9average review
92%of bags shipped the day they're roasted

Variants and states

Four numbers

Each counts up over 800ms once it's in view, in tabular figures with the final number's room kept.

1.2M+decks presented
48countries
99.9%of exports under a second
6slide sizes

Two numbers

24background gradients
18solid colors

Cards

layout cards puts each stat on a card of its own, 16px apart, in the columns a row has.

1.2M+decks presented
48countries
99.9%of exports under a second
6slide sizes

Stacked

layout stacked puts the stats in one column with a hairline between them, for a narrow column such as an aside.

24background gradients
18solid colors
6slide sizes

Large

size lg sets display numbers over body-lg labels, in four columns too.

1.2M+decks presented
48countries
99.9%of exports under a second
6slide sizes

Props

StatStrip

PropTypeDefaultDescription
columns2 | 44How many stats share the row: 2 or 4 (the default). Four fall into two rows of two below 640px of page.
layout"row" | "cards" | "stacked""row"How the stats lay out: "row" (the default), equal columns each behind a 1px hairline; "cards", equal columns 16px apart, each stat on a card of its own; or "stacked", one column with a hairline between stats, for a narrow column such as an aside, whatever columns says.
size"md" | "lg""md""md" (the default): display numbers in two columns and heading-1 in four or stacked, with body labels. "lg": display numbers and body-lg labels in every layout.

It also takes ComponentPropsWithRef<"div">.

Stat

PropTypeDefaultDescription
value

required

numberThe number it shows.
label

required

stringWhat the number counts, under it.
prefixstringWritten before the number, such as a currency sign.
suffixstringWritten after the number, such as "%" or "+".
format((value: number) => string)Writes a number, including the ones it passes while counting. Defaults to the locale's grouping, rounded to the value's decimals.

It also takes ComponentPropsWithRef<"div">.

Accessibility

A list of stats; each reads its final number and its label from the start, since the counting is drawn over a hidden copy. With reduced motion the numbers show at once.

It takes no keyboard input of its own.

Motion

It appears with a `Presence` preset and leaves faster than it came, in about 60% of the time.

With reduced motion: The numbers show their final values at once instead of counting up.

Layout

It fills its parent's width in four equal columns 24px apart (two when columns is 2), each stat behind a 1px hairline, and four fall into two rows of two while the strip is under 640px wide. With layout cards each stat is on a card of its own, padded 24 and 16px from the next; with layout stacked the stats take one column, a hairline and 16px on either side of it between each and the next. Numbers are heading-1 in four columns or stacked and display in two, or display everywhere at size lg, over body labels (body-lg at lg), in tabular figures with room kept for the final number; one too long for its column breaks rather than spilling, and the strip has no hit areas.

See it in the Halfmoon shop demo.

Bento

When to use it

Use it for

  • Showing a product's features as pictures with short titles
  • A mix of large and small cards that should still line up

Not for

  • A list of equal items: use Grid
  • Settings or links: use a settings index or a list

Examples

Card variants

The five card variants in one bento: elevated, outline, soft, tinted and plain.

Roasted to order

elevated

Ships the same week

outline

Pause any time

soft

Gift a subscription

tinted

Brew guides inside

plain

Feature grid

A wide card beside a narrow one, lined up on the page's 12 columns.

Tilt it in 3D

Product shot

Any size

16:9

Features section

A features section on a marketing page, one card with a preview the visitor can switch.

Everything a deck needs

Pick a shape, tilt a picture, and take it with you.

Any size

16:9

Tilt it in 3D

Product shot

Tall card

A tall card two rows high beside two short ones.

Tall for phones

9:16

Wide for talks

16:9

Square for posts

1:1

Variants and states

Feature cards

12 columns from 1024px of grid, 6 from 640, one below that, in 320px rows. Cards lift 2px on hover.

Tilt it in 3D

Product shot

Any size

1:1

16:9

A background for every talk

Gradient

Every change kept

Undo 路 Redo

Variants

elevated, the surface with the card shadow; outline, a 1px edge on the surface; soft, the bg-control fill; tinted, bg-tint from the palettes; plain, no surface, its title on the grid's edge and its visual carrying the shape.

Tilt it in 3D

elevated

Any size

outline

Every change kept

soft

A background for every talk

tinted

Present from any screen

plain

Props

Bento

It also takes ComponentPropsWithRef<"div">.

Bento.Card

PropTypeDefaultDescription
title

required

ReactNodeThe card's title, top left. It names the card.
span4 | 6 | 8 | 126Columns it spans once the grid is 1024px wide: 4, 6 (the default), 8 or 12.
rows1 | 21Rows it spans, each --bt-bento-row (320px) tall: 1 (the default) or 2.
affordanceReactNodeSomething small at the top end, such as an icon or a button.
variant"elevated" | "outline" | "soft" | "plain" | "tinted""elevated"How it draws its surface: "elevated" (the default), the surface with the card shadow; "outline", a 1px edge on the surface; "soft", the bg-control fill; "plain", no surface, its title on the grid's edge and its visual carrying the shape on the section's gray; or "tinted", bg-tint, a soft fill from the palettes its words keep AA contrast on. It lifts 2px on hover; a plain card lifts its visual instead.

It also takes Omit<ComponentPropsWithRef<"article">, "title">.

Also exported

ExportDescription
BentoContext: Context<BentoState | null>The bento a card sits in: an ExpandableCard marks itself open here, and the other cards fade while it is.

Accessibility

Each card is an article named by its title, an h3. Cards that only show a picture take no focus; give an interactive card a control of its own.

It takes no keyboard input of its own.

Motion

It answers the pointer and keyboard focus within `--bt-dur-fast`, such as an arrow growing its stem, without changing size.

With reduced motion: A card, or a plain card's visual, no longer lifts 2px on hover; its shadow still steps up to raised, and a soft card's fill still darkens.

Layout

It's its own size container: from 1024px wide its cards span 4, 6, 8 or 12 of 12 columns, 16px apart; from 640 they take half or all of 6 columns; under 640 they stack. Each row is 320px (--bt-bento-row), a card's title wraps at 22ch, and its visual is clipped at the card's rounded edges. A card draws itself elevated (the default), outline, soft, tinted (bg-tint, which its words keep AA contrast on) or plain, whose title starts on the grid's edge, level with the titles beside it and 16px over a visual with the card's 16px corners and a section's well.

See it in the Halfmoon shop demo.

ArticleLayout

When to use it

Use it for

  • A long read with a table of contents or related links beside it
  • Guides, release notes, a changelog

Not for

  • App screens: use AppShell
  • An article with nothing beside it: put it straight in a Section

Examples

Guide

A short guide with its sections listed beside it.

Start with a title

Type the title in the inspector and it lands on the slide.

Pick a theme

Plain, Paper or Ink, each readable on any background.

A release notes page: the notes on the page grid, related reading beside them and a feedback row after them.

What's new in 2.4

Pictures tilt further, PDF exports keep their shadows, and Undo remembers every change you make.

Were these notes useful?

Variants and states

A guide with its sections beside it

The article takes 8 of 12 columns and the aside the last 3, a column apart. The aside sticks under the bars and stops at the end of the article; under 1024px of room it follows the article.

Making your first deck

Four steps from a blank slide to a deck you can present.

Start with a title

Type the title in the inspector and it lands on the slide with every key. A long title wraps onto a second line rather than shrinking.

Type the title in the inspector and it lands on the slide with every key. A long title wraps onto a second line rather than shrinking.

Pick a theme

Plain lets the background show through, Paper is a soft white and Ink a deep near-black. Each keeps the title readable on any background.

Plain lets the background show through, Paper is a soft white and Ink a deep near-black. Each keeps the title readable on any background.

Tilt a picture

Steer the tilt pad and the picture tips toward you, up to 20 degrees each way. Flat lays it back down.

Steer the tilt pad and the picture tips toward you, up to 20 degrees each way. Flat lays it back down.

Take it with you

Save the deck as a PDF or one slide as a PNG, or press Copy and paste the slide wherever it's going. The export draws the tilt and the shadow just as the editor shows them.

Save the deck as a PDF or one slide as a PNG, or press Copy and paste the slide wherever it's going. The export draws the tilt and the shadow just as the editor shows them.

Props

ArticleLayout

PropTypeDefaultDescription
asideReactNodeWhat goes beside the article, such as a table of contents or related links. With 1024px of room it takes the last 3 of 12 columns and sticks under the bars as the article scrolls; with less it follows the article.
asideLabelstringNames the aside for screen readers, such as "On this page".

It also takes ComponentPropsWithRef<"div">.

Accessibility

The aside is a complementary landmark named by asideLabel. It comes after the article in reading order, and it still does when the two stack.

It takes no keyboard input of its own.

Motion

It doesn't move.

With reduced motion: Nothing changes.

Layout

It's its own size container. From 1024px of room the article takes 8 of 12 columns and the aside the last 3, a column apart, and the aside sticks under the sticky bars with 24px of padding, fitting between them and stopping at the article's end; with less room the aside follows the article as a plain block, 48px under it, and the text wraps.

Use it for

  • The end of a marketing, docs or help page

Not for

  • App screens: put links in the sidebar or a menu
  • The bottom of a dialog or panel: give it an actions row

A help center's footer with everything centered: its name, three columns of links and the small print.

Columns of links with nothing else: a help center's foot.

A shop's footer as one row: its links, with the small print at the end of the row.

The end of a landing page: a brand column with a newsletter signup, two columns of links and the small print.

Decks for every meeting

Written in an afternoon, ready for any screen.

The brand takes 4 of 12 columns and each column of links 2. Under 1024px of footer the brand takes a row; the columns go four to a row, then two.

layout centered sets the brand over the columns over the small print, each on the footer's middle, the columns wrapping onto more rows as it narrows.

layout simple makes one row of links, each column's heading kept for screen readers only, with the small print at its end; under 640px of footer the small print goes under the links.

Footer

PropTypeDefaultDescription
brandReactNodeThe first column: a mark and a line about the product. In a simple footer, keep it to a mark or a name.
legalReactNodeThe last row, under a divider: small print, such as a copyright and legal links.
layout"columns" | "centered" | "simple""columns"How it arranges itself: "columns" (the default), the brand and columns of links on the page grid with the small print under a divider; "centered", the brand over the columns over the small print, each centered; or "simple", one row of links, each column's heading kept for screen readers only, with the small print at its end, the two stacking under 640px.

It also takes ComponentPropsWithRef<"footer">.

Footer.Column

PropTypeDefaultDescription
title

required

ReactNodeThe column's heading, which also names its list of links.

It also takes Omit<ComponentPropsWithRef<"div">, "title">.

Footer.Link

It also takes ComponentPropsWithRef<"a">.

It's the page's contentinfo landmark. Each column is a list of links named by its heading, an h2, which a simple footer keeps for screen readers only; links are at least 24px tall.

It takes no keyboard input of its own.

It doesn't move.

With reduced motion: Nothing changes.

It takes its container's width and sets its content on the page container, 1200px at most, in a grid of 4, 8 or 12 columns by its own width: the brand takes 4 of 12 columns, or a row of its own under 1024px, and each column of links takes 2. The small print sits under a 1px divider 48px below the grid; links wrap rather than truncate, and each is at least 24px tall. With layout centered the brand, the columns and the small print share the footer's middle, the columns 64px apart (40 under 640px) and wrapping onto more rows; with layout simple it's one row of links 24px apart, with the small print at its end and no divider, padded 32 above and below, and the two stack under 640px.

See it in the Halfmoon shop demo.

  • Page grid and containers

    The page grid, the content column, sections and centered content, for marketing and content pages.

  • NavBar

    The bar across the top of a page: the brand, menus that open in one morphing panel, and the calls to action, static, sticky or auto-hiding.