Buttons

button

#existingsource

A single clickable action. Use Primary for the page's main action. Use Ghost or Link for low-emphasis affordances. Use Danger only for destructive operations. If you need two actions side-by-side that should feel like peers, use the same variant on both.

Readiness
complete
Preview
live
Props
6
Examples
4
Code
implementation mapped

When to use

  • Page's main action — Primary variant
  • Form submit affordance — Primary or Confirm
  • Destructive operation (delete, cancel-with-loss) — Danger variant
  • Low-emphasis secondary action — Ghost or Secondary
  • Inline text-link styled action — Link variant

When not to use

  • Navigation between routes — use a Link/anchor instead (semantic <a>)
  • Toggling a state visible to the user — use Switch or Checkbox
  • Selecting one of N exclusive options — use SegmentedControl or RadioGroup
  • Compact decorative chip without action — use Badge

Accessibility

Role: button

  • Enter — Activates the button
  • Space — Activates the button (when focused)
  • Tab — Moves focus to/from the button

Screen reader: Reads label content + any aria-label/title. Sets `aria-busy=true` while `loading`. `disabled` removes from focus order entirely.

Notes: `variant: icon` REQUIRES the `title` prop — without it, screen-reader users have no label. The codegen audit fails the build if any `<Button variant=icon>` lacks a title.

Props

NameTypeDefaultDescription
variantenum: primary | vibrant | secondary | ghost | link | danger | warning | confirm | icon | itemprimaryRole + visual weight.
sizeenum: small | medium | largemediumPadding scale. `icon` and `item` variants ignore this (their padding is intrinsic to the variant).
loadingbooleanfalseRenders a spinner inside the button and sets `aria-busy=true`. The click handler is suppressed automatically while loading.
disabledbooleanfalseDisables the button and removes hover/focus affordances.
titlestringTooltip text. Required for `variant: icon` so screen readers and keyboard users have a label.
typeenum: button | submit | resetbuttonNative form button type. Use `submit` inside a form-field group when the button advances the form.

Examples

Symmetric login CTAs

Symmetric login-page CTAs (the bug we're fixing).

YAML
type: stack
props:
  gap: md
  direction: row
children:
- type: button
  props:
    variant: primary
  slots:
    default: Sign in
- type: button
  props:
    variant: primary
  slots:
    default: Create account
Dev-mode action

Dev-mode button (drops the inline orange rgba in DevLoginSection).

YAML
type: button
props:
  variant: warning
  size: small
slots:
  default: Dev login
Loading submit

Submit button with loading state.

YAML
type: button
props:
  variant: primary
  type: submit
  loading: ${state.is_submitting}
slots:
  default: Sign in
Variants gallery

All eight non-icon variants for visual comparison.

YAML
type: stack
props:
  gap: sm
  direction: row
children:
- type: button
  props:
    variant: primary
  slots:
    default: Primary
- type: button
  props:
    variant: vibrant
  slots:
    default: Vibrant
- type: button
  props:
    variant: secondary
  slots:
    default: Secondary
- type: button
  props:
    variant: ghost
  slots:
    default: Ghost
- type: button
  props:
    variant: link
  slots:
    default: Link
- type: button
  props:
    variant: danger
  slots:
    default: Danger
- type: button
  props:
    variant: warning
  slots:
    default: Warning
- type: button
  props:
    variant: confirm
  slots:
    default: Confirm
Edit YAML

button-group

#existingsource

ButtonGroup is the canonical wrapper for related actions. It keeps spacing, alignment, attached clusters, and equal-width footer controls consistent so a toolbar or form footer does not invent its own action rhythm.

Readiness
complete
Preview
live
Props
6
Examples
2
Code
implementation mapped

When to use

  • Related actions in a form footer, panel header, or toolbar
  • Peer actions that must keep equal visual weight
  • Attached button clusters where the group reads as one control
  • Mobile stacks where the same actions should become vertical

When not to use

  • Exclusive selection between options; use SegmentedControl or RadioGroup
  • Navigation lists; use anchors, tabs, or ItemButton depending on behavior
  • One standalone action; use Button directly

Accessibility

Role: group

  • Tab — Moves through each child button in document order

Screen reader: Announces the group label followed by each button label.

Notes: The group should contain real buttons. Do not place unrelated actions in one group.

Props

NameTypeDefaultDescription
directionenum: row | columnrowPrimary layout direction for the group.
gapenum: xs | sm | mdsmSpacing between actions when the group is not attached.
alignenum: start | center | end | stretchstartCross-axis alignment.
equal_widthbooleanfalseMakes child actions share available width.
attachedbooleanfalseRemoves the gap and attaches neighbouring button borders.
aria_labelstringRelated actionsAccessible label for the action group.

Examples

Panel footer

A panel footer with cancel and save actions.

YAML
type: button-group
props:
  gap: sm
  align: center
  aria_label: Panel actions
children:
- type: button
  props:
    variant: ghost
  slots:
    default: Cancel
- type: button
  props:
    variant: primary
  slots:
    default: Save changes
Attached toolbar

Attached toolbar controls for a compact command cluster.

YAML
type: button-group
props:
  attached: true
  aria_label: View controls
children:
- type: button
  props:
    variant: secondary
    size: small
  slots:
    default: List
- type: button
  props:
    variant: secondary
    size: small
  slots:
    default: Graph
- type: button
  props:
    variant: secondary
    size: small
  slots:
    default: Trace
Edit YAML

close-button

#existingsource

CloseButton is the canonical dismiss control. It gives every dialog, drawer, sheet, and floating panel the same target size, icon, hover state, focus ring, and accessible label.

Readiness
complete
Preview
live
Props
5
Examples
2
Code
implementation mapped

When to use

  • Dismissible dialog or modal header
  • Panel, drawer, sheet, or overlay chrome
  • Temporary inline surface that has an explicit close action

When not to use

  • Navigation back to a previous route; use a back link or breadcrumb
  • Cancelling a form with potential data loss; use an explicit Button label
  • Closing a process that keeps running; use Stop or Cancel copy instead

Accessibility

Role: button

  • Enter — Activates the close action
  • Space — Activates the close action
  • Escape — Belongs on the surrounding dismissible surface, not this button

Screen reader: Reads the label prop, defaulting to Close.

Notes: Use a specific label such as 'Close browser panel' when multiple surfaces are present.

Props

NameTypeDefaultDescription
labelstringCloseAccessible label and tooltip.
sizeenum: small | medium | largemediumSquare hit-target size.
placementenum: inline | absolute-top-rightinlineInline flow or top-right anchored placement.
disabledbooleanfalse
on_closestring

Examples

Dialog close

Dialog header close affordance.

Invite teammate
YAML
type: stack
props:
  gap: sm
  direction: row
  align: center
children:
- type: text
  props:
    kind: heading
    value: Invite teammate
- type: close-button
  props:
    label: Close invite dialog
    size: small
Anchored close

Absolute close button inside a positioned preview surface.

Panel content with a canonical dismiss target.
YAML
type: container
props:
  class: showcase-positioned-surface
children:
- type: text
  props:
    kind: muted
    value: Panel content with a canonical dismiss target.
- type: close-button
  props:
    label: Close panel
    placement: absolute-top-right
Edit YAML

copy-button

#existingsource

CopyButton is the standard way to copy tokens, URLs, IDs, commands, and short snippets. It keeps clipboard handling, success state, icon, target size, and accessible status consistent across the platform.

Readiness
complete
Preview
live
Props
6
Examples
2
Code
implementation mapped

When to use

  • Copying API tokens, webhook URLs, invite links, or command snippets
  • Compact code or identifier rows where the copied value is visible nearby
  • Inline tool chrome that needs immediate success feedback

When not to use

  • Long editable text; use a textarea or code block with native selection
  • Downloading files; use a download action
  • Copying destructive commands without surrounding warning copy

Accessibility

Role: button

  • Enter — Copies the value
  • Space — Copies the value

Screen reader: Announces Copy before activation and Copied after activation.

Notes: The copied value must be available in surrounding text or described by context.

Props

NameTypeDefaultDescription
value*stringString copied to the clipboard.
labelstringCopyIdle label and accessible name.
copied_labelstringCopiedLabel and accessible name after activation.
variantenum: icon | buttoniconIcon-only or visible text button.
disabledbooleanfalse
on_copystring

Examples

Token copy

Copy an API token suffix from a settings row.

sk-live-...7f29
YAML
type: stack
props:
  gap: sm
  direction: row
  align: center
children:
- type: text
  props:
    kind: muted
    value: sk-live-...7f29
- type: copy-button
  props:
    value: sk-live-demo-7f29
    label: Copy token
Visible label

Text button variant for command snippets.

YAML
type: copy-button
props:
  variant: button
  value: triform run deployment --target staging
  label: Copy command
  copied_label: Command copied
Edit YAML

floating-action-button

#existingsource

FloatingActionButton is a rare, high-salience action for constrained canvases and mobile surfaces. It should announce one obvious create or add action and must not be the only way to perform that action.

Readiness
complete
Preview
live
Props
6
Examples
2
Code
implementation mapped

When to use

  • Primary create action on a dense canvas or mobile surface
  • A bounded tool surface where a persistent action would otherwise disappear
  • Inline showcase or settings previews using placement: inline

When not to use

  • Desktop page footers where a normal Button is visible
  • Multiple competing actions; use a toolbar or ButtonGroup
  • Navigation, destructive actions, or hidden menus without a fallback path

Accessibility

Role: button

  • Enter — Activates the FAB
  • Space — Activates the FAB

Screen reader: Reads the required label prop.

Notes: Always provide another visible route to the same action in the surrounding UI.

Props

NameTypeDefaultDescription
label*stringAccessible label and tooltip.
iconstringplusIcon key from the Triform icon registry.
placementenum: inline | bottom-right | bottom-centerbottom-rightInline preview or fixed viewport placement.
toneenum: primary | neutral | dangerprimarySemantic visual tone.
disabledbooleanfalse
on_clickstring

Examples

Create action

Inline preview of the canonical create affordance.

YAML
type: floating-action-button
props:
  label: Create element
  icon: plus
  placement: inline
Neutral FAB

Neutral anchored action for a local tool surface.

YAML
type: floating-action-button
props:
  label: Open tools
  icon: tune
  placement: inline
  tone: neutral
Edit YAML

icon-button

#existingsource

An icon-only square button used in toolbars, table-row actions, and close affordances. Differs from `Button variant=icon` only in that the Rust component is exported separately for ergonomics — both flow through the same dispatch. The `title` prop is required so screen readers and keyboard users have a label.

Readiness
complete
Preview
live
Props
3
Examples
2
Code
implementation mapped

When to use

  • Toolbar action where space prohibits a text label
  • Row-level affordance (delete row, edit row, expand row)
  • Close button in dialogs and panels (use CloseButton variant when it lands)
  • Compact navigation (vertical rail items)

When not to use

  • Primary page action — use Button variant=primary so the label is visible
  • Touch-first surfaces where icon-only fails minimum tap-target heuristics — pair with text
  • Destructive action without confirm — pair with ConfirmDialog

Accessibility

Role: button

  • Enter — Activates the button
  • Space — Activates the button
  • Tab — Moves focus to/from the button

Screen reader: Reads the `title` (aria-label fallback). Without a title the audit fails the build — icon glyphs alone are not screen-reader content.

Notes: The audit gate `check-icon-button-has-title` rejects any IconButton that lacks a title prop or aria-label.

Props

NameTypeDefaultDescription
title*stringRequired accessible label — read by screen readers, also rendered as a tooltip on hover.
sizeenum: small | medium | largemedium
disabledbooleanfalse

Examples

Settings icon

Toolbar settings affordance with required title.

YAML
type: icon-button
props:
  title: Settings
slots:
  default:
  - type: icon
    props:
      name: settings
Sizes

All sizes side by side.

YAML
type: stack
props:
  gap: sm
  direction: row
  align: center
children:
- type: icon-button
  props:
    title: S
    size: small
  slots:
    default:
    - type: icon
      props:
        name: settings
- type: icon-button
  props:
    title: M
    size: medium
  slots:
    default:
    - type: icon
      props:
        name: settings
- type: icon-button
  props:
    title: L
    size: large
  slots:
    default:
    - type: icon
      props:
        name: settings
Edit YAML

item-button

#existingsource

ItemButton turns a full-width row into a real button. Use it for picker rows, command lists, and drill-in rows where the whole row activates one action and should feel keyboard-reachable.

Readiness
complete
Preview
live
Props
2
Examples
1
Code
implementation mapped

When to use

  • Selecting an item from a command or picker list
  • Opening details from a full-width row
  • Rows that need hover, focus, disabled, and activation states

When not to use

  • Navigation to a URL; use an anchor or route link
  • Rows with multiple independent actions; use a row layout plus separate buttons
  • Static list content with no activation behavior

Accessibility

Role: button

  • Enter — Activates the row
  • Space — Activates the row
  • Tab — Moves focus to and from the row

Screen reader: Reads the row content as the button label.

Notes: Keep secondary text concise so the button label remains understandable.

Props

NameTypeDefaultDescription
disabledbooleanfalseDisables activation and applies disabled styling.
on_clickstring

Examples

Component family row

A drill-in row for opening a component family.

YAML
type: item-button
slots:
  default:
  - type: stack
    props:
      gap: xs
    children:
    - type: text
      props:
        kind: heading
        value: Selection controls
    - type: text
      props:
        kind: muted
        value: Checkbox, radio, and select patterns
Edit YAML

segmented-control

#existingsource

SegmentedControl is for compact, mutually exclusive mode and filter choices. It looks like a button cluster, behaves like a radiogroup, and should only contain short options that can be scanned quickly.

Readiness
complete
Preview
live
Props
7
Examples
2
Code
implementation mapped

When to use

  • Switching a dense panel between modes such as List, Graph, Trace
  • Filtering a table or board to one of a few known states
  • Choosing a compact display density or inspection mode

When not to use

  • Navigation across pages; use tabs or links
  • Long option labels or explanatory choices; use RadioGroup or RadioCardGroup
  • Independent toggles where more than one option can be active

Accessibility

Role: radiogroup

  • ArrowLeft — Selects the previous enabled segment
  • ArrowRight — Selects the next enabled segment
  • ArrowUp — Selects the previous enabled segment
  • ArrowDown — Selects the next enabled segment
  • Tab — Moves focus to and from the control

Screen reader: Each segment is announced as a radio option with checked state.

Notes: Use a clear aria_label when the visible labels are terse.

Props

NameTypeDefaultDescription
options*arraySegments as { value, label, disabled? } objects.
value*stringCurrently selected value.
sizeenum: small | mediummedium
directionenum: horizontal | verticalhorizontal
aria_labelstringChoose one optionAccessible label for the radiogroup.
disabledbooleanfalse
on_changestring

Examples

Mode switcher

Canvas inspection mode switcher.

YAML
type: segmented-control
props:
  aria_label: Canvas mode
  value: graph
  options:
  - value: list
    label: List
  - value: graph
    label: Graph
  - value: trace
    label: Trace
Compact filter

Small forecast window selector.

YAML
type: segmented-control
props:
  size: small
  aria_label: Forecast window
  value: week
  options:
  - value: day
    label: Day
  - value: week
    label: Week
  - value: month
    label: Month
Edit YAML

split-button

#existingsource

SplitButton presents one default command and a small menu of related variants. It keeps the main path fast while keeping rarer variants discoverable and keyboard reachable.

Readiness
complete
Preview
live
Props
8
Examples
2
Code
implementation mapped

When to use

  • A default action has a few related variants, such as Run plus Dry run
  • Operational commands where the primary path should stay one click away
  • Toolbar actions that need a compact variant picker

When not to use

  • Unrelated menu items; use DropdownMenu or ContextMenu
  • More than five variants; use a menu button with grouped content
  • Actions with equal importance; use ButtonGroup

Accessibility

Role: group

  • Enter — Activates the focused button
  • Space — Activates the focused button
  • ArrowDown — Opens the variant menu
  • Escape — Closes the variant menu

Screen reader: Primary button and menu toggle are separate controls inside one group.

Notes: The primary label must describe the default action, not the whole menu.

Props

NameTypeDefaultDescription
label*stringPrimary action label.
items*arrayMenu items as { value, label, danger?, disabled? } objects.
variantenum: primary | secondary | ghost | danger | warning | confirmprimaryVisual role of the primary action.
sizeenum: small | medium | largemedium
loadingbooleanfalse
disabledbooleanfalse
on_clickstring
on_selectstring

Examples

Run variants

Run action with operational variants.

YAML
type: split-button
props:
  label: Run
  items:
  - value: run-now
    label: Run now
  - value: dry-run
    label: Dry run
  - value: schedule
    label: Schedule run
Deploy variants

Deploy action with a disabled production variant.

YAML
type: split-button
props:
  label: Deploy
  variant: confirm
  items:
  - value: staging
    label: Deploy to staging
  - value: production
    label: Deploy to production
    disabled: true
  - value: rollback
    label: Rollback
    danger: true
Edit YAML