Skip to main content
Button
@coinbase/cds-web@8.30.1
A pressable button element.
Import
import { Button } from '@coinbase/cds-web/buttons/Button'
SourceView source codeStorybookView StorybookFigmaView Figma (internal only)
Related components
View as Markdown

Buttons allow users to take actions and make choices with a single tap. They communicate what action will occur when the user interacts with them.

Basics

The only required prop is children, which is the button's label. Buttons default to the primary variant.

Loading...
Live Code
<Button onClick={console.log}>Get started</Button>

Variants

Use variants to communicate the importance and intent of an action.

  • Primary — High emphasis for main actions like "Save" or "Confirm". Limit to one per screen.
  • Secondary — Medium emphasis for multiple actions of equal weight.
  • Tertiary — High contrast with inverted background.
  • Negative — Destructive actions that can't be undone. Use sparingly.
Loading...
Live Code
<HStack gap={2} flexWrap="wrap">
  <Button onClick={console.log} variant="primary">
    Primary
  </Button>
  <Button onClick={console.log} variant="secondary">
    Secondary
  </Button>
  <Button onClick={console.log} variant="tertiary">
    Tertiary
  </Button>
  <Button onClick={console.log} variant="negative">
    Negative
  </Button>
</HStack>

Transparent

Use transparent buttons for supplementary actions with lower prominence. The container is only visible on interaction. Works with any variant.

Loading...
Live Code
<HStack gap={2} flexWrap="wrap">
  <Button onClick={console.log} transparent>
    Primary
  </Button>
  <Button onClick={console.log} variant="secondary" transparent>
    Secondary
  </Button>
  <Button onClick={console.log} variant="tertiary" transparent>
    Tertiary
  </Button>
  <Button onClick={console.log} variant="negative" transparent>
    Negative
  </Button>
</HStack>

States

Loading

Use the loading prop to indicate an action is in progress. The button becomes non-interactive and displays a spinner while preserving its width.

Loading...
Live Code
function LoadingExample() {
  const [isLoading, setIsLoading] = useState(false);

  const handleClick = () => {
    setIsLoading(true);
    setTimeout(() => setIsLoading(false), 2000);
  };

  return (
    <HStack gap={2} flexWrap="wrap">
      <Button onClick={handleClick} loading={isLoading}>
        Save changes
      </Button>
      <Button onClick={handleClick} variant="secondary" loading={isLoading}>
        Submit
      </Button>
    </HStack>
  );
}

Disabled

Use the disabled prop to prevent interaction and indicate the action is unavailable.

Loading...
Live Code
<HStack gap={2} flexWrap="wrap">
  <Button disabled onClick={console.log}>
    Primary
  </Button>
  <Button disabled onClick={console.log} variant="secondary">
    Secondary
  </Button>
  <Button disabled onClick={console.log} variant="negative">
    Negative
  </Button>
</HStack>

Sizing

Compact

Use compact for smaller buttons with reduced padding. Useful in dense UIs or alongside other compact elements.

Loading...
Live Code
<HStack gap={2} flexWrap="wrap" alignItems="center">
  <Button onClick={console.log} compact>
    Compact
  </Button>
  <Button onClick={console.log}>Default</Button>
</HStack>

Block

Use block to make the button expand to fill its container width.

Loading...
Live Code
<VStack gap={2}>
  <Button onClick={console.log} block>
    Full width button
  </Button>
  <Button onClick={console.log} variant="secondary" block>
    Another full width
  </Button>
</VStack>

Icons

End Icon

Add an icon after the label to provide additional context or indicate direction.

Loading...
Live Code
<HStack gap={2} flexWrap="wrap">
  <Button onClick={console.log} endIcon="forwardArrow" variant="secondary" compact>
    See more
  </Button>
  <Button onClick={console.log} endIcon="externalLink" variant="secondary" compact>
    Open link
  </Button>
</HStack>

Start Icon

Add an icon before the label to reinforce the action.

Loading...
Live Code
<HStack gap={2} flexWrap="wrap">
  <Button onClick={console.log} startIcon="add" startIconActive variant="secondary" compact>
    Add item
  </Button>
  <Button onClick={console.log} startIcon="download" variant="secondary" compact>
    Download
  </Button>
</HStack>

Full Width with Icons

When using block with icons, the content automatically spreads across the button width.

Loading...
Live Code
<Button onClick={console.log} startIcon="wallet" endIcon="forwardArrow" variant="secondary" block>
  Connect wallet
</Button>

Accessibility

Buttons automatically use their children as the accessible label. For buttons with only icons or ambiguous labels, provide an accessibilityLabel.

<Button onClick={handleClose} accessibilityLabel="Close dialog">
×
</Button>

Composed Examples

Confirmation Dialog

A common pattern using primary and secondary buttons together.

Loading...
Live Code
<HStack gap={2} flexWrap="wrap" justifyContent="flex-end">
  <Button onClick={console.log} variant="secondary" transparent>
    Cancel
  </Button>
  <Button onClick={console.log}>Confirm</Button>
</HStack>

Destructive Confirmation

Use negative buttons with a secondary cancel option for destructive actions.

Loading...
Live Code
<HStack gap={2} flexWrap="wrap" justifyContent="flex-end">
  <Button onClick={console.log} variant="secondary" transparent>
    Cancel
  </Button>
  <Button onClick={console.log} variant="negative">
    Delete
  </Button>
</HStack>

Form Actions

A full-width primary action with a compact secondary option.

Loading...
Live Code
<VStack gap={2}>
  <Button onClick={console.log} block>
    Create account
  </Button>
  <Button onClick={console.log} variant="secondary" transparent block>
    Already have an account? Sign in
  </Button>
</VStack>

Is this page useful?

Coinbase Design is an open-source, adaptable system of guidelines, components, and tools that aid the best practices of user interface design for crypto products.