I was frustrated when I saw a lot of Tailwind CSS classes in my JSX code. I love Tailwind CSS, but it can be a bit verbose. I recently learned about shadcn/ui
, a collection of Tailwind CSS components that can be used to create your own component library. I was surprised to find that shadcn/ui
is not a traditional component library. Instead, it provides a set of components and utilities that you can use to create your own components. This makes shadcn/ui
a great choice for developers who want to create their own custom component libraries.
Here are some of the benefits of using shadcn/ui
:
Versatility:
shadcn/ui
provides a wide range of components and utilities, so you can create a component library that meets your specific needs.Flexibility:
shadcn/ui
is not a traditional component library, so you have complete control over the look and feel of your components.Efficiency:
shadcn/ui
can help you to reduce the amount of Tailwind CSS code that you need to write, which can make your code more readable and maintainable.
If you are looking for a way to create your own custom component library, I highly recommend shadcn/ui
. It is a powerful tool that can help you to create beautiful and efficient components.
Here is the simple Title component I have created with it.
import * as React from "react"
import { VariantProps, cva } from "class-variance-authority"
import { cn } from "@/lib/utils"
const titleVariants = cva(
"text-3xl font-extrabold leading-tight tracking-tighter sm:text-3xl md:text-5xl lg:text-6xl",
{
variants: {
variant: {
default: "",
h1: "", // Think Something for H1 specific design
h2: "", // Think Something for H2 specific design
},
size: {
default: "sm:text-3xl md:text-5xl lg:text-6xl",
sm: "sm:text-2xl md:text-4xl lg:text-5xl",
lg: "sm:text-4xl md:text-6xl lg:text-7xl",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface TitleProps
extends React.HTMLAttributes<HTMLHeadingElement>,
VariantProps<typeof titleVariants> {}
function Title(props: TitleProps) {
const { variant, size, className, ...rest } = props
function H1() {
return (
<h1
className={cn(titleVariants({ variant, size, className }))}
{...rest}
/>
)
}
function H2() {
return (
<h2
className={cn(titleVariants({ variant, size, className }))}
{...rest}
/>
)
}
let titleComponentMap = {
h1: <H1 />,
h2: <H2 />,
default: <H1 />,
}
type ComponentMapKey = keyof typeof titleComponentMap
return titleComponentMap[variant as ComponentMapKey] || <H1 />
}
export { Title, titleVariants }
And its implementation in the page.tsx
looks like
import Link from "next/link"
import { siteConfig } from "@/config/site"
import { buttonVariants } from "@/components/ui/button"
import { Title, titleVariants } from "@/components/ui/title"
export default function IndexPage() {
return (
<section className="container grid items-center gap-6 pb-8 pt-6 md:py-10">
<div className="flex max-w-[980px] flex-col items-start gap-2">
<Title size="default" variant="h1">
Beautifully designed components <br className="hidden sm:inline" />
built with Radix UI and Tailwind CSS.
</Title>
<h2 className={titleVariants({ variant: "h2", size: "sm" })}>
This is H2
</h2>
<p className="max-w-[700px] text-lg text-muted-foreground sm:text-xl">
Accessible and customizable components that you can copy and paste
into your apps. Free. Open Source. And Next.js 13 Ready.
</p>
</div>
<div className="flex gap-4">
<Link
href={siteConfig.links.docs}
target="_blank"
rel="noreferrer"
className={buttonVariants({ size: "lg" })}
>
Documentation
</Link>
<Link
target="_blank"
rel="noreferrer"
href={siteConfig.links.github}
className={buttonVariants({ variant: "outline", size: "lg" })}
>
GitHub
</Link>
</div>
</section>
)
}
Have you noticed the following part in the page.tsx
page:
<Title size="default" variant="h1">
Beautifully designed components <br className="hidden sm:inline" />
built with Radix UI and Tailwind CSS.
</Title>
<h2 className={titleVariants({ variant: "h2", size: "sm" })}>
This is H2
</h2>
In the first example, we have used Title
component with size
and variant
props, and in the second example, we have used titleVariants
in the className property.
Thank you.