Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

Detail page

A page about one thing, with its main column and an aside holding its one primary action.

A detail page is about one thing, such as a customer or a price list: its title over a hairline, the main column, and an aside with the one primary action and lists of links. Use DetailPage for any page that shows and acts on a single record.

The parts

  • The title

    title over a hairline, with optional breadcrumbs, a badge and a one-line description, laid out by a PageHeader.

  • The main column

    The page's children: the record itself, such as the coffees and prices on a price list.

  • The aside

    The one primary action, full width at its top, then lists of links: DetailPage.Links in aside.

The aside sits beside the main column from 1100px of the page's column and drops below it under that, so the primary action is never more than a scroll away.

A price list for cafés, with its one action and a list of resources:

src/pages/PriceList.tsx

import type { ReactElement } from "react";
import { Text } from "@butteryui/core";
import { Button, DetailPage } from "@butteryui/react";

export function PriceList(): ReactElement {
  return (
    <DetailPage
      title="Café price list"
      description="Wholesale, by the 5 kg bag"
      action={<Button variant="primary">Send to cafés</Button>}
      aside={
        <DetailPage.Links
          title="Resources"
          links={[{ label: "How prices are set", href: "/help/prices" }]}
        />
      }
    >
      <Text variant="body">Twelve coffees, from 42 to 58 dollars a bag.</Text>
    </DetailPage>
  );
}

DetailPage

When to use it

Use it for

  • One plan, price list, product or integration, with its main facts and one thing to do about it
  • A page reached from a list or a catalog, under breadcrumbs

Not for

  • A record with tabs of related lists, such as a customer: use AppPage with an aside
  • A page of settings: use SettingsPage

Examples

Green coffee lot

A green coffee lot: what's left in the main column, reordering it the aside's primary action.

Nyeri AA

Washed, from the Gatomboya cooperative

180 kg on hand

About nine days of roasting at this week's pace.

Plan detail

One plan's page: its price in the main column, choosing it the aside's one primary action.

Roaster plan

Billed monthly

$39 a month

For a roastery selling to cafés as well as its own customers.

Variants and states

A price list

The aside sits beside the main column from 1100px of column, and under it below that.

Café price list

Wholesale, by the 5 kg bag

$18.40 a kilo

Nyeri AA and Huila, roasted to order and shipped on Tuesdays.

Props

DetailPage

PropTypeDefaultDescription
title

required

stringWhat the page is about, its h1.
breadcrumbsReactNodeThe trail of pages above it, a Breadcrumbs.
badgeReactNodeA ScopeBadge after the title.
descriptionReactNodeOne line under the title, such as how it's billed.
actionsReactNodeActions at the end of the title's row: PageHeader.Actions. Most detail pages put their action in the aside.
actionReactNodeThe aside's one primary action, full width at its top, such as a Button variant="primary".
asideReactNodeThe aside's lists: DetailPage.Links.
asideLabelstring"Details"Names the aside's landmark. Defaults to "Details".
fillbooleanfalseGives the page's last block the rest of the height, so a table scrolls inside it with its header sticky while the header and filters stay put; the table's pagination then keeps floating lanes above it. Defaults to false.
footerReactNodeA small footer that ends the page under a hairline, such as a feedback link and the keyboard shortcuts, in body-sm and text-secondary.

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

DetailPage.Links

PropTypeDefaultDescription
title

required

stringThe list's heading, an h2 in title-sm, over a hairline.
links

required

readonly DetailPageLink[]Its links, in the body-sm size and primary.
onNavigate((href: string, event: MouseEvent<HTMLAnchorElement>) => void)Runs as a link is followed, where a router can take over. A click that opens the page elsewhere, in a new tab or window, is left to the browser.

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

DetailPageLink

One link in a `DetailPage.Links` list.

FieldTypeDefaultDescription
label

required

stringWhat it says.
href

required

stringWhere it goes.

Accessibility

The page's main landmark, its title the h1. The aside is a complementary landmark named by asideLabel; each list of links is a region named by its h2. Each link's target is at least 24px tall.

KeysWhat they do
EnterFollows the focused link in the aside's lists

Motion

It doesn't move.

With reduced motion: Nothing changes.

Layout

It's an AppPage, at most 1280px wide (--bt-w-app-page), its header over a hairline. From 1100px of column the 320px aside (--bt-w-aside) sits beside the main column, 32 apart, and under it otherwise; the aside's primary action is full width, its lists sit 24 apart, and each link is at least 24px tall.

  • Page header

    The top of an app page, with its title, an optional value and the page's actions.

  • DataTable

    A table of records: columns with minimum widths and shares, selection, sorting, row actions, a sticky header and first column, skeleton rows and pagination.