Create a Universal Button With React + TailwindCSS

As your project grows in size, component reusability becomes more and more important. There are times when it makes sense to make universal components, and there are times when you need more specialized components. Knowing when to use which is crucial. If you try to make too many universal components that do too many things, then your product will end up with a lot of bloat. But if you use too few universal components, you will go crazy keeping track of them all. Today we're going to learn how to create a very useful component: a React universal button component that can be either a or element depending on the props passed to it. We will also be using TailwindCSS for styling. The demo project (link at bottom) was spun up using pnpm create vite@latest, selecting React + Typescript template. We'll also need to install Tailwind and some additional utilities: pnpm i -D tailwindcss @tailwindcss/vite tailwind-merge clsx Next, we'll add Tailwind to our vite.config.ts: import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; import tailwindcss from "@tailwindcss/vite"; // https://vite.dev/config/ export default defineConfig({ plugins: [react(), tailwindcss()], }); Then replace everything in index.css with: @import "tailwindcss"; Now we need to create a helper function to help us deal with variable Tailwind classes (src/lib/cn.ts): import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } If this looks familiar, it's the same function that ShadCN uses to merge class names. Next, we'll create our button component at src/components/button.tsx: import { cn } from "../lib/cn"; import type { ButtonHTMLAttributes, AnchorHTMLAttributes } from "react"; type ButtonAsButton = ButtonHTMLAttributes & { type: "button"; title: string; }; type ButtonAsAnchor = AnchorHTMLAttributes & { type: "a"; href: string; title: string; }; type ButtonProps = ButtonAsButton | ButtonAsAnchor; export default function Button(props: ButtonProps) { const { className, type, ...rest } = props; const classes = cn( "bg-blue-500 hover:brightness-120 cursor-pointer transition-all duration-200 ease-in-out text-white px-4 py-2 rounded-md text-center", className ); if (type === "button") { return ; } return ; } This component does several useful things: It provides strict type safety based on the type attribute It provides a default base style that you can use as your default button It allows any other Tailwind background color to be used without having to specify a hover background color, thanks to brightness-120 class We return a or element depending on type prop. You could also supply a React Router or Next.js component as well. Below are several examples of various ways this component can be used: import { useState } from "react"; import Button from "./components/button"; export default function App() { const [displayText, setDisplayText] = useState("Choose your button wisely!"); return ( React + Tailwind CSS - Universal Button Demo {displayText} { setDisplayText("Default Button, a safe choice!"); }} > Default Button { setDisplayText("Red Button, a risky choice!"); }} > Red Button { setDisplayText("Green Button, NO NOT THAT ONE!"); }} > Green Button { setDisplayText("Link Button, it's a link and a button!"); }} > Link Button ); } Links GitHub Repo Demo Site Thank You! Thank you for taking the time to read my article and I hope you found it useful (or at the very least, mildly entertaining). For more great information about web dev, systems administration and cloud computing, please read the Designly Blog. Also, please leave your comments! I love to hear thoughts from my readers. If you want to support me, please follow me on Spotify or SoundCloud! Current Projects Snoozle.io- An AI app that generates bedtime stories for kids ❤️ react-poptart - A React Notification / Alerts Library (under 20kB) Spectravert - A cross-platform video converter (ffmpeg GUI) Smartname.app - An AI name generator for a variety of purposes Looking for a web developer? I'm available for hire! To inquire, please fill out a contact form.

May 4, 2025 - 03:14
 0
Create a Universal Button With React + TailwindCSS

As your project grows in size, component reusability becomes more and more important. There are times when it makes sense to make universal components, and there are times when you need more specialized components. Knowing when to use which is crucial.

If you try to make too many universal components that do too many things, then your product will end up with a lot of bloat. But if you use too few universal components, you will go crazy keeping track of them all.

Today we're going to learn how to create a very useful component: a React universal button component that can be either a