All components
Actions
Button
stable
Since 1.1
Action control with four emphasis variants, three semantic tones, five sizes, icon slots, loading, and navigational semantics.
Actions
primitive
Interactive
Needs State Matrix
import { Button } from '@ivim/native/components';
When to use
Use when
Someone needs to trigger an action or submit a form.
You want to signal the single most important action on a surface — use one primary button per view.
Don't use when
The control is icon-only — use IconButton, which requires an accessible name by construction.
The control navigates somewhere and should look like body text — use a link variant, or set role="link".
Playground
Adjust the controls to preview live prop combinations. The code snippet updates to match the current selection.
variant
variant
primary
secondary
tertiary
link
tone
tone
brand
gray
destructive
glass
size
size
xs
sm
md
lg
xl
Loading
isLoading
Disabled
isDisabled
Full width
fullWidth
Label
children
<Button>Continue</Button>
Example
Preview
Code
Variants
Primary
Secondary
Tertiary
Link
Tones
Gray, all variants
Destructive primary
Destructive secondary
Destructive tertiary
Destructive link
Sizes
Extra small
Small
Medium
Large
Extra large
States and slots
Leading icon
Trailing icon
Loading (label overlaid, width preserved)
Loading (label retained)
Disabled
Navigational (announces as a link)
View invoice
Full width
Anatomy
The parts that compose this component.
1
Container
Pressable surface carrying the variant fill, tone, radius, and padding.
2
Leading icon
Optional element before the label. Replaced by the spinner while loading, so the two never appear together.
3
Label
Required children — the action text.
4
Trailing icon
Optional element after the label.
5
Spinner
Overlays the hidden label by default, preserving the button width; sits beside it with showTextWhileLoading.
Guidelines
Do
Use one primary button per surface, with secondary or tertiary buttons for lower-emphasis actions beside it.
Do
Set tone="destructive" for irreversible actions rather than reaching for a red color token.
Do
Use isLoading for in-flight actions — it blocks a second submit and keeps the button accessibly named.
Don't
Stack multiple primary buttons together; it removes the hierarchy that tells people what to do first.
Don't
Write vague labels like "OK" or "Submit" when a specific outcome word would be clearer.
Props
Public props for this component. Required props are marked; defaults reflect the component implementation.
variant
'primary' | 'secondary' | 'tertiary' | 'link'
default: 'primary'
Emphasis hierarchy. Primary fills, secondary outlines, tertiary and link are chrome-less.
tone
'brand' | 'gray' | 'destructive'
default: 'brand'
Semantic intent. Every variant has a destructive form; this replaces the removed raw color prop.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
default: 'md'
Controls min height, padding, and label type scale.
iconLeading
ReactNode
Element before the label. Hidden while loading.
iconTrailing
ReactNode
Element after the label.
isLoading
boolean
default: false
Shows a spinner, reports busy, and blocks activation to prevent duplicate submits.
showTextWhileLoading
boolean
default: false
Keeps the label beside the spinner instead of overlaying it. The default preserves button width.
loadingAccessibilityLabel
string
Announced instead of the label while loading.
isDisabled
boolean
default: false
Dims the button, blocks activation, and announces disabled.
fullWidth
boolean
default: false
Stretches the button to fill its container.
role
'button' | 'link'
default: 'button'
Set to link for navigational actions so assistive tech describes the outcome correctly.
children
required
ReactNode
Button label content.
Deviations from Untitled UI
Where this component deliberately differs from Untitled UI's API, and why. These are kept choices, not gaps to close.
Untitled UI
`color` single axis, 9 values (`"secondary-destructive"`, …)
Ours
`variant` (4) × `tone` (3)
The 9-value union is a partial flattening of a 4×3 grid. Two orthogonal axes are more regular, express combinations UUI omits, and keep `destructive` a tone rather than a suffix. Mapping: `primary` → `variant="primary" tone="brand"`; `secondary` → `variant="secondary" tone="gray"`; `tertiary` → `variant="tertiary" tone="gray"`; `link-color` → `variant="link" tone="brand"`; `link-gray` → `variant="link" tone="gray"`; any `*-destructive` → the same `variant` with `tone="destructive"`.
Untitled UI
Icon-only via the same Button
Ours
a separate `IconButton` with a required `label`
Icon-only buttons need an accessible name; a required prop on a dedicated component makes that unforgettable.
Untitled UI
default `size="sm"`
Ours
default `size="md"`
UUI defaults to desktop density; mobile requires a 44pt touch-target floor. Grammar rule G12.
Accessibility
Roles and screen-reader behavior this component provides, plus keyboard interactions.
•
Sets accessibilityRole="button", or "link" when role="link" marks a navigational action.
•
Derives the accessible name from a string label; pass accessibilityLabel when children are not plain text.
•
Keeps its accessible name while loading hides the visible label, and loadingAccessibilityLabel can replace it ("Saving changes").
•
Loading reports busy and blocks activation, so a second submit is impossible rather than merely discouraged.
•
Sizes below the 44px touch target (xs, sm) extend their press area with hitSlop rather than shrinking the target.
Tab
Moves focus to the button.
Space / Enter
Activates the button.
Platform & RTL
Behavior that differs across the platforms this component runs on.
Web
Focusable with a visible inset focus ring; activates on Space/Enter.
iOS
Press scale and opacity feedback from PressableFeedback.
Android
Adds a ripple tuned to the border-muted token.
RTL
Leading and trailing icons mirror automatically under RTL layouts.
State coverage
Interaction and visual states this component supports.
default
pressed
disabled
active
Token references
Semantic design tokens this component page exercises. Tap one to edit it live.
Related components
Components that solve adjacent problems or compose with this one.
Utility buttons
Icon-only actions and dismiss controls: IconButton with variant, tone, size, and loading, plus regular and inverse CloseButton.
ButtonGroup
Joined group of adjacent segments: an action group, or a single- or multiple-selection control with group and per-item disabled states.
LinkButton
Pressable text link.
Utility buttons
Icon-only actions and dismiss controls: IconButton with variant, tone, size, and loading, plus regular and inverse CloseButton.