React.js
frontend
Tailwind
Shadcn UI
Shadcn UI provides a unique way to build React interfaces. Instead of installing a typical component library package, you copy beautifully designed and accessible component code directly into your project. This gives you full control over styling and behavior.
Here's a simple example using Shadcn UI's Button component:
Loading...
Shadcn UI stands out because it combines:
npx shadcn-ui@latest add button
), not installed as a dependency. This means no version conflicts and complete freedom to modify.Key Differences from Traditional Libraries:
Feature | Traditional Libraries | Shadcn UI |
---|---|---|
Installation | Package Dependency | Copy-paste code into project |
Updates | Manage versions | Update code manually (if needed) |
Customization | Often Limited | Full code access |
Ownership | External dependency | You own the component code |
Shadcn UI offers a variety of components. You add them to your project as needed using its CLI tool.
Use Cards to structure content sections:
1import { 2 Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle 3} from "@/components/ui/card"; // Assuming default path 4import { Button } from "@/components/ui/button"; 5 6function ProfileCard() { 7 return ( 8 <Card className="w-[350px]"> 9 <CardHeader> 10 <CardTitle>User Profile</CardTitle> 11 <CardDescription>View and manage your information.</CardDescription> 12 </CardHeader> 13 <CardContent> 14 <p>Details about the user go here.</p> 15 </CardContent> 16 <CardFooter className="flex justify-end space-x-2"> 17 <Button variant="outline">Cancel</Button> 18 <Button>Save Changes</Button> 19 </CardFooter> 20 </Card> 21 ); 22}
Create accessible modal dialogs for actions or information:
1import { 2 Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger 3} from "@/components/ui/dialog"; // Assuming default path 4import { Button } from "@/components/ui/button"; 5 6function DeleteConfirmation() { 7 return ( 8 <Dialog> 9 <DialogTrigger asChild> 10 <Button variant="destructive">Delete Account</Button> 11 </DialogTrigger> 12 <DialogContent> 13 <DialogHeader> 14 <DialogTitle>Are you absolutely sure?</DialogTitle> 15 <DialogDescription> 16 This action cannot be undone. This will permanently delete the account. 17 </DialogDescription> 18 </DialogHeader> 19 <DialogFooter> 20 <Button variant="outline">Cancel</Button> 21 <Button variant="destructive">Confirm Deletion</Button> 22 </DialogFooter> 23 </DialogContent> 24 </Dialog> 25 ); 26}
Shadcn UI components integrate smoothly with form libraries like React Hook Form, often using Zod for validation.
1import { zodResolver } from "@hookform/resolvers/zod"; 2import { useForm } from "react-hook-form"; 3import * as z from "zod"; 4import { Button } from "@/components/ui/button"; 5import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; 6import { Input } from "@/components/ui/input"; 7 8// 1. Define validation schema 9const formSchema = z.object({ 10 username: z.string().min(3, "Username must be at least 3 characters.").max(50), 11}); 12 13function ProfileForm() { 14 // 2. Initialize form 15 const form = useForm<z.infer<typeof formSchema>>({ 16 resolver: zodResolver(formSchema), 17 defaultValues: { username: "" }, 18 }); 19 20 // 3. Handle submission 21 function onSubmit(values: z.infer<typeof formSchema>) { 22 console.log("Form submitted:", values); 23 // Add actual submission logic here 24 } 25 26 // 4. Build the form UI 27 return ( 28 <Form {...form}> 29 <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6 w-[350px]"> 30 <FormField 31 control={form.control} 32 name="username" 33 render={({ field }) => ( 34 <FormItem> 35 <FormLabel>Username</FormLabel> 36 <FormControl> 37 <Input placeholder="Enter your username" {...field} /> 38 </FormControl> 39 <FormMessage /> 40 </FormItem> 41 )} 42 /> 43 <Button type="submit">Update Profile</Button> 44 </form> 45 </Form> 46 ); 47}
Customize the look and feel by modifying CSS variables in your global CSS file (e.g., globals.css
or index.css
):
1/* Example from globals.css */ 2@tailwind base; 3@tailwind components; 4@tailwind utilities; 5 6@layer base { 7 :root { 8 --background: 0 0% 100%; /* Light mode background */ 9 --foreground: 222.2 84% 4.9%; /* Light mode text */ 10 /* ... other core variables ... */ 11 --primary: 222.2 47.4% 11.2%; 12 --primary-foreground: 210 40% 98%; 13 /* ... more variables for borders, inputs, rings etc. ... */ 14 --radius: 0.5rem; /* Border radius */ 15 } 16 17 .dark { 18 --background: 222.2 84% 4.9%; /* Dark mode background */ 19 --foreground: 210 40% 98%; /* Dark mode text */ 20 /* ... override other variables for dark mode ... */ 21 --primary: 210 40% 98%; 22 --primary-foreground: 222.2 47.4% 11.2%; 23 /* ... */ 24 } 25}
Since you own the component code, you can directly edit the files (usually within a components/ui
directory) to change structure, styles, or behavior. For example, adding a custom variant to the Button:
1// Inside components/ui/button.jsx (example path) 2import { cva } from "class-variance-authority"; 3 4export const buttonVariants = cva( 5 "inline-flex items-center justify-center ...", // Base classes 6 { 7 variants: { 8 variant: { 9 default: "bg-primary text-primary-foreground hover:bg-primary/90", 10 destructive: "...", 11 outline: "...", 12 secondary: "...", 13 ghost: "...", 14 link: "...", 15 // Add your custom variant 16 success: "bg-green-600 text-white hover:bg-green-700", 17 }, 18 size: { 19 default: "h-10 px-4 py-2", 20 sm: "h-9 rounded-md px-3", 21 lg: "h-11 rounded-md px-8", 22 icon: "h-10 w-10", 23 }, 24 }, 25 defaultVariants: { 26 variant: "default", 27 size: "default", 28 }, 29 } 30); 31 32// ... rest of the Button component ...
components/ui
) separate from your custom application components.Shadcn UI offers a pragmatic approach for React developers wanting control and customization without building everything from scratch. By leveraging Tailwind CSS and Radix UI, it provides a foundation for beautiful, accessible, and maintainable user interfaces directly within your project codebase.