Skip to main content

Component Library (shadcn/ui)

Overview

shadcn/ui is a collection of reusable components built with:

  • Radix UI - Accessible, unstyled primitives
  • Tailwind CSS - Styling
  • Class Variance Authority - Variant management
  • TypeScript - Type safety

Configuration

Location: components.json

{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/cn",
"ui": "@/components/ui"
}
}

Available Components

Location: src/components/ui/

ComponentDescriptionBased On
button.tsxButton with variantsRadix Slot
input.tsxText input with formattingCustom
select.tsxDropdown selectRadix Select
card.tsxCard containerCustom
dialog.tsxModal dialogRadix Dialog
form.tsxForm componentsReact Hook Form
table.tsxTable componentsCustom
tabs.tsxTab navigationRadix Tabs
toast.tsxToast notificationsRadix Toast
tooltip.tsxTooltipRadix Tooltip
sidebar.tsxSidebar navigationCustom
avatar.tsxAvatar imageRadix Avatar
badge.tsxBadge labelCustom
checkbox.tsxCheckboxRadix Checkbox
switch.tsxToggle switchRadix Switch
radio-group.tsxRadio buttonsRadix Radio Group
popover.tsxPopoverRadix Popover
dropdown-menu.tsxDropdown menuRadix Dropdown Menu
scroll-area.tsxScrollable areaRadix Scroll Area
separator.tsxDividerRadix Separator
skeleton.tsxLoading skeletonCustom
spinner.tsxLoading spinnerCustom
stepper.tsxStep indicatorCustom
calendar.tsxDate pickerCustom
datePicker.tsxDate pickerCustom
dateTimePicker.tsxDateTime pickerCustom
color-picker.tsxColor pickerCustom
phone-input/Phone number inputCustom
fileUpload/File uploadCustom

Component Structure

All UI components follow a consistent pattern:

// src/components/ui/button.tsx
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/cn";

// Define variants using Class Variance Authority
const buttonVariants = cva(
// Base classes (always applied)
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
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",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);

// Component props interface
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}

// Component implementation
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";

export { Button, buttonVariants };

Key Patterns:

  1. Class Variance Authority (CVA) - Type-safe variant management
  2. cn() utility - Merges classes intelligently
  3. forwardRef - Supports ref forwarding
  4. asChild prop - Radix UI pattern for composition
  5. TypeScript - Full type safety