Skip to content
buttery

v1.0.0

Source on GitHub

Version 1.0.0

ConsequenceDialog

A dialog that spells out what saying yes will do before anyone confirms.

import { ConsequenceDialog } from "@butteryui/react";

Demo

When to use it

Use it for

  • Starting a trial, changing a plan or anything that costs money or can't be undone easily
  • Confirming after a PlanComparison card's button

Not for

  • A plain yes or no: use Dialog with Dialog.Actions
  • Asking for values: use FormDialog

Examples

Close a shop

Closing a shop for good, opened from code, the confirm taking a moment while it saves.

Pier Street is open

Plan change

Plan cards that ask first: a card's button spells out what the change will do, and confirming makes it.

Starter

For a roastery selling to its own customers.

$19per month

Includes

  • Online shop
  • Subscriptions

Roaster

For a roastery that also sells to cafés.

$39per month

Everything in Starter, and

  • Wholesale accounts
  • Price lists

On the Starter plan

Start a trial

A trial that starts only once its cost and timing have been read and confirmed.

On Starter

Variants and states

Starting a trial

What the trial costs and when, the small print, then one button.

Props

ConsequenceDialog

PropTypeDefaultDescription
triggerReactNodeThe control that opens it, such as a plan's button. Leave it out to open it from code with open.
openbooleanWhether it's open. Pair with onOpenChange to control it.
defaultOpenbooleanfalseWhether it starts open when uncontrolled. Defaults to false.
onOpenChange((open: boolean) => void)Called when it opens or closes.
title

required

stringWhat's being confirmed, in title-lg, which names the dialog.
items

required

readonly ConsequenceItem[]What saying yes will do, a row each.
termsReactNodeSmall print under a divider, in caption, links welcome.
confirmLabel

required

stringThe confirm button's label, such as "Start the trial".
onConfirm

required

() => void | Promise<void>Called on the confirm button. It closes once this returns, or once the promise it returns resolves, the button showing busy until then; a rejected promise leaves it open.
closeLabelstring"Close"Names the close button. Defaults to "Close".
classNamestringClasses for the dialog's content, the element that carries data-bt="ConsequenceDialog".
styleCSSPropertiesInline styles for the same element.
refRef<HTMLDivElement>The dialog element.

ConsequenceItem

One thing that saying yes will do, a row of a `ConsequenceDialog`.

FieldTypeDefaultDescription
icon

required

ComponentType<IconComponentProps>A 16px icon in a 32px tile at the row's start.
title

required

stringWhat happens, in title-sm, such as "Then $39 a month".
body

required

ReactNodeThe detail, in body-sm.

Accessibility

A modal dialog named by its title. Focus goes to the dialog itself so the consequences are read first; Tab reaches the links in the small print, then the confirm button, which is busy (aria-busy) while a returned promise is pending. Escape or the close button cancels, and focus goes back to what opened it. The rows' icons are decorative.

KeysWhat they do
Tab or Shift+TabMoves from the dialog itself to the links in the small print, the confirm button and the close button, staying inside
Enter or SpacePresses the confirm button, which shows busy while a promise it returned is pending
EscapeCancels and puts focus back on what opened it, unless a confirm is pending

Motion

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

With reduced motion: It and its scrim fade in and out in 100ms, without growing or rising.

Layout

It's 560px wide at most (--bt-w-dialog-md) and 16px inside the window, scrolling inside when it's taller. Its rows sit 20 apart, each a 32px icon tile beside a heading over a line that wraps, the small print sits under a 1px divider, and the confirm button is full width and 48px tall (--bt-h-cta).

See it in the roastery demo's settings.