Buttons with Tailwind CSS and React
Tags: tailwindcss, react, typescript
Published: 2022-03-17 19:16:45

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](https://www.gatsbyjs.com/), [TypeScript](https://www.typescriptlang.org/) in my project. 


### Props
```javascript
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;
}
```

### 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.

```javascript
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',
};
```


### Button Component

I have used custom google font here. Check out this [link](https://daily-dev-tips.com/posts/using-google-fonts-in-a-tailwind-project/) if you like to add a custom google font to your tailwind project.

For button with links or href, I have used [Gatsby Link](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-link/).

```javascript
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;
```

I have built the UI component with [Storybook](https://storybook.js.org/)


![Primary Light Button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kqoei2bkb750r1kbn6zg.png)

![Primary Dark Button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0q6ykcizc54tb1scc4dy.png)

![Secondary Light Button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqcvrfs6toxeq8um05uv.png)

![Secondary Dark Button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6x0gxslab1hlijl8add.png)

![Text Light Button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yexn1setlf1b1jhx24b6.png)

![Text Dark Button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6sim0lgo5hhlgcw0q5ca.png)