Building a Customizable Button Component in React with Tailwind CSS and TypeScript
Here’s a complete guide on setting up and using the Button component you provided, from installing dependencies to implementation.
Step 1: Set Up a New Project (If Needed)
- If you don’t already have a Next.js/React project, create a new one by running:
npx create-next-app@latest my-app
- Navigate into the project directory:
cd my-app
Step 2: Install Dependencies
Install the following packages if they’re not already included in your project:
- class-variance-authority: Helps to manage class-based variants.
- classnames: Simplifies conditional class name merging (often aliased as cn in code).
npm install class-variance-authority classnames
Step 3: Create Utility Functions
In your project, create a utility function cn to combine class names using the classnames library.
- Create a new file at lib/utils/utils.ts.
- Add the following code in utils.ts:
import classNames from "classnames"; export function cn(...classes: string[]) { return classNames(...classes); }
Step 4: Create the Button Component
- Create a new file for the Button component, for example, components/Button.tsx.
- Add the Button component code you provided:
import { cn } from "@/lib/utils/utils"; import { cva, type VariantProps } from "class-variance-authority"; import React, { ButtonHTMLAttributes, forwardRef, Ref } from "react"; const buttonVariants = cva( "active:scale-95 text-center active:duration-75 transition-all ease-in-out dark:bg-inherit", { variants: { variant: { default: "dark:bg-black rounded-full flex items-center bg-white bg-slate-900 text-black dark:text-white text-center dark:hover:bg-blue-800/50 hover:bg-slate-300/80 dark:border-white border-black", primary: "bg-sky-500 text-white", secondary: "bg-slate-500 text-white", danger: "bg-red-500 text-white", }, size: { default: "h-12 px-10 py-2 border-2", sm: "h-10 px-6 py-2 border-[1.5px]", lg: "h-14 px-10", }, }, defaultVariants: { variant: "default", size: "default", }, } ); interface NewButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { title?: string; children?: React.ReactNode; } const Button = forwardRef<HTMLButtonElement, NewButtonProps>( ( { title, variant, className, children, size, ...props }, ref: Ref<HTMLButtonElement> ) => { return ( <button className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} > {title} {children} </button> ); } ); Button.displayName = "Button"; export { Button, buttonVariants };
Step 5: Use the Button Component
Now that the component is set up, import and use it within your application.
- Open any page, such as pages/index.tsx.
- Import the Button component.
- Use it as follows:
import React from "react"; import { Button } from "@/components/Button"; export default function Home() { return ( <div className="flex flex-col items-center justify-center h-screen"> <Button variant="primary" size="lg" title="Primary Button"> Primary Button Content </Button> <Button variant="secondary" size="sm" title="Secondary Button"> Secondary Button Content </Button> <Button variant="danger" title="Danger Button"> Danger Button Content </Button> </div> ); }
Step 6: Add CSS (Optional Tailwind Configuration)
If you’re using Tailwind CSS, make sure it’s properly set up in your project for the styles to apply. If not, install it by following these steps:
- Install Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
- Configure Tailwind in your tailwind.config.js:
module.exports = { content: [ "./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {}, }, plugins: [], };
- Import Tailwind CSS in styles/globals.css:
@tailwind base; @tailwind components; @tailwind utilities;
Step 7: Run the Project
Start your development server to see your button component in action:
npm run dev
Summary
- Set up the project, install dependencies, and create the cn utility.
- Implement the Button component with cva for variant and size management.
- Use and customize the component throughout your app.
The Button component is now ready for consistent use across your application with built-in styling options for various states, sizes, and themes.