- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- React Hook Form
- Hover Card
- Input
- Input OTP
- Label
- Menubar
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll-area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
May 2025 - New Site
We've upgraded ui.shadcn.com to Next.js 15.3 and Tailwind v4. The site now uses the upgraded new-york
components.
We've also made some minor design updates to make the site faster and easier to navigate.
This upgrade unlocks a lot of new features that we're working on. More to come.
April 2025 - MCP
We're working on zero-config MCP support for shadcn/ui registry. One command npx shadcn registry:mcp
to make any registry mcp-compatible.

Learn more in the thread here: https://x.com/shadcn/status/1917597228513853603
March 2025 - shadcn 2.5.0
We tagged shadcn 2.5.0 earlier this week. It comes with a pretty cool feature: resolve anywhere.
Registries can now place files anywhere in an app and we’ll properly resolve imports. No need to stick to a fixed file structure. It can even add files outside the registry itself.
On install, we track all files and perform a multi-pass resolution to correctly handle imports and aliases. It’s fast.
March 2025 - Cross-framework Route Support
The shadcn CLI can now auto-detect your framework and adapts routes for you.
Works with all frameworks including Laravel, Vite and React Router.
February 2025 - Tailwind v4
We shipped the first preview of Tailwind v4 and React 19. Ready for you to try out. You can start using it today.
What's New:
- The CLI can now initialize projects with Tailwind v4.
- Full support for the new @theme directive and @theme inline option.
- All components are updated for Tailwind v4 and React 19.
- We’ve removed the forwardRefs and adjusted the types.
- Every primitive now has a data-slot attribute for styling.
- We've fixed and cleaned up the style of the components.
- We're deprecating the toast component in favor of sonner.
- Buttons now use the default cursor.
- We're deprecating the default style. New projects will use new-york.
- HSL colors are now converted to OKLCH.
Read more in the docs.
February 2025 - Updated Registry Schema
We're updating the registry schema to support more features.
Define code as a flat JSON file and distribute it via the CLI.
- Custom styles: bring your own design system, components & tokens
- Extend, override, mix & match components from third-party registries and LLMs
- Install themes, CSS vars, hooks, animations, and Tailwind layers & utilities
January 2025 - Blocks
We are inviting the community to contribute to the blocks library. Share your components and blocks with other developers and help build a library of high-quality, reusable components.
We'd love to see all types of blocks: applications, marketing, products, and more.
See the docs page to get started.
December 2024 - Monorepo Support
Until now, using shadcn/ui in a monorepo was a bit of a pain. You could add components using the CLI, but you had to manage where the components were installed and manually fix import paths.
With the new monorepo support in the CLI, we've made it a lot easier to use shadcn/ui in a monorepo.
The CLI now understands the monorepo structure and will install the components, dependencies and registry dependencies to the correct paths and handle imports for you.
Read more in the docs.
November 2024 - Icons
An update on icons. The new-york style now uses Lucide as the default icon set.
- New projects will use Lucide by default
- No breaking changes for existing projects
- Use the CLI to (optionally) migrate primitives to Lucide
For more info on why we're doing this, see the thread.
October 2024 - React 19
shadcn/ui is now compatible with React 19 and Next.js 15.
We published a guide to help you upgrade your project to React 19.
Read more here.
October 2024 - Sidebar
Introducing sidebar.tsx: 25 components to help you build all kinds of sidebars.
I don't like building sidebars. So I built 30+ of them. All types. Then simplified the core into sidebar.tsx: a strong foundation to build on top of.
It works with Next.js, Remix, Vite & Laravel.
See the announcement here.
August 2024 - npx shadcn init
The new CLI is now available. It's a complete rewrite with a lot of new features and improvements. You can now install components, themes, hooks, utils and more using npx shadcn add
.
This is a major step towards distributing code that you and your LLMs can access and use.
- First up, the cli now has support for all major React framework out of the box. Next.js, Remix, Vite and Laravel. And when you init into a new app, we update your existing Tailwind files instead of overriding.
- A component now ship its own dependencies. Take the accordion for example, it can define its Tailwind keyframes. When you add it to your project, we’ll update your tailwind.config.ts file accordingly.
- You can also install remote components using url.
npx shadcn add https://acme.com/registry/navbar.json
. - We have also improve the init command. It does framework detection and can even init a brand new Next.js app in one command.
npx shadcn init
. - We have created a new schema that you can use to ship your own component registry. And since it has support for urls, you can even use it to distribute private components.
- And a few more updates like better error handling and monorepo support.
You can try the new cli today.
pnpm dlx shadcn init sidebar-01 login-01
Update Your Project
To update an existing project to use the new CLI, update your components.json
file to include import aliases for your components, utils, ui, lib and hooks.
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"tailwind": {
// ...
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
If you're using a different import alias prefix eg ~
, replace @
with your prefix.
April 2024 - Introducing Lift Mode
We're introducing a new mode for Blocks called Lift Mode.
Enable Lift Mode to automatically "lift" smaller components from a block template for copy and paste.


With Lift Mode, you'll be able to copy the smaller components that make up a block template, like cards, buttons, and forms, and paste them directly into your project.
Visit the Blocks page to try it out.
March 2024 - Introducing Blocks
One of the most requested features since launch has been layouts: admin dashboards with sidebar, marketing page sections, cards and more.
Today, we're launching Blocks.


Blocks are ready-made components that you can use to build your apps. They are fully responsive, accessible, and composable, meaning they are built using the same principles as the rest of the components in shadcn/ui.
We're starting with dashboard layouts and authentication pages, with plans to add more blocks in the coming weeks.
Open Source
Blocks are open source. You can find the source on GitHub. Use them in your projects, customize them and contribute back.


Request a Block
We're also introducing a "Request a Block" feature. If there's a specific block you'd like to see, simply create a request on GitHub and the community can upvote and build it.


v0
If you have a v0 account, you can use the Edit in v0 feature to open the code on v0 for prompting and further generation.
That's it. Looking forward to seeing what you build with Blocks.
March 2024 - Breadcrumb and Input OTP
We've added a new Breadcrumb component and an Input OTP component.
Breadcrumb
An accessible and flexible breadcrumb component. It has support for collapsed items, custom separators, bring-your-own routing <Link />
and composable with other shadcn/ui components.
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
export function BreadcrumbDemo() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1">
<BreadcrumbEllipsis className="size-4" />
<span className="sr-only">Toggle menu</span>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/docs/components">Components</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}
Input OTP
A fully featured input OTP component. It has support for numeric and alphanumeric codes, custom length, copy-paste and accessible. Input OTP is built on top of input-otp by @guilherme_rodz.
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp"
export function InputOTPDemo() {
return (
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
)
}
If you have a v0, the new components are available for generation.
December 2023 - New components, CLI and more
We've added new components to shadcn/ui and made a lot of improvements to the CLI.
Here's a quick overview of what's new:
- Carousel - A carousel component with motion, swipe gestures and keyboard support.
- Drawer - A drawer component that looks amazing on mobile.
- Pagination - A pagination component with page navigation, previous and next buttons.
- Resizable - A resizable component for building resizable panel groups and layouts.
- Sonner - The last toast component you'll ever need.
- CLI updates - Support for custom Tailwind prefix and
tailwind.config.ts
.
Carousel
We've added a fully featured carousel component with motion, swipe gestures and keyboard support. Built on top of Embla Carousel.
It has support for infinite looping, autoplay, vertical orientation, and more.
import * as React from "react"
import { Card, CardContent } from "@/components/ui/card"
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel"
export function CarouselDemo() {
return (
<Carousel className="w-full max-w-xs">
<CarouselContent>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index}>
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-4xl font-semibold">{index + 1}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)
}
Drawer
Oh the drawer component 😍. Built on top of Vaul by emilkowalski_.
Try opening the following drawer on mobile. It looks amazing!
"use client"
import * as React from "react"
import { Minus, Plus } from "lucide-react"
import { Bar, BarChart, ResponsiveContainer } from "recharts"
import { Button } from "@/components/ui/button"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
const data = [
{
goal: 400,
},
{
goal: 300,
},
{
goal: 200,
},
{
goal: 300,
},
{
goal: 200,
},
{
goal: 278,
},
{
goal: 189,
},
{
goal: 239,
},
{
goal: 300,
},
{
goal: 200,
},
{
goal: 278,
},
{
goal: 189,
},
{
goal: 349,
},
]
export function DrawerDemo() {
const [goal, setGoal] = React.useState(350)
function onClick(adjustment: number) {
setGoal(Math.max(200, Math.min(400, goal + adjustment)))
}
return (
<Drawer>
<DrawerTrigger asChild>
<Button variant="outline">Open Drawer</Button>
</DrawerTrigger>
<DrawerContent>
<div className="mx-auto w-full max-w-sm">
<DrawerHeader>
<DrawerTitle>Move Goal</DrawerTitle>
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
</DrawerHeader>
<div className="p-4 pb-0">
<div className="flex items-center justify-center space-x-2">
<Button
variant="outline"
size="icon"
className="h-8 w-8 shrink-0 rounded-full"
onClick={() => onClick(-10)}
disabled={goal <= 200}
>
<Minus />
<span className="sr-only">Decrease</span>
</Button>
<div className="flex-1 text-center">
<div className="text-7xl font-bold tracking-tighter">
{goal}
</div>
<div className="text-muted-foreground text-[0.70rem] uppercase">
Calories/day
</div>
</div>
<Button
variant="outline"
size="icon"
className="h-8 w-8 shrink-0 rounded-full"
onClick={() => onClick(10)}
disabled={goal >= 400}
>
<Plus />
<span className="sr-only">Increase</span>
</Button>
</div>
<div className="mt-3 h-[120px]">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={data}>
<Bar
dataKey="goal"
style={
{
fill: "hsl(var(--foreground))",
opacity: 0.9,
} as React.CSSProperties
}
/>
</BarChart>
</ResponsiveContainer>
</div>
</div>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose asChild>
<Button variant="outline">Cancel</Button>
</DrawerClose>
</DrawerFooter>
</div>
</DrawerContent>
</Drawer>
)
}
Pagination
We've added a pagination component with page navigation, previous and next buttons. Simple, flexible and works with your framework's <Link />
component.
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination"
export function PaginationDemo() {
return (
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationNext href="#" />
</PaginationItem>
</PaginationContent>
</Pagination>
)
}
Resizable
Build resizable panel groups and layouts with this <Resizable />
component.
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable"
export function ResizableDemo() {
return (
<ResizablePanelGroup
direction="horizontal"
className="max-w-md rounded-lg border md:min-w-[450px]"
>
<ResizablePanel defaultSize={50}>
<div className="flex h-[200px] items-center justify-center p-6">
<span className="font-semibold">One</span>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={50}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel defaultSize={25}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-semibold">Two</span>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={75}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-semibold">Three</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
)
}
<Resizable />
is built using react-resizable-panels by bvaughn. It has support for mouse, touch and keyboard.
Sonner
Another one by emilkowalski_. The last toast component you'll ever need. Sonner is now availabe in shadcn/ui.
"use client"
import { toast } from "sonner"
import { Button } from "@/components/ui/button"
export function SonnerDemo() {
return (
<Button
variant="outline"
onClick={() =>
toast("Event has been created", {
description: "Sunday, December 03, 2023 at 9:00 AM",
action: {
label: "Undo",
onClick: () => console.log("Undo"),
},
})
}
>
Show Toast
</Button>
)
}
CLI updates
This has been one of the most requested features. You can now configure a custom Tailwind prefix and the cli will automatically prefix your utility classes when adding components.
This means you can now easily add shadcn/ui components to existing projects like Docusaurus, Nextra...etc. A drop-in for your existing design system with no conflict. 🔥
<AlertDialog className="tw-grid tw-gap-4 tw-border tw-bg-background tw-shadow-lg" />
It works with cn
, cva
and CSS variables.
The cli can now also detect tailwind.config.ts
and add the TypeScript version of the config for you.
That's it. Happy Holidays.
July 2023 - JavaScript
This project and the components are written in TypeScript. We recommend using TypeScript for your project as well.
However we provide a JavaScript version of the components, available via the cli.
Would you like to use TypeScript (recommended)? no
To opt-out of TypeScript, you can use the tsx
flag in your components.json
file.
{
"style": "default",
"tailwind": {
"config": "tailwind.config.js",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"rsc": false,
"tsx": false,
"aliases": {
"utils": "~/lib/utils",
"components": "~/components"
}
}
To configure import aliases, you can use the following jsconfig.json
:
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
June 2023 - New CLI, Styles and more
I have a lot of updates to share with you today:
- New CLI - Rewrote the CLI from scratch. You can now add components, dependencies and configure import paths.
- Theming - Choose between using CSS variables or Tailwind CSS utility classes for theming.
- Base color - Configure the base color for your project. This will be used to generate the default color palette for your components.
- React Server Components - Opt out of using React Server Components. The CLI will automatically append or remove the
use client
directive. - Styles - Introducing a new concept called Style. A style comes with its own set of components, animations, icons and more.
- Exit animations - Added exit animations to all components.
- Other updates - New
icon
button size, updatedsheet
component and more. - Updating your project - How to update your project to get the latest changes.
New CLI
I've been working on a new CLI for the past few weeks. It's a complete rewrite. It comes with a lot of new features and improvements.
init
pnpm dlx shadcn@latest init
When you run the init
command, you will be asked a few questions to configure components.json
:
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › › app/globals.css
Do you want to use CSS variables for colors? › no / yes
Where is your tailwind.config.js located? › tailwind.config.js
Configure the import alias for components: › @/components
Configure the import alias for utils: › @/lib/utils
Are you using React Server Components? › no / yes
This file contains all the information about your components: where to install them, the import paths, how they are styled...etc.
You can use this file to change the import path of a component, set a baseColor or change the styling method.
{
"style": "default",
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"rsc": false,
"aliases": {
"utils": "~/lib/utils",
"components": "~/components"
}
}
This means you can now use the CLI with any directory structure including src
and app
directories.
add
pnpm dlx shadcn@latest add
The add
command is now much more capable. You can now add UI components but also import more complex components (coming soon).
The CLI will automatically resolve all components and dependencies, format them based on your custom config and add them to your project.
diff
(experimental)
pnpm dlx shadcn diff
We're also introducing a new diff
command to help you keep track of upstream updates.
You can use this command to see what has changed in the upstream repository and update your project accordingly.
Run the diff
command to get a list of components that have updates available:
pnpm dlx shadcn diff
The following components have updates available:
- button
- /path/to/my-app/components/ui/button.tsx
- toast
- /path/to/my-app/components/ui/use-toast.ts
- /path/to/my-app/components/ui/toaster.tsx
Then run diff [component]
to see the changes:
pnpm dlx shadcn diff alert
const alertVariants = cva(
- "relative w-full rounded-lg border",
+ "relative w-full pl-12 rounded-lg border"
)
Theming with CSS Variables or Tailwind Colors
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
When you add new components, the CLI will automatically use the correct theming methods based on your components.json
configuration.
Utility classes
<div className="bg-zinc-950 dark:bg-white" />
To use utility classes for theming set tailwind.cssVariables
to false
in your components.json
file.
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": false
}
}
CSS Variables
<div className="bg-background text-foreground" />
To use CSS variables classes for theming set tailwind.cssVariables
to true
in your components.json
file.
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
}
}
Base color
You can now configure the base color for your project. This will be used to generate the default color palette for your components.
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": false
}
}
Choose between gray
, neutral
, slate
, stone
or zinc
.
If you have cssVariables
set to true
, we will set the base colors as CSS variables in your globals.css
file. If you have cssVariables
set to false
, we will inline the Tailwind CSS utility classes in your components.
React Server Components
If you're using a framework that does not support React Server Components, you can now opt out by setting rsc
to false
. We will automatically append or remove the use client
directive when adding components.
{
"rsc": false
}
Styles
We are introducing a new concept called Style.
You can think of style as the visual foundation: shapes, icons, animations & typography. A style comes with its own set of components, animations, icons and more.
We are shipping two styles: default
and new-york
(with more coming soon).

The default
style is the one you are used to. It's the one we've been using since the beginning of this project. It uses lucide-react
for icons and tailwindcss-animate
for animations.
The new-york
style is a new style. It ships with smaller buttons, cards with shadows and a new set of icons from Radix Icons.
When you run the init
command, you will be asked which style you would like to use. This is saved in your components.json
file.
{
"style": "new-york"
}
Theming
Start with a style as the base then theme using CSS variables or Tailwind CSS utility classes to completely change the look of your components.

Exit animations
I added exit animations to all components. Click on the combobox below to see the subtle exit animation.
"use client"
import * as React from "react"
import { Check, ChevronsUpDown } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
const frameworks = [
{
value: "next.js",
label: "Next.js",
},
{
value: "sveltekit",
label: "SvelteKit",
},
{
value: "nuxt.js",
label: "Nuxt.js",
},
{
value: "remix",
label: "Remix",
},
{
value: "astro",
label: "Astro",
},
]
export function ComboboxDemo() {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState("")
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[200px] justify-between"
>
{value
? frameworks.find((framework) => framework.value === value)?.label
: "Select framework..."}
<ChevronsUpDown className="opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search framework..." className="h-9" />
<CommandList>
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
{frameworks.map((framework) => (
<CommandItem
key={framework.value}
value={framework.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue)
setOpen(false)
}}
>
{framework.label}
<Check
className={cn(
"ml-auto",
value === framework.value ? "opacity-100" : "opacity-0"
)}
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
)
}
The animations can be customized using utility classes.
Other updates
Button
- Added a new button size
icon
:
import { ChevronRightIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
export function ButtonIcon() {
return (
<Button variant="secondary" size="icon" className="size-8">
<ChevronRightIcon />
</Button>
)
}
Sheet
- Renamed
position
toside
to match the other elements.
"use client"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
const SHEET_SIDES = ["top", "right", "bottom", "left"] as const
type SheetSide = (typeof SHEET_SIDES)[number]
export function SheetSide() {
return (
<div className="grid grid-cols-2 gap-2">
{SHEET_SIDES.map((side) => (
<Sheet key={side}>
<SheetTrigger asChild>
<Button variant="outline">{side}</Button>
</SheetTrigger>
<SheetContent side={side}>
<SheetHeader>
<SheetTitle>Edit profile</SheetTitle>
<SheetDescription>
Make changes to your profile here. Click save when you're done.
</SheetDescription>
</SheetHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="name" className="text-right">
Name
</Label>
<Input id="name" value="Pedro Duarte" className="col-span-3" />
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="username" className="text-right">
Username
</Label>
<Input id="username" value="@peduarte" className="col-span-3" />
</div>
</div>
<SheetFooter>
<SheetClose asChild>
<Button type="submit">Save changes</Button>
</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
))}
</div>
)
}
- Removed the
size
props. UseclassName="w-[200px] md:w-[450px]"
for responsive sizing.
Updating your project
Since we follow a copy and paste approach, you will need to manually update your project to get the latest changes.
Note: we are working on a diff
command to help you
keep track of upstream updates.
Add components.json
Creating a components.json
file at the root:
{
"style": "default",
"rsc": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
Update the values for tailwind.css
and aliases
to match your project structure.
Button
Add the icon
size to the buttonVariants
:
const buttonVariants = cva({
variants: {
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",
},
},
})
Sheet
- Replace the content of
sheet.tsx
with the following:
"use client"
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { cva, type VariantProps } from "class-variance-authority"
import { X } from "lucide-react"
import { cn } from "@/lib/utils"
const Sheet = SheetPrimitive.Root
const SheetTrigger = SheetPrimitive.Trigger
const SheetClose = SheetPrimitive.Close
const SheetPortal = ({
className,
...props
}: SheetPrimitive.DialogPortalProps) => (
<SheetPrimitive.Portal className={cn(className)} {...props} />
)
SheetPortal.displayName = SheetPrimitive.Portal.displayName
const SheetOverlay = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay
className={cn(
"bg-background/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 backdrop-blur-sm",
className
)}
{...props}
ref={ref}
/>
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
const sheetVariants = cva(
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
{
variants: {
side: {
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
bottom:
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
right:
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
},
},
defaultVariants: {
side: "right",
},
}
)
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps
>(({ side = "right", className, children, ...props }, ref) => (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
>
{children}
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
))
SheetContent.displayName = SheetPrimitive.Content.displayName
const SheetHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
)}
{...props}
/>
)
SheetHeader.displayName = "SheetHeader"
const SheetFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
SheetFooter.displayName = "SheetFooter"
const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title
ref={ref}
className={cn("text-foreground text-lg font-semibold", className)}
{...props}
/>
))
SheetTitle.displayName = SheetPrimitive.Title.displayName
const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description
ref={ref}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
))
SheetDescription.displayName = SheetPrimitive.Description.displayName
export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}
- Rename
position
toside
- <Sheet position="right" />
+ <Sheet side="right" />
Thank you
I'd like to thank everyone who has been using this project, providing feedback and contributing to it. I really appreciate it. Thank you 🙏
On This Page
May 2025 - New SiteApril 2025 - MCPMarch 2025 - shadcn 2.5.0March 2025 - Cross-framework Route SupportFebruary 2025 - Tailwind v4February 2025 - Updated Registry SchemaJanuary 2025 - BlocksDecember 2024 - Monorepo SupportNovember 2024 - IconsOctober 2024 - React 19October 2024 - SidebarAugust 2024 - npx shadcn initUpdate Your ProjectApril 2024 - Introducing Lift ModeMarch 2024 - Introducing BlocksOpen SourceRequest a Blockv0March 2024 - Breadcrumb and Input OTPBreadcrumbInput OTPDecember 2023 - New components, CLI and moreCarouselDrawerPaginationResizableSonnerCLI updatesJuly 2023 - JavaScriptJune 2023 - New CLI, Styles and moreNew CLIinit
add
diff
(experimental)Theming with CSS Variables or Tailwind ColorsUtility classesCSS VariablesBase colorReact Server ComponentsStylesThemingExit animationsOther updatesButtonSheetUpdating your projectAdd components.json
ButtonSheetThank you