go to article list

Photo by David Pisnoy on Unsplash
TLDR; This is likely the optimal approach for creating variants in react using tailwind
// @/lib/cn.ts
import clsx from "clsx";
import { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
// @/components/Button/Button.variants.ts
import { cva } from 'class-variance-authority';
const buttonSizes = {
sm: "w-8 h-6",
md: "w-12 h-8"
lg: "w-16 h-12",
};
const buttonColors = {
primary: "bg-blue-400",
danger: "bg-red-400",
warning: "bg-orange-400",
}
export const buttonVariants = cva(
'button',
{
variants: {
size: buttonSizes,
color: buttonColors
},
defaultVariants: {
size: 'md',
color: 'primary',
}
}
)
// @/components/Button/Button.tsx
import cn from '@/lib/cn';
import { VariantProps } from 'class-variance-authority';
import { buttonVariants } from './Button.variants.ts'
interface Props extends VariantProps<typeof buttonVariants> {
children: React.ReactNode;
className?: string;
}
const Button: React.FC<Props> = ({ children, size, color, className }) ⇒ {
return <button className={cn(buttonVariants({ size, color, className })}>{children}</button>
}
<button className={`bg-${color}-400`}></button>
// This would not register since the tailwind only detects classes on runtime, so it would not include bg-{dynamic}-400
// App.tsx
<CustomButton className={’bg-red-400’}>Test</CustomButton>
// CustomButton.tsx
<button className={classNames(’bg-blue-400’, className}>{children}</button>
npm install clsx tailwind-merge class-authority-variance
cn functiontailwind-merge makes sure that there are no conflicting classnames.
// @/lib/cn.ts
import clsx from "clsx";
import { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Button.variants.tsThis is optional, but I prefer using a modular folder structure, and that's why I like to keep things separated
// @/components/Button/Button.variants.ts
import { cva } from 'class-variance-authority';
const buttonSizes = {
sm: "w-8 h-6",
md: "w-12 h-8"
lg: "w-16 h-12",
};
const buttonColors = {
primary: "bg-blue-400",
danger: "bg-red-400",
warning: "bg-orange-400",
}
export const buttonVariants = cva(
'button',
{
variants: {
size: buttonSizes,
color: buttonColors
},
defaultVariants: {
size: 'md',
color: 'primary',
}
}
)
Button.tsx component// @/components/Button/Button.tsx
import { cn } from '@/app/_utils/tailwind-merge';
import { VariantProps } from 'class-variance-authority';
import { buttonVariants } from './Button.variants.ts'
interface Props extends VariantProps<typeof buttonVariants> {
children: React.ReactNode;
className?: string;
}
const Button: React.FC<Props> = ({ children, size, color, className }) ⇒ {
return <button className={cn(buttonVariants({ size, color, className })}>{children}</button>
}
// @/App.tsx
import Button from './components/Button'
export default App() {
return <Button size="sm" color="warning">Warning!</Button>;
}
I've tried my fair share of tricks in creating variants. But guess what? This one takes the cake — and I'm not saying it's better, I'm saying it's a game-changer. Seriously, it's like finding the perfect playlist for your day. So much simpler, so much better. Try it, you won't be disappointed! 🚀
TAGS:
#best-practice
#react
#component variance
#tailwind
go to article list

Having trouble updating branches that is dependent to one another? Enter git-branch-updater

KEEP IT SIMPLE STUPID! EP1 - Pomodoro

The Right Way to Make Component Variants using Tailwind

Essential Tools and Libraries for Daily Web Development Works

How to Send Emails in Next.js 13 Using the New App API Route

Mastering React Testing: A Comprehensive Checklist of What to Test

Mastering Commit Messages: Best Practices and Examples

How to Integrate Contentful to Next 13

Real-Life Applications of Design Patterns in Your Daily React Code