Skip to content
SproutAceve · v3.33.1
Overview What is your role? Connect to Sprout MCP reference Adopting Sprout
Brand & logos Color Typography Spacing & layout Elevation Iconography Accessibility
Overview Alert Avatar Badge Breadcrumb Buttons Cards Checkbox Data grid Dialog Dropdown button Fab button Floating tabs Inputs Menu Navigation Numeric input Progress bar Progress ring Radio button Ribbon toolbar Switch Tabs Tag Tooltip
Interaction & motion Voice & content Product patterns
AI patterns AI transparency & disclosure AI disclosure label AI labels in marketing
Design principles Personas Trust and ethics Meet the makers
Build the systemplay Tower of tokensplay Site runnerplay
How it works Changelogv3.33 Roadmap Contribute
Components

Button.

One action, one label, one place to press. Always an imperative verb plus a noun, never the verb alone. Type carries the meaning, style carries the weight, size carries the context — the three axes are independent, and every combination is a real button.

Try it

Type
Style
Size
State

Type

Four semantic tokens. Style and size below change how much weight each one carries, not what it means.

TypeWhen to useToken
primaryThe one action you want people to take on this view. One per view.containers/primary
neutralCancel, back, secondary paths. Pair it with a Primary, never with another Neutral Filled.containers/neutral
successConfirm, approve, complete. Reserve it for the positive final step.containers/success
dangerDelete, remove, reset. Always pair with a confirmation and a plain-language warning.containers/danger

secondary and destructive still work as aliases for neutral and danger — nothing built against the old API breaks. subtle still works too, and now forces appearance="text".

Options

Type carries the meaning, size carries the context, state carries the feedback. Exact values live in Specification below.

Style

Filled is a decision. Outlined and Text are lighter ways to say the same type when a Filled button would out-shout everything near it.

filledoutlinedtext
Primary
Neutral
Success
Danger

One Filled per view, always. A screen with three Filled buttons has no primary action — it has three. Outlined pairs with a Filled sibling; Text stands alone in toolbars and dense rows where a border would add noise.

Size

Heights come from input/height — a Button always lines up with the field or row next to it.

Small 28px
Medium 38px
Large 48px

States

Default → Hover → Pressed → Disabled ship today. Focus is specified below but is not a variant — it is what :focus-visible always draws.

Default
Hover
Pressed
Disabled
Focused not a variant

Icons

Placement and meaning.

Do — leading icon repeats the verb. Plus means add, the arrow means download. Icon and label say the same thing.
Don't — decorative icon. Stars say nothing about saving. A glyph that does not name the action is noise.
Do — trailing icon means direction. A chevron says a menu opens below. An arrow says the flow continues.
Don't — trailing icon on a destructive action. The arrow makes Delete look like navigation. Use a leading trash icon or none.
Do — one icon per meaning. Trash means delete everywhere in Aceve. Never reuse it for archive, clear or reset.
Don't — two icons around one label. Both sides pull the eye and the button stops reading as one action.
Icon button · aria-label "Delete order"
Do — icon only is a different component. Icon button ships the aria-label and the tooltip that Button does not.
no accessible name, no tooltip
Don't — a Button with the label removed. Screen readers announce nothing and keyboard users land on an unnamed target.

Specification

Every value is a token. If a value is not in this table, it does not exist.

PropertySmallMediumLargeToken
Height283848input/height/*
Corner radius888border-radius/large
Horizontal padding, Filled121620—
Horizontal padding, Outlined / Text81212—
LabelManrope Bold 12Manrope Bold 14Manrope Bold 16_type-midlayer
Icon size161616—
Icon to label gap81212space-xs · space-s
Border, Outlined111—
Resting shadownonenonenonestatic-shadow/surface available
Guidelines

Anatomy, icon placement, do and don't rules with live examples, and the accessibility notes above. Everything about using the button well lives on this page.

Read the guidelines →

Accessibility

KeyboardA real <button>, so Enter and Space both activate it and Tab reaches it in document order — nothing to wire by hand.
DisabledRemoved from the tab order and from the accessibility tree's actionable elements. Never disable a button to explain a missing precondition — say the precondition instead, next to the button.
Focus visibleThe 2px accent ring in States above is the browser default left alone. Do not suppress :focus-visible to "clean up" the design.
Toggle buttonsPass pressed to add aria-pressed. A toggle needs a label that reads correctly in both states, e.g. "Mute" / "Unmute", not a single ambiguous "Toggle".
Icon-onlyNot this component. Use Icon button, which ships the required aria-label and a tooltip — see the Icons do/don't above.
ColourDanger and Success repeat their meaning in the label ("Delete row", "Confirm payment"), so colour is reinforcement, never the only signal.

Props (React)

type ButtonProps = {
  variant?: "primary" | "neutral" | "success" | "danger";
  // legacy aliases still accepted: "secondary" → neutral, "destructive" → danger,
  // "subtle" → neutral text (forces appearance="text")
  appearance?: "filled" | "outlined" | "text";  // default "filled"
  size?: "s" | "m" | "l";                       // default "m" — 28 / 38 / 48px
  icon?: IconName;              // optional icon, 16px
  trailing?: boolean;           // render icon after the label instead of before
  disabled?: boolean;
  pressed?: boolean;            // toggle state — adds aria-pressed
  children: ReactNode;          // verb + noun, please
  onClick?: (e) => void;
};
← PreviousBreadcrumbNext →Cards
Sprout · Aceve Design System · v3.33.1
Figma library GitLabReleases