Skip to main content

Overview

The Button component is a highly customizable, accessible button element that supports multiple visual variants, sizes, and states. It’s built with TypeScript and forwards refs for advanced use cases. Source: src/shared/ui/button/Button.tsx

Basic Usage

import { Button } from '@/shared/ui/button/Button';

function Example() {
  return (
    <Button variant="primary" size="md">
      Click Me
    </Button>
  );
}

Props

The Button component extends all standard HTML button attributes and includes these additional props:
variant
ButtonVariant
default:"primary"
The visual style variant of the button.Options: "primary" | "secondary" | "danger" | "outline"
  • primary: Main call-to-action buttons
  • secondary: Secondary actions
  • danger: Destructive actions (e.g., delete)
  • outline: Outlined style for subtle actions
size
ButtonSize
default:"md"
Controls the size of the button.Options: "sm" | "md" | "lg"
  • sm: Small buttons for compact spaces
  • md: Default medium size
  • lg: Large buttons for prominent actions
block
boolean
default:"false"
When true, the button stretches to fill its container’s full width.Useful for mobile layouts and full-width CTAs.
disabled
boolean
default:"false"
Disables the button, preventing user interaction and applying disabled styling.
className
string
Additional CSS class names to apply to the button for custom styling.
children
React.ReactNode
required
The content to display inside the button (text, icons, or other elements).
type
string
default:"button"
HTML button type attribute.Options: "button" | "submit" | "reset"

Variants

Primary Button

The default variant for primary actions:
<Button variant="primary">
  Primary Button
</Button>

Secondary Button

For secondary or alternative actions:
<Button variant="secondary">
  Secondary Button
</Button>

Danger Button

For destructive actions that require user attention:
<Button variant="danger">
  Delete
</Button>

Outline Button

For subtle actions with an outlined style:
<Button variant="outline">
  Outline
</Button>

Sizes

Small

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

Medium (Default)

<Button size="md">
  Medium Button
</Button>

Large

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

Block Width

Full-width buttons that stretch to fill their container:
<Button block>
  Full Width Button
</Button>
Block buttons are particularly useful for mobile layouts and form submit buttons.

Disabled State

<Button disabled>
  Disabled Button
</Button>
Disabled buttons cannot be interacted with and display appropriate visual feedback.

Real-World Examples

Form Submit Button

import { Button } from '@/shared/ui/button/Button';

function SubmitForm() {
  const [isLoading, setIsLoading] = useState(false);
  
  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
      <Button 
        type="submit" 
        variant="primary" 
        size="lg"
        block
        disabled={isLoading}
      >
        {isLoading ? 'Submitting...' : 'Submit'}
      </Button>
    </form>
  );
}

Confirmation Dialog

import { Button } from '@/shared/ui/button/Button';

function ConfirmDelete() {
  return (
    <div>
      <p>Are you sure you want to delete this item?</p>
      <div style={{ display: 'flex', gap: '8px' }}>
        <Button variant="outline" onClick={handleCancel}>
          Cancel
        </Button>
        <Button variant="danger" onClick={handleDelete}>
          Delete
        </Button>
      </div>
    </div>
  );
}

Action Group

import { Button } from '@/shared/ui/button/Button';

function ActionBar() {
  return (
    <div style={{ display: 'flex', gap: '12px' }}>
      <Button variant="primary" size="md">
        Save
      </Button>
      <Button variant="secondary" size="md">
        Save Draft
      </Button>
      <Button variant="outline" size="md">
        Cancel
      </Button>
    </div>
  );
}

With Icons

import { Button } from '@/shared/ui/button/Button';
import { Plus, Trash2 } from 'lucide-react';

function IconButtons() {
  return (
    <>
      <Button variant="primary">
        <Plus size={16} /> Add Item
      </Button>
      
      <Button variant="danger">
        <Trash2 size={16} /> Delete
      </Button>
    </>
  );
}

TypeScript Types

The Button component is fully typed for TypeScript users:
export type ButtonSize = "sm" | "md" | "lg";
export type ButtonVariant = "primary" | "secondary" | "danger" | "outline";

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  size?: ButtonSize;
  variant?: ButtonVariant;
  block?: boolean;
  className?: string;
}

Accessibility

  • The Button component uses semantic <button> HTML elements
  • Properly handles the disabled state with visual and functional feedback
  • Supports keyboard navigation (Enter and Space keys)
  • Forwards refs for advanced accessibility features (e.g., focus management)
When using buttons for navigation, consider using a link (<a>) element instead. Buttons should be used for actions, not navigation.

Best Practices

  • Use primary for the main action on a page
  • Use secondary for alternative actions
  • Reserve danger for destructive actions
  • Use outline for tertiary actions
  • Keep button text concise (1-3 words ideal)
  • Use action verbs (Save, Delete, Submit)
  • Be specific about the action (“Save Changes” vs “OK”)
  • Disable buttons during async operations
  • Update button text to indicate loading (“Saving…”)
  • Consider adding a loading spinner for longer operations

TextField

Often used together in forms

CardContainer

Buttons frequently appear in card layouts

Build docs developers (and LLMs) love