💪Mastering React: Crafting a Stunning Reusable Button Component ✨

💪Mastering React: Crafting a Stunning Reusable Button Component ✨

Introduction📑

Buttons are an essential part of any user interface, and in React, creating reusable button components can help streamline your development process. In this blog, we'll walk you through the steps to create a clean and beautiful reusable button component using React. We'll also explain each step in detail, making it easy for both beginners and experienced developers to follow along.

Tech Stack📃

To make a Reusable button comment i will use this techstack🚀

HTML , Tailwind css , Typescript, Reactjs , React-icons

Step 1️⃣: Setting up your Environment🌎

Before we dive into the code, make sure you have a React project up and running. You can create one using tools like . Here, i am using Nextjs 13 so my create-app command in this:

To read more about this in detail . Click Here

npx create-next-app@latest

After running this command ☝ You will de this type of interface in CLI

What is your project named? my-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias? No / Yes
What import alias would you like configured? @/*

I will select YES to every opition . You can select according to your choice .

After installation the project directory look like this : 👇

🔻my-app
    ▶ .next
    ▶ node_modules
    ▶ public
    ▶ src
    ⚙.env
    .eslintrc.json
    .gitignore
    {}components.json
    next-env.d.ts
    next.config.js
    {}package-lock.json
    {}package.json
    postcss.config.js
    tailwind.config.ts
    tsconfig.json

Step 2️⃣: Import Necessary Dependencies📁

To get started, import the required dependencies for your button component. In your code, you'll notice we're using packages like 'class-variance-authority', 'clsx' , 'tailwind-merge' and 'lucide-react' to enhance the functionality and styling of our buttons. These packages are essential for creating versatile and visually appealing buttons. COPY THIS COMMAND AND INSTALL DEPENDENCIES.

npm install clsx tailwind-merge class-variance-authority lucide-react

Ok then after installing it . Let's , move to code reusable component .

Step 3️⃣: Creating utils.ts file for reusable button components✡

Before creating Button component , We have to create a folder with name "lib" inside "src" named folder and then create a file with name "utils.ts" inside "lib" folder.

You can give any name to that file and folder .📁

🔻my-app
    ▶ .next
    ▶ node_modules
    ▶ public
    🔻src
        ▶ app
        🔻lib
           📃utils.ts
    ⚙.env
    .eslintrc.json
    .gitignore
    {}components.json
    next-env.d.ts
    next.config.js
    {}package-lock.json
    {}package.json
    postcss.config.js
    tailwind.config.ts
    tsconfig.json

Ok then lets write code in utils.ts📃

import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

This piece of code appears to define a function called cn that takes one or more arguments representing CSS class values and combines them using two libraries: clsx and tailwind-merge.

Main Step 4️⃣ : Creating main file Button.tsx🚀

After creating utils.ts .Now, Main step is to create Button.tsx file for that first we will create components name folder inside src directory , Not neccessay to create components we are creating to make our file structure clean and easy to maintain.

🔻my-app
    ▶ .next
    ▶ node_modules
    ▶ public
    🔻src
        ▶ app
        🔻components
            Button.tsx
        🔻lib
            utils.ts

So we are creating here components folder and inside it Button.tsx name folder

Here is the code to copy of Button.tsx file:

import { cn } from '@/lib/utils' //Here "cn" is importing from utils file
import { cva, VariantProps } from 'class-variance-authority'
import { Loader2 } from 'lucide-react'
import * as React from 'react'

const buttonVariants = cva(
  'active:scale-95 inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:opacity-50 dark:focus:ring-slate-400 disabled:pointer-events-none dark:focus:ring-offset-slate-900',
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive:
          "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline:
          'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
        custom:
          ' bg-[#343e44] text-white  hover:bg-[#5c6165]  hover:shadow-lg',
        subtle:
          'border border-input bg-background hover:bg-[#6aa2e6] hover:text-white',
        ghost:
          'bg-transparent hover:bg-zinc-100 text-zinc-800 data-[state=open]:bg-transparent data-[state=open]:bg-transparent',
      },
      size: {
        default: 'h-10 py-2 px-4',
        sm: 'h-9 px-2 rounded-md',
        xs: 'h-8 px-1.5 rounded-sm',
        lg: 'h-11 px-8 rounded-md',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
  VariantProps<typeof buttonVariants> {
  isLoading?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, children, variant, isLoading, size, ...props }, ref) => {
    return (
      <button
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        disabled={isLoading}
        {...props}>
        {isLoading ? <Loader2 className='mr-2 h-4 w-4 animate-spin' /> : null}
        {children}
      </button>
    )
  }
)
Button.displayName = 'Button'

export { Button, buttonVariants }

Now, we define the Button component. It is created using React.forwardRef, which enables us to pass a ref to the underlying button element. The component takes various props like className, children, variant, isLoading, size, and more. It renders a button with appropriate CSS classes based on the provided props.

You can create different varients with any name accourding to your needs.

🚀Final Step : How to render reusable Button ✅

In this final step, we render the button element. We apply CSS classes based on the variant, size, and className props. We also handle the isLoading prop, which displays a loading spinner when set to true. The children prop is used to render any content inside the button.

import { Button } from '@/components/ui/button'
import Link from 'next/link'

export default function Home() {
  return (
    <div className='h-screen w-full flex justify-center items-center'>
      <h3 className='mt-2 mb-2 text-lg text-center '>Testing My reusable Button</h3>
      <Button 
         variant={'custom'} 
         ClassName={"p-4 text-state-400"} 
         size={"lg"} 
         isLoading={false}
        > click Here!
       </Button>
     </div>
  )
}

Explanation:

         variant={'custom'} // => SELECT ANY VARIENT or ADD and EDit
         ClassName={"p-4 text-state-400"} // => YOU CAN USE ANY TAILWIND STYLING
         size={"lg"} // => 3 Types of size you can edit accourding to you
         isLoading={true} // => Awsome inbuilt loading . By default it is false.

Conclusion✨

By following these steps, we've successfully created a reusable button component in React. This component is highly customizable, making it a valuable asset for building clean and beautiful user interfaces. You can use it throughout your application, changing its style and size effortlessly by passing the appropriate props. This approach not only promotes code reusability but also ensures a consistent and appealing design across your web application.

Thanks for reading this article, If you find this article useful then please Like💖 and Comment 💬 this article.

SUBSCRIBE NEWSLETTER FOR MORE ✅

THANK YOU💖

Happy coding!👩‍💻

Did you find this article valuable?

Support Today'sCode by becoming a sponsor. Any amount is appreciated!