Redpanda UI
RC
Redpanda UI

Button

Displays a button or a component that looks like a button.

Made by shadcn
Loading component...

Installation

Usage

The Button component supports multiple variants and sizes to fit different use cases in your application:

import { Button } from "@/components/redpanda-ui/button"

// Basic usage
<Button>Click me</Button>

// With variants
<Button variant="outline">Outline Button</Button>
<Button variant="destructive">Delete</Button>
<Button variant="ghost">Ghost Button</Button>

// With sizes
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button size="icon">
  <Plus className="h-4 w-4" />
</Button>

// Loading state
<Button disabled>
  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
  Loading...
</Button>

// As a link wrapper
<Button asChild>
  <Link href="/dashboard">Go to Dashboard</Link>
</Button>

Composing Buttons

When designing interfaces with multiple buttons, visual hierarchy and consistency are essential. Follow these principles to create clear, intuitive button compositions:

The One Filled Button Rule

Use a singular filled button per screen or context. This filled button represents the primary action you want users to take—whether that's submitting a form, progressing through a flow, or completing a task. Multiple filled buttons create visual competition and dilute the primary action's importance.

Button Hierarchy

Buttons follow a clear visual hierarchy that communicates priority:

  1. Filled buttons (default, destructive) - Primary actions, highest emphasis
  2. Outline buttons (secondary-outline, destructive-outline) - Secondary actions, medium emphasis
  3. Ghost buttons (secondary-ghost, ghost) - Tertiary actions, lowest emphasis

Outline buttons are your workhorse—use them frequently for secondary actions. Their white background and border make them more prominent and user-friendly than ghost buttons, while still clearly secondary to filled buttons. Ghost buttons should be reserved for tertiary actions that shouldn't dominate the interface.

CRUD Action Patterns

When designing create, read, update, and delete operations, maintain consistency across your interface:

  • Create actions - Use the default (filled) variant
  • Edit/Update actions - Use secondary-outline variant
  • Delete actions - Use destructive-outline variant
  • Confirm delete - Use destructive (filled) variant in confirmation dialogs

This pattern creates a consistent visual language: filled buttons move forward with creation or confirmation, outline buttons for modification actions, and destructive variants clearly signal data removal.

Loading component...

Form and Multi-Step Flow Patterns

Forms, wizards, and multi-step processes require careful button placement to guide users through the experience:

  • Submit/Next/Continue - Use default (filled) variant, only one per view
  • Secondary actions (Save draft, Skip, etc.) - Use secondary-outline variant
  • Back/Cancel - Use secondary-ghost variant

The filled button always represents forward progress. Back and cancel actions use ghost buttons since they're escape routes users shouldn't be encouraged to take.

Loading component...

Content Guidelines

Button content should be text OR an icon, never both. This maintains visual simplicity and clarity. When you need an icon with text, consider whether the icon is truly necessary—often the text alone is clearer. Icon-only buttons should be reserved for common, universally understood actions (close, search, menu) and should always include accessible labels.

When to use

Use this decision tree to determine which button variant is most appropriate for your context:

Variant Guidelines

Understanding each variant's purpose helps maintain consistent visual hierarchy across your interface:

  • Default - Your primary filled button. Use for forward-moving actions like "Submit", "Create", "Continue", and "Save". Only one per screen or context.

  • Secondary Outline - Your most frequently used secondary button. The white background and visible border provide clear emphasis while remaining visually secondary. Use for edit actions, secondary form actions, and any supporting operation that needs prominence.

  • Secondary Ghost - For tertiary actions that shouldn't dominate. Use sparingly for back/cancel actions in flows, or when you need a button-like interaction with minimal visual weight.

  • Destructive - The filled destructive variant for critical confirmations. Use exclusively in confirmation dialogs when users must confirm permanent data deletion.

  • Destructive Outline - For inline delete actions. The outline treatment makes destructive actions visible but not as visually dominant as filled buttons, appropriate for destructive operations in tables, cards, or lists.

  • Outline - A neutral outline button for general secondary actions that don't fit the secondary-outline or destructive patterns.

  • Ghost - Minimal tertiary actions in data-dense interfaces like tables, cards, or navigation. Use when you need interaction without adding visual weight.

  • Link - For actions that behave like navigation links. Use when the action feels more like "going somewhere" than "doing something".

  • Dashed - Specialized for "add new" or placeholder actions, commonly used in empty states or to add items to lists.

You can use the buttonVariants helper to create a link that looks like a button.

import { buttonVariants } from "@/components/ui/button"
<Link className={buttonVariants({ variant: "outline" })}>Click here</Link>

Alternatively, you can set the asChild parameter and nest the link component from any router, including TanStack/React Router/Next.js/Remix paradigms.

<Button asChild>
  <Link href="/login">Login</Link>
</Button>

Anatomy

The Button component is built with composition in mind, using Radix UI's Slot primitive for flexibility:

Button Component Structure:
┌─────────────────────────────────────┐
│ Button Container                    │
│ ┌─────────────────────────────────┐ │
│ │ Slot/HTML button element        │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ Content Area                │ │ │
│ │ │ [Icon] [Text] [Icon]        │ │ │
│ │ │                             │ │ │
│ │ │ - Icons: auto-sized (4×4)   │ │ │
│ │ │ - Text: inherits font style │ │ │
│ │ │ - Gap: 0.5rem between items │ │ │
│ │ └─────────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
│                                     │
│ Properties:                         │
│ - variant: styling theme            │
│ - size: dimensions & padding        │
│ - asChild: render as child element  │
│ - disabled: interaction state       │
└─────────────────────────────────────┘

Component Composition

  • Base: Uses either <button> element or Radix UI Slot for custom components
  • Styling: CSS classes via class-variance-authority for consistent theming
  • Accessibility: Built-in focus states, disabled states, and ARIA support
  • Icons: Automatically sized and positioned with proper spacing
  • Content: Flexible content area supporting text, icons, or custom elements

Examples

Primary

Loading component...

Variants

Loading component...

Dashed

Loading component...
Loading component...

Icon

Loading component...

With Icon

Loading component...

Loading

Loading component...

As Child

Loading component...

Router Integration

Loading component...

Credits

  • We use Radix UI for the slot component.
  • We take our inspiration from Shadcn UI for the button style.

Built by malinskibeniamin. The source code is available on GitHub.

On this page