Making Shadcn UI Components Simple with UIC
At Contember, we use Shadcn UI as our main UI library. It’s powerful and easy to customize, with many useful components built on Radix UI. We already liked Radix, so Shadcn was an easy choice.
But as our projects grew, we noticed the components became difficult to read and manage. We wanted something simpler and easier to maintain. So, we created the UIC package to help with that.
Original Shadcn UI Button Example
Here's what a typical Button component looks like in Shadcn UI:
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
Simplified with UIC
With our new UIC package, this Button becomes very simple:
export const Button = uic('button', buttonConfig)
This way, the code is clearer, easier to change, and quicker to maintain.
Another Example – Card Components
This is how typical Shadcn UI Card components look:
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("rounded-xl border bg-card text-card-foreground shadow", className)} {...props} />
)
)
Card.displayName = "Card"
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
)
)
CardHeader.displayName = "CardHeader"
const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("font-semibold leading-none tracking-tight", className)} {...props} />
)
)
CardTitle.displayName = "CardTitle"
// Additional Card components not shown for brevity
Easier Card Components with UIC
Here's how these same Card components look using UIC:
export const Card = uic('div', {
baseClass: 'rounded-xl border bg-card text-card-foreground shadow',
})
export const CardHeader = uic('div', {
baseClass: 'flex flex-col space-y-1.5 p-6',
})
export const CardTitle = uic('h3', {
baseClass: 'font-semibold leading-none tracking-tight',
})
export const CardDescription = uic('p', {
baseClass: 'text-sm text-muted-foreground',
})
export const CardContent = uic('div', {
baseClass: 'p-6 pt-0 space-y-2 first:pt-6',
})
export const CardFooter = uic('div', {
baseClass: 'flex items-center p-6 pt-0',
})
As you can see, the new version is shorter and much clearer. These simple changes help us build things faster and keep our code clean and easy to understand.
I hope this gives you some ideas to simplify your UI code too!