Componentsv2.189.1
Iconsv1.19.0
MCPv0.8.62
Tokensv0.34.3

Buttons are interactive elements that allow the user to perform an action on the page or serve as a prominent hyperlink.

Button

Usage

  • Use Buttons to perform actions on the current page (open a modal, submit a form). Buttons and hyperlinks are not functionally interchangeable.
  • Use links/anchors for navigation, downloads, or external URLs.
  • Provide href to render a Button as a hyperlink — prefer this for CTAs or prominent standalone links.
  • Limit one Primary Button per page or workflow.
  • Order actions by importance from right (most important) to left (least important).
  • Never use Button variants or danger state purely to fit a color theme.

Types

  • Regular — includes a label and optionally an icon. The default type.
  • Icon-only (isIconOnly) — renders only the icon with reduced padding. Use in condensed layouts or for menus and dropdowns. Requires icon or iconSrc.
  • Link (href) — renders as an anchor element. Use for calls-to-action that navigate.

Variants

  • variant="primary" — the most important action on the page, including CTAs and form submission. Limit to one per page.
  • variant="secondary" — lesser important actions. Multiple allowed per page.
  • variant="subtle" — the least important action (referred to as "Tertiary" in design language).

Appearance

  • size="md" — default size for most use cases.
  • size="sm" — for smaller screens or less prominent actions.
  • icon — renders a Pluma icon by name. Leading position by default.
  • iconPosition="trailing" — places the icon after the label.
  • iconSrc — renders a custom image icon by URL. Sizing matches Pluma icons. Be aware of how the custom icon's color and style interact with each variant's background.

Behaviors

  • Loading (isLoading) — displays a spinner overlay and blocks interaction.
  • Auto-loading (autoLoading, default true) — automatically shows a spinner when onClick returns a promise.
  • Disabled (isDisabled) — prevents interaction and applies lighter colors across all variants.
  • Danger (isDanger) — applies critical color treatment for destructive actions. Works with all variants.
  • Active (isActive) — applies the hover/active visual state programmatically.

Content

  • Start with an action verb. Keep labels to 1–3 words.
  • Use sentence case. Never add a period.
  • Prefer specific labels (e.g., "Send campaign" over "Submit"), but generic labels are acceptable when the context makes the action clear.
  • Be consistent in verbiage across the application.
  • Add an ellipsis () when the action opens a dialog or requires additional input before completing. Never add an ellipsis for immediate actions.
  • Use the present participle with an ellipsis for loading-state labels (e.g., "Saving…").
  • Use "Delete + object" for destructive actions and "Permanently delete + object" for irreversible ones.
  • Use "Upload" or "Upload + object" for file upload actions.
  • Use common user questions as labels for AI agent interaction Buttons.

Implementation Notes

  • Tertiary naming mismatch — design docs refer to "Tertiary" but the prop value is variant="subtle". The literal value "tertiary" also exists as a separate variant with different styling. Use variant="subtle" for the Tertiary design intent.
  • unsafe_withSoftDeprecatedSecondaryVariant — when true, the secondary variant renders with tertiary styling. Used during the layout refresh transition. Can also be set globally via PlumaProvider component config.
  • unsafe_withMigratedButtonVariants — when true, shifts all variants down one level (secondarytertiary styling, tertiarysubtle styling). Intended for use after running the button-variant-rename codemod (pnx @customerio/pluma-cli upgrade --codemod button-variant-rename). Supersedes unsafe_withSoftDeprecatedSecondaryVariant.
  • isError is deprecated — use isDanger instead.
  • unsafe_isActive is deprecated — use isActive instead.
  • size="medium" and size="small" are deprecated — use "md" and "sm".
  • Content — React uses children for the label text. Ember uses {{yield}} (default block) via <PlumaButton>Label</PlumaButton>.
  • Button renders as <button type="button"> by default. When href is provided, it renders as a PlainLink anchor element instead.

On this page