Docs
Button

Button

Buttons allow users to take actions and make decisions with a single tap.

When to use

✅ Use when…🚫 Avoid when…

Buttons communicate actions that users can perform. They are typically placed throughout the user interface, in places like:

  • Dialog boxes
  • Modal windows
  • Forms
  • Cards
  • Toolbars
  • For navigation between pages/routes. Use Link — a button communicates "action", a link communicates "go somewhere else".
  • As a decorative label. Use Label or Text.
  • When the content is just a clickable icon. Use IconButton to get the correct touch area and semantics.

Colors

<Button color="primary" text="primary" />
<Button color="secondary" text="secondary" />
<Button color="tertiary" text="tertiary" />
<Button color="success" text="success" />
<Button color="warning" text="warning" />
<Button color="danger" text="danger" />

Neutral (quiet chrome)

color="neutral" paints the button from the engine's quiet palette — a Neutral-ramp interaction palette (rest / hover / pressed stops, AA ink) with no brand hue. Use it for chrome CTAs that must not compete with the page's primary action: a compact "trade" chip in the top bar, a secondary toolbar action. All three variants work; IconButton and Link.Button accept it too.

<Button text="Trade" variant="outlined" size="small" color="neutral" />

The neutral scale (neutral.70…) is still not accepted as a Button color — it has no interaction stops. The palette lives at theme.colors.quiet if you need it elsewhere.

Variants

There are four button variants:

  • Contained (Default)
  • Outlined
  • Text (linked)
  • Ghost — bare chrome control (nothing at rest, a wash on hover; never an underline). Meant for IconButton clusters, available on Button for lockstep.
<Button variant="contained" text="Contained" />
<Button color="secondary" variant="outlined" text="Outlined" />
<Button variant="linked" text="Text" />
<Button variant="ghost" text="Ghost" />

Sizes

Four sizes available:

  • extraSmall
  • small
  • medium (default)
  • large
<Button size="extraSmall" text="extraSmall" />
<Button size="small" text="small" />
<Button size="medium" text="default" />
<Button size="large" text="large" />

Icons

Sometimes you want icons on a given button to improve UX — logos are recognized faster than plain text. See all available icons in Icon.

<Button icon={<Icon icon={trash} />} text="Delete" color="warning" />
<Button icon={<Icon icon={upload} />} text="Upload" />
<Button icon={<Icon icon={shareAlt} />} text="Share" color="primary" variant="linked" />

Interactive Demo

loading

Properties

Prop
Type
Default
Description
color
"primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "neutral"
primary
Semantic color of the button.
containment
string
Containment marker for the `cq` channel: emits `container-type` (+ `container-name` when the string form carries one, e.g. `'inline-size card'`). Apply on the immediate wrapper of the adapting component — NEVER on page-level shells.
fullWidth
boolean
false
Expands the button to fill the container's full width. Useful in forms on mobile and in primary CTAs.
icon
ReactNode
null
Icon displayed next to the text. Accepts any `ReactNode`, but the typical usage is with the `<Icon />` component. @example ```tsx <Button icon={<Icon icon={trash} />} text="Delete" /> ```
iconPosition
"left" | "right"
left
Position of the icon relative to the text.
isLoading
boolean
false
Replaces the content with a spinner while true. The button width is preserved to avoid reflow during the transition. Named `isLoading` (rather than `loading`) because `loading` is a native `<button>` attribute.
legibility
"on-photo"
Reading-shadow preset for text over a photographic background (`on-photo`). Replaces the inline `style={{ textShadow }}` in the consumer (brasil_2030 radar, gap A3). Token emission is deferred until a 2nd consumer asks for the raw var (see backlog).
pageShell
boolean
Centers the element and caps the width at `theme.layout.pageMaxWidth`. The page shell of a classic centered layout.
readable
number | boolean
Makes the `color` legible against the page surface: `true` = WCAG AA (4.5), a number sets a custom floor. Ignored with `contrast`. See the Layout Props concept page for the full semantics.
size
"small" | "medium" | "large" | "extraSmall"
medium
Size of the button.
text
string
Text to display. Alternative to passing content via `children` — when both are provided, `children` takes precedence.
transform
string
CSS `transform` value (e.g. `translate(-50%, -33px)`). Never leaks to the DOM as an attribute.
variant
"contained" | "outlined" | "linked" | "ghost"
contained
Visual variant.

Theming (theme.component.button)

The size scale is a component token: theme.component.button.size.{extraSmall,small,medium,large}, each carrying fontSize / fontWeight / textTransform? / py / px / borderRadius (foundation-scale keys). Override one field of one size without forking the component:

createTheme({
  component: {
    button: {
      size: {
        medium: { px: 'xl' },
      },
    },
  },
});

See also

  • Storybook story: Components / Button
  • Icon-only variant: IconButton