DEV Community

Tasfia Islam
Tasfia Islam

Posted on • Edited on

Buttons with Tailwind CSS and React

Responsive button design with single React component with Tailwind CSS.

Here I'll show how you can design different types of buttons for both light and dark mode with tailwind. I have used Gatsby, TypeScript in my project.

Props

import { Link } from 'gatsby';
import React, { ReactNode } from 'react';

interface Props {
  type?: 'primary' | 'secondary' | 'text';
  children: ReactNode;
  onClick?: () => void;
  isBlock?: boolean;
  disabled?: boolean;
  className?: string;
  href?: string;
  target?: string;
  width?: string;
}
Enter fullscreen mode Exit fullscreen mode

Define the styles.

Added different text sizes and paddings for mobile and desktop devices. According to button type, text color, background and border are varied.

const textSize = 'text-base lg:text-lg';

const padding = 'px-7 lg:px-10 py-3 lg:py-4';

const color = {
  primary: 'text-white',
  secondary: 'text-slate-700 dark:text-slate-200',
  text: 'text-slate-700 hover:text-white dark:text-slate-200 dark:hover:text-white',
};

const backgroundColors = {
  primary: 'bg-blue-500',
  secondary: 'bg-transparent',
  text: 'bg-light-button hover:bg-blue-500 dark:bg-gray-800 dark:hover:bg-blue-500',
};

const border = {
  primary: 'border-none',
  secondary: 'border-2 border-gray-800 dark:border-white',
  text: 'border-none',
};
Enter fullscreen mode Exit fullscreen mode

Button Component

I have used custom google font here. Check out this link if you like to add a custom google font to your tailwind project.

For button with links or href, I have used Gatsby Link.

const Button = ({
  type = 'primary',
  children,
  onClick,
  className = '',
  disabled = false,
  href,
  target,
  isBlock = true,
  width,
}: Props): JSX.Element => {
  const disabledStyle = disabled
    ? 'opacity-50 cursor-not-allowed'
    : 'transition ease-in-out duration-300 hover:cursor-pointer';

  let baseClasses = [
    'uppercase',
    'font-oswald',
    textSize,
    border[type],
    backgroundColors[type],
    color[type],
    padding,
    disabledStyle,
  ];

  if (className) {
    baseClasses = [...baseClasses, ...className.split(' ')];
  }
  if (isBlock) {
    baseClasses = [...baseClasses, 'block w-full'];
  }
  if (!!width) {
    baseClasses = [...baseClasses, width];
  }

  if (href) {
    let linkClasses = [...baseClasses, 'flex items-center justify-center whitespace-nowrap'];
    return (
      <Link to={href} target={target} onClick={onClick} className={linkClasses.join(' ')}>
        {children}
      </Link>
    );
  }

  return (
    <button onClick={onClick} className={baseClasses.join(' ')} disabled={disabled}>
      {children}
    </button>
  );
};

export default Button;
Enter fullscreen mode Exit fullscreen mode

I have built the UI component with Storybook

Primary Light Button

Primary Dark Button

Secondary Light Button

Secondary Dark Button

Text Light Button

Text Dark Button

Top comments (0)