Button Design System with React and Tailwind

Buttons are fundamental UI elements in web development, serving as key interaction points for users. Designing a flexible, reusable button component can significantly enhance the consistency and scalability of your React application.

In this button design system guide, I’ll walk you through creating a button component using React and Tailwind CSS with three distinct variants Primary, Secondary, and Outline as well as a disabled state and a loading spinner for better user feedback.

React Button Design System UI Preview

React Button Design System

Button Component Variants

  1. Primary - The default attention-grabbing color for main actions.
  2. Secondary - A softer, muted color for secondary actions.
  3. Outline - A minimalist style with a transparent background and border.

React Button Component with Tailwind

Here’s the complete code for the button component with live preview. Copy paste this into your ui components folder.

1import React, { MouseEventHandler, ReactNode } from 'react' 2import { cn } from '../utils/functions' 3 4interface ButtonProps { 5 children: ReactNode 6 variant?: 'primary' | 'secondary' | 'outline' 7 loading?: boolean 8 disabled?: boolean 9 type?: 'button' | 'submit' | 'reset' 10 onClick?: MouseEventHandler<HTMLButtonElement> 11 className?: string 12} 13 14const Button: React.FC<ButtonProps> = ({ 15 children, 16 variant = 'primary', 17 loading = false, 18 disabled = false, 19 type = 'button', 20 onClick, 21 className, 22}) => { 23 const baseStyles = 24 'h-9 rounded-lg py-2 px-4 font-medium transition duration-300 ease-in-out inline-flex items-center justify-center gap-2 disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-not-allowed disabled:border-gray-300' 25 26 const variantStyles: Record<string, string> = { 27 primary: 'bg-[#00AAFF] text-white hover:bg-sky-600 border border-transparent', 28 secondary: 'bg-[#EBEEF7] text-[#191F33] hover:bg-violet-200 border border-transparent', 29 outline: 'bg-transparent text-[#7D8592] border border-[#D8E0F0] hover:bg-[#D8E0F0]', 30 } 31 32 return ( 33 <button 34 className={cn(baseStyles, !disabled && variantStyles[variant], className)} 35 disabled={disabled || loading} 36 onClick={onClick} 37 type={type} 38 > 39 {children} 40 </button> 41 ) 42} 43 44export default Button

Here are some of the variants we created using the button component code above. I coded it with a design system in mind.

Button Variants

You can easily adjust the primary, secondary, and other variants by changing the color names by matching it with your theme in button.tsx file.

Button Variants

Disabled State

Loading Spinner Button

Loading State

Features of the Loading Spinner Button

  1. Dynamic Spinner Animation
    • Displays a spinning loader icon (Loader2 from Lucide React) when in the loading state.
  2. Disabled State Handling
    • Automatically disables the button during loading to prevent duplicate submissions.

Custom Style Button

You can easily customize and override the default styling by passing className props.

Custom Styles

Continue with Google Button

Login with Google

API

PropTypeRequiredDefaultDescription
childrenReactNodeYesThe content inside the button, such as text or icons.
variant'primary' | 'secondary' | 'outline'No'primary'Defines the button style variant.
loadingbooleanNofalseDisplays a loading spinner when set to true.
disabledbooleanNofalseDisables the button when set to true.
type'button' | 'submit' | 'reset'No'button'Specifies the button type attribute.
onClickMouseEventHandler<HTMLButtonElement>NoundefinedFunction triggered when the button is clicked.
classNamestringNoundefinedAdditional Tailwind classes for customization.

This component is a great starting point for building more complex UI systems and can be extended to include additional variants and functionality as needed.


Flexy UI Newsletter

Build better and faster UIs.Get the latest Tailwind UI components directly in your inbox. No spam!