Agent docs

Kit: the Button gallery

The Button gallery, seventeen example cards deep, deliberately including the props no shipping screen has exercised yet.

Page and route#

/components/button, rendered by ButtonGallery in apps/playground/src/app/components/button/gallery.tsx.

What the reader sees#

Seventeen small, focused demonstrations, each one card, each showing one facet of the kit's single button component: real product shapes first (a page-title action row, a card toolbar, table row actions, a form footer, a split-button export), then the raw prop surface (every color, every variant, every size, every named preset, async pending state, icon-only acknowledgement, corner badges, loading and disabled states, shade, and shape).

Layer 1: shell#

The playground's own navigation shell wraps this page like any other component page; there is no page-specific shell layer to describe. Button itself has no shell dependency; every example on this page renders standalone.

Layer 2: composition#

Same shared frame as every gallery page: PageFrame (button/gallery.tsx:35), ShowcaseTitle (:36), then a flat sequence of ExampleCards (:38-177), closing with a SlotMapCard (:179-186). The card order is deliberate, not alphabetical: the first six cards (page-title-actions, card-toolbar, row-actions-cluster, form-footer, export-split-button, link-buttons) are real product shapes lifted from shipping pages, and the remaining eleven are the prop-by-prop reference (colors, sizes, presets, promisify, IconOnClick, dropdown, badges, loading/skeleton/disabled, disabled-across-variants, shade, shapes). A reader skimming top to bottom sees "here is what it looks like in product" before "here is the whole knob set."

Layer 3: primitives#

PrimitiveProps as calledfile:lineContract doc
PageFrame / ShowcaseTitlethe shared page frame and headerbutton/gallery.tsx:35-36shared across every playground page
ExampleCard (×17)title, subtitle, source/sourceTitle from src(name) (:29-32), each wrapping one example component; the second one also passes toolbarbutton/gallery.tsx:38-177apps/playground/src/app/example-card.tsx
Button (inside presets.tsx)ten named presets mapped over one array, with Icon/content overrides only where the preset needs oneapps/playground/src/app/components/button/examples/presets.tsx:3-18packages/ui/docs/button.md
Button (inside shapes-badge-sizing.tsx)circle, dashed, badge/badgeClassNameapps/playground/src/app/components/button/examples/shapes-badge-sizing.tsx:8-12packages/ui/docs/button.md
SlotMapCardthe four ButtonClassNames slot namesbutton/gallery.tsx:179-186apps/playground/src/app/slot-map-card.tsx

Layer 4: patterns#

This page is one layer below the pattern layer, not an instance of a named pattern itself; it demonstrates the primitive the patterns are built from. The pattern pages that consume Button most directly are /patterns/job-title (a Button-driven copy affordance beside a page title), /patterns/bulk-selection-bar (the action bar's own buttons), /patterns/confirm-and-report (the modal footer's buttons, promisify-guarded per button.md:94-97), and /patterns/account-menu (a colorless sign-out button). None of those compositions are re-demonstrated here; this gallery stays at the single-component level throughout.

Layer 5: canon rules in force#

  • packages/ui/docs/button.md's own Banned section (:65-70) names dropdown, promisify, bricked, and IconOnClick as implemented but with zero shipped call sites in either app; this gallery is where a reader actually sees them exercised (export-split-button.tsx, promisify.tsx, bricked-tooltip.tsx, icon-on-click.tsx). Demonstrating a cautioned prop on a component page is the intended use of that caution, not a lapse against it.
  • docs/design-language/02-buttons-and-actions.md §A9, cited through button.md:103-107: an icon-only button still needs a derived accessible name. The circle examples in shapes-badge-sizing.tsx:8-9 both carry an explicit tooltip naming what the demo shows ("circle", "circle lg"), satisfying the derivation chain even though these are documentation buttons with no real onClick.
  • packages/ui/docs/card.md:11, 23: a card-scoped action belongs in toolbar, never a sibling div. The "Card toolbar actions" card (gallery.tsx, second card; examples/card-toolbar.tsx) demonstrates it twice over: the ExampleCard itself carries a Right-arrow link to the Card page in its toolbar, and the example inside renders a plain Card whose toolbar holds a shaded, toned action and an arrowed link.

Lapses#

Fixed 2026-08-17: the gallery now demonstrates a Button inside a Card's own toolbar slot. Until then none of the sixteen ExampleCards passed a toolbar prop, though packages/ui/docs/card.md:11, 23 and button.md's Travels-with section both name that composition as the one place a card-scoped action belongs, and the AppShell gallery (docs/breakdowns/05-kit-shell.md) exercised it while this page did not. The seventeenth card closes that loop; it was a coverage gap in the gallery's self-demonstration, never a defect in Button.

See also#

@versable-git/ui · reference, canon, and method, read in place