Button

● Stable · v0.1

The single, unmistakable action on a screen. A first-time shop owner should be able to glance at a screen and know the one thing to tap next — the primary Button is how we make that obvious.

In context

9:41

Try the variants

Variant
Size
Full width
Loading
Disabled
import { Button } from '@daytwo/components'
<Button
fullWidth
onPress={recordSale}
>
Record sale
</Button>

Purpose

Button triggers an action. Its job on a DayTwo screen is to make the next step obvious for someone who may not understand the product yet and has no one beside them to ask. Emphasis is a deliberate signal: the high-emphasis primary variant means "this is the thing to do here," and there should be only one of those per screen.

Anatomy

A Button is a single tappable surface containing a centered label, with optional leading/trailing icons. It has no separate "container + text" split to get wrong — that is intentional, so it always meets the touch target and always reads as one thing.

  • Tap surface — the whole control is tappable; height is never below the 48dp minimum.
  • Label — a concrete verb phrase ("Record sale"), not "OK" or "Submit".
  • Optional icon — paired with a label, never icon-only for a primary action.
  • State — default, pressed, disabled, loading.

Variants

Four variants, ordered by emphasis. Emphasis communicates importance — use the highest emphasis for the screen's main action and step down from there.

  • Primary — the one main action. Teal brand fill, white label (passes contrast in a bright market stall).
  • Secondary — a supporting action that's still important. Tinted fill, brand-colored label.
  • Tertiary — low-emphasis or dismissive ("Not now"). No fill, so it never competes with primary.
  • Destructive — irreversible or data-losing actions. Red, and always paired with a confirmation step.

Sizes

Every size meets the 48dp minimum touch target — sm is smaller in padding and type, never in tappability.

Code

import { Button } from '@daytwo/components'
// The primary action on a capture screen
<Button fullWidth onPress={recordSale}>
Record sale
</Button>

When to use

  • The screen has one clear action the user is meant to take — make it primary, fullWidth.
  • A supporting action sits alongside the main one (e.g. "See advice") — make it secondary.
  • You need a quiet, low-stakes way out ("Not now", "Skip") — make it tertiary.

When NOT to use

  • For navigation between screens or tabs. That's a link or a tab, not a Button — a Button implies "something happens here," and mislabeling erodes the trust that an action did what it said.
  • For more than one primary action on a screen. Two primaries means no primary; the user loses the one obvious next step.
  • As an icon-only control for an important action. Low-literacy and first-time users rely on the word. Pair the icon with a label.
  • To toggle a setting. Use a switch — a Button doesn't communicate on/off state.

The correct scenario

A first-time shop owner finishes entering a cash sale. The screen shows one primary, full-width Button — Record sale — and a quiet tertiary Cancel. There is exactly one obvious thing to do, it's large enough to hit without aiming, and the word says precisely what will happen.

Anti-patterns

Do
One primary action, full-width, with a quiet tertiary escape. The next step is unmistakable.
Don't
Two primary buttons compete for attention, so the user has to stop and decide which one is 'the' action. Now there is no primary.
The rule, and why

One primary button per screen. A first-time user scans for the brightest, biggest thing and taps it — so there must be exactly one. Two equal buttons force a decision the user isn't equipped to make, which is where hesitation and drop-off start.

Edge cases

Loading
Shows a spinner, blocks repeat taps, keeps its size
WhyPrevents double-submitting a sale on a slow connection
Disabled
Dims to 40%, ignores taps
WhyCommunicates "not yet" without removing the action from view
Long Burmese label
Label truncates to one line; container height holds
WhyBurmese runs ~1.3–1.7× longer — layout must not break
Offline
Button still presses; the action handles the queue/retry
WhyThe user should never feel blocked by connectivity
Small / low-end screen
fullWidth keeps the target large and easy to hit
WhyOne-handed use in a busy market

Tokens used

Button reads only from semantic tokens — change a token and every Button updates in the app and on this page at once.

color.brand.primarycolor.brand.onPrimarycolor.brand.tintcolor.feedback.errorSolidcolor.text.brandradius.pilltouchTargets.mintypography.fontFamily.sanstypography.fontWeight.semibold