Table of contents
- Introduction📑
- Tech Stack📃
- Step 1️⃣: Setting up your Environment🌎
- Step 2️⃣: Import Necessary Dependencies📁
- Step 3️⃣: Creating utils.ts file for reusable button components✡
- Ok then lets write code in utils.ts📃
- Main Step 4️⃣ : Creating main file Button.tsx🚀
- 🚀Final Step : How to render reusable Button ✅
- Conclusion✨
- SUBSCRIBE NEWSLETTER FOR MORE ✅
- THANK YOU💖
- Happy coding!👩💻
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.