Set-up Shadcn UI in Next JS

Apr 21 20248 minutes
Video Tutorial

There are 100s of UI Libraries like Material UI, Chakra UI, Bootstrap, etc. while using these libraries we have to Install whole library and only then we can use components and themes they provide. Shadcn UI is an UI library which uses different approach than this, Shadcn UI is based on Tailwind CSS and Radix UI, its most loved and trending among the developer community with over 50K stars on GItHub.

In Shadcn we dont install the whole library all at once instead we copy the source code for the component we need, this helps to keep our project as light as possible also as we are copying the actual source code of the components we can also modify them as we like.

#PROs and CONs of using Shadcn UI

#PROs

  1. Minimilistic : Each component is very minimislitic and higly customizable.
  2. Accessibility : Shadcn components are fully accessible and follows Web Content Accessibility Guidelines (WCAG) standards.
  3. Easy to Use : We just need to add the component we need and we are ready to use it anywhere in our project.

#CONs

Only con that you may find is that as we are adding components everytime it may feel tedious.

#Getting started with Shadcn UI

Now lets see how we can integrate Shadcn UI in our Next Js app and use its components

#Step 1 : Creating new Next JS app

FIrst of all we need a Next Js app to setup Shadcn UI, you can create a new nextjs app using- following command

npx create-next-app@latest my-app

You can change my-app to whatever name you want to keep for your app.

Press Enter and follow the prompt and configure your app, make sure to choose Tailwind CSS as Shadcn UI depends upon it.

image from tutorend.com

after few seconds a success messege will be shown that means your application has been created successfully.

Navigate to your project directory using cd /my-app

Now run npm run dev to run your application in development mode.

#Step 2 : Initialize dependencies for Shadcn UI

Open new terminal in your project and run npx shadcn-ui@latest init to initialize all Shadcn UI components in your project.

Some prompts will be shown to setup components.json just keep pressing Enter to select default ones.

image from tutorend.com

#Step 3 : Configure Fonts ( Optional )

Shadcn UI by default uses Inter font from google but you can change it to whatever you like, to do that you need to edit code inside root Layout.tsx

image from tutorend.com
layout.tsx

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}

Also import cn funtion from utils and use it to wrap tailwind classes which you’ll write on your components because cn funtion is helper funtion for Tailwind Merge and below is the code of utils.ts

import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Use it like below code in root layout.tsx

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { cn } from "@/lib/utils";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={cn("min-h-screen mx-auto", inter.className)}>{children}</body>
    </html>
  );
}

#4. Adding and using Components from Shadcn

As I already told you unlike other UI libraries we can independently add each components from Shadcn UI in our project.

For example: Lets add a button from Shadcn in our Home page ie. page.tsx

Run following command to add button component in our project

npx shadcn-ui@latest add button

In page.tsx remove default code and write following code to use <Button> component from button

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
export default function Home() {
  return (
    <div className={cn("text-center mx-auto ")}>
      <h1>Home Page</h1>
      <Button >Button</Button>
    </div>
  )
}

Output

image from tutorend.com

In your project you can see a folder called components created by Shadcn insde which you can see a subfolder called ui which is going to hold source code for the components we add in our projet from Shadcn UI, and we can even modify the source code to change look and behaviour of the component.

image from tutorend.com

For example lets see the source code for <Button> components

import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
  "inline-flex items-center justify-center 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",
    },
  }
)
export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean
}
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 }

As you can see in source code we can use varients of the <Button> component

We have 6 varients of <Button>

  1. Default
  2. Destructive
  3. Outline
  4. Secondary
  5. Ghost
  6. Link

To use varient just pass varient prop with any of 6 values

Example: Destructive

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
export default function Home() {
  return (
    <div className={cn("text-center mx-auto ")}>
      <h1>Home Page</h1>
      <Button variant="destructive" >Button</Button>
    </div>
  )
}
image from tutorend.com

#Additional Features

#Theme Editor

While cofiguring Shadcn you might have noticed that we choose from two themes Default and New York configuration for the theme exits in global.css in your project

@tailwind base;
@tailwind components;
@tailwind utilities;
 
@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 0 0% 3.9%;
    --card: 0 0% 100%;
    --card-foreground: 0 0% 3.9%;
 
    --popover: 0 0% 100%;
    --popover-foreground: 0 0% 3.9%;
 
    --primary: 0 0% 9%;
    --primary-foreground: 0 0% 98%;
 
    --secondary: 0 0% 96.1%;
    --secondary-foreground: 0 0% 9%;
 
    --muted: 0 0% 96.1%;
    --muted-foreground: 0 0% 45.1%;
 
    --accent: 0 0% 96.1%;
    --accent-foreground: 0 0% 9%;
 
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 0 0% 98%;
    --border: 0 0% 89.8%;
    --input: 0 0% 89.8%;
    --ring: 0 0% 3.9%;
 
    --radius: 0.5rem;
  }
 
  .dark {
    --background: 0 0% 3.9%;
    --foreground: 0 0% 98%;
 
    --card: 0 0% 3.9%;
    --card-foreground: 0 0% 98%;
 
    --popover: 0 0% 3.9%;
    --popover-foreground: 0 0% 98%;
 
    --primary: 0 0% 98%;
    --primary-foreground: 0 0% 9%;
 
    --secondary: 0 0% 14.9%;
    --secondary-foreground: 0 0% 98%;
 
    --muted: 0 0% 14.9%;
    --muted-foreground: 0 0% 63.9%;
 
    --accent: 0 0% 14.9%;
    --accent-foreground: 0 0% 98%;
 
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 0 0% 98%;
 
    --border: 0 0% 14.9%;
    --input: 0 0% 14.9%;
    --ring: 0 0% 83.1%;
  }
}
 
@layer base {
  * {
    @apply border-border;
  }
  body {
    @apply bg-background text-foreground;
  }
}

As you can see we have configuration for both light and dark mode

Although we can manually customize the theme a better way Shadcn UI provides is Theme Editor where we can visually configure our theme

image from tutorend.com

Customize theme and copy code by clicking on copy code, and replace the theme code in global.css

#Conclusion

We just saw basic usage of Shadcn UI but we can do lot more than just adding a button eg. we can add custom themes, we can create complex layouts like dashboard and all.

To learn more and see all available component visit official documentation here.

Thanks for reading till here, Stay healthy Keep coding 🙂