Skip to main content

Button Component

The Button component is a versatile, styled button built on top of the native HTML button element. It supports multiple variants, sizes, icons, and loading states.

Import

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

Basic Usage

<Button onClick={() => console.log('Clicked!')}>
  Click Me
</Button>

API Reference

Props

The Button component extends all standard HTML button attributes and adds the following custom props:
variant
string
default:"primary"
The visual style variant of the button.Options:
  • primary - Blue background, white text with shadow
  • secondary - Light gray background with border
  • success - Green background with hover lift effect
  • danger - Red background for destructive actions
  • ghost - Transparent background, visible on hover
  • outline - Transparent with border
size
string
default:"md"
The size of the button.Options:
  • sm - Small (px-3 py-1.5 text-xs)
  • md - Medium (px-4 py-2.5 text-sm)
  • lg - Large (px-5 py-3 text-base)
  • xl - Extra Large (px-6 py-4 text-lg h-16)
icon
ReactNode
An optional icon element to display before the button text.
isLoading
boolean
default:"false"
When true, displays a spinning loader icon and disables the button.
fullWidth
boolean
default:"false"
When true, the button takes up the full width of its container.
className
string
default:""
Additional CSS classes to apply to the button.
disabled
boolean
When true, disables the button (also disabled when isLoading is true).
children
ReactNode
The content to display inside the button.

Inherited Props

The component also accepts all standard ButtonHTMLAttributes<HTMLButtonElement> props including:
  • onClick
  • type (button, submit, reset)
  • form
  • name
  • value
  • And all other native button attributes

Examples

Variant Examples

<Button variant="primary">
  Save Changes
</Button>
Default blue button with white text and shadow.

Size Examples

// Small button
<Button size="sm">Small</Button>

// Medium button (default)
<Button size="md">Medium</Button>

// Large button
<Button size="lg">Large</Button>

// Extra large button
<Button size="xl">Extra Large</Button>

With Icon

import { Save, Trash2 } from 'lucide-react';

<Button 
  variant="primary" 
  icon={<Save size={16} />}
>
  Save Document
</Button>

<Button 
  variant="danger" 
  icon={<Trash2 size={16} />}
>
  Delete
</Button>

Loading State

import { useState } from 'react';

function SubmitForm() {
  const [loading, setLoading] = useState(false);
  
  const handleSubmit = async () => {
    setLoading(true);
    await saveData();
    setLoading(false);
  };
  
  return (
    <Button 
      variant="success" 
      isLoading={loading}
      onClick={handleSubmit}
    >
      Submit Form
    </Button>
  );
}

Full Width

<Button fullWidth variant="primary">
  Continue
</Button>

Custom Styling

<Button 
  variant="primary"
  className="shadow-xl hover:scale-105"
>
  Custom Styled Button
</Button>

Styling Details

Base Styles

All buttons include these base styles:
  • Flexbox centering for content
  • Bold font weight
  • Rounded corners (rounded-lg)
  • Smooth transitions
  • Focus ring for accessibility
  • Disabled state styling (50% opacity, not-allowed cursor)

Variant Color Schemes

VariantBackgroundTextHoverFocus Ring
primaryBlue 600WhiteBlue 700Blue 500
secondarySlate 100Slate 700Slate 200Slate 500
successEmerald 600WhiteEmerald 700Emerald 500
dangerRed 500WhiteRed 600Red 500
ghostTransparentSlate 600Slate 100Slate 500
outlineTransparentSlate 700Slate 50Slate 500

Accessibility

  • Supports keyboard navigation (Tab, Enter, Space)
  • Includes focus ring for visibility
  • Properly handles disabled state
  • Loading state prevents multiple submissions
When isLoading is true, the button is automatically disabled to prevent duplicate submissions.

Source Code

Location: /home/daytona/workspace/source/src/components/ui/Button.tsx:1

Build docs developers (and LLMs) love