Dyme

Button Components

Explore all button variants, sizes, and states from the design system.

API Reference

ButtonProps

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  // Variant style
  variant?:
    | 'default'    // Gray background, white text
    | 'cta'        // Primary blue, white text
    | 'secondary'  // Secondary color, white text
    | 'success'    // Green background, black text
    | 'warning'    // Orange background, dark text
    | 'premium'    // Juicy orange, black text
    | 'error'      // Red background, white text
    | 'outline'    // Transparent with border
    | 'header'     // Transparent, blue text

  // Size
  size?:
    | 'default'    // 48px height (h-12)
    | 'small'      // 32px height (h-8)

  // Icon
  icon?: React.ReactNode          // Icon element (e.g., from lucide-react)
  iconPosition?: 'left' | 'right' // Icon position (default: 'left')

  // State
  loading?: boolean               // Shows spinner when true
  disabled?: boolean              // Disables button interaction

  // Standard HTML button props
  onClick?: (e: React.MouseEvent) => void
  type?: 'button' | 'submit' | 'reset'
  className?: string
  children?: React.ReactNode
  // ... all other HTML button attributes
}

Available Variants

VariantUse CaseColorsPreview
defaultStandard actionsGray 900 bg, white text
ctaPrimary call-to-actionPrimary 500 bg, white text
secondarySecondary actionsSecondary 500 bg, white text
successConfirmations, positive actionsSuccess 400 bg, black text
warningWarnings, caution actionsWarning 500 bg, gray 900 text
premiumPremium features, upgradesJuicy orange 500 bg, black text
errorDestructive actions, deleteError 500 bg, white text
outlineSecondary, cancel actionsTransparent bg, gray 900 border
headerNavigation, header actionsTransparent bg, primary 500 text

Available Sizes

SizeHeightPaddingFont SizeIcon Size
default48px (h-12)20px horizontal, 12px vertical16px (text-base)24px (h-6 w-6)
small32px (h-8)12px horizontal, 8px vertical12px (text-xs)16px (h-4 w-4)

Props Details

PropTypeDefaultDescription
variantstring'default'Visual style of the button
size'default' | 'small''default'Size of the button (48px or 32px height)
iconReactNodeundefinedIcon to display (usually from lucide-react)
iconPosition'left' | 'right''left'Position of the icon relative to text
loadingbooleanfalseShows spinner and disables interaction
disabledbooleanfalseDisables button (opacity: 0.75)
onClickfunctionundefinedClick handler callback
type'button' | 'submit' | 'reset''button'HTML button type attribute
classNamestringundefinedAdditional CSS classes
childrenReactNodeundefinedButton label/content

Important Notes

  • Button inherits all standard HTML button attributes
  • When loading=true, the button is automatically disabled
  • Disabled buttons have 75% opacity and pointer-events disabled
  • Icons are automatically sized based on button size (24px for default, 16px for small)
  • Focus ring is automatically added for keyboard navigation accessibility
  • All variants have hover states with darker color variants

Variant Overview

default

cta

secondary

success

warning

premium

error

outline

header

import { Button } from '@/components/ui/button'

// All available variants
<Button variant="default">Default</Button>
<Button variant="cta">CTA</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="success">Success</Button>
<Button variant="warning">Warning</Button>
<Button variant="premium">Premium</Button>
<Button variant="error">Error</Button>
<Button variant="outline">Outline</Button>
<Button variant="header">Header</Button>

Button States

VariantDefaultWith IconDisabledLoading
Default
CTA
Secondary
Success
Warning
Premium
Error
Outline
Header
import { Button } from '@/components/ui/button'
import { Settings } from 'lucide-react'

// Default state
<Button variant="cta">Label</Button>

// With icon
<Button icon={<Settings />} variant="cta">Action</Button>

// Disabled state
<Button disabled variant="cta">Label</Button>

// Loading state (shows spinner)
<Button loading variant="cta">Loading</Button>

Size Comparison

Default Size (48px)

Small Size (32px)

import { Button } from '@/components/ui/button'

// Default size (48px height)
<Button variant="cta">Default Button</Button>

// Small size (32px height)
<Button size="small" variant="cta">Small Button</Button>

Common Use Cases

Primary Actions

Secondary Actions

Feedback Actions

Full Width Layout

Icon Positions

import { Button } from '@/components/ui/button'
import { Settings, ChevronRight } from 'lucide-react'

// Icon on the left (default)
<Button icon={<Settings />} variant="cta">
  Left Icon
</Button>

// Icon on the right
<Button icon={<ChevronRight />} iconPosition="right" variant="cta">
  Right Icon
</Button>

Quick Start Guide

Basic Usage

import { Button } from '@/components/ui/button'

function MyComponent() {
  return (
    <div className="flex gap-4">
      <Button variant="cta">Click me</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="outline">Outline</Button>
    </div>
  )
}

With Click Handlers

import { Button } from '@/components/ui/button'

function MyComponent() {
  const handleConfirm = () => {
    // Your logic here
    console.log('Confirmed!')
  }

  return (
    <Button variant="success" onClick={handleConfirm}>
      Confirm
    </Button>
  )
}

Full Width Buttons

import { Button } from '@/components/ui/button'

function MyForm() {
  return (
    <div className="max-w-md space-y-3">
      <Button className="w-full" variant="cta">
        Continue
      </Button>
      <Button className="w-full" variant="outline">
        Go Back
      </Button>
    </div>
  )
}

With Icons (Lucide)

import { Button } from '@/components/ui/button'
import { Crown, ChevronRight, X } from 'lucide-react'

function MyComponent() {
  return (
    <>
      <Button icon={<Crown />} variant="premium">
        Upgrade
      </Button>

      <Button icon={<ChevronRight />} iconPosition="right" variant="cta">
        Next Step
      </Button>

      <Button icon={<X />} size="small" variant="error">
        Delete
      </Button>
    </>
  )
}

Loading State

import { Button } from '@/components/ui/button'
import { useState } from 'react'

function MyComponent() {
  const [isLoading, setIsLoading] = useState(false)

  const handleSubmit = async () => {
    setIsLoading(true)
    try {
      await saveData()
    } finally {
      setIsLoading(false)
    }
  }

  return (
    <Button loading={isLoading} variant="cta" onClick={handleSubmit}>
      Save Changes
    </Button>
  )
}