feat: rss for changelog (#9420)

* feat: init

* fix

* fix
This commit is contained in:
shadcn
2026-01-22 17:43:45 +04:00
committed by GitHub
parent 0ae734bdb2
commit 598f17812d
38 changed files with 1991 additions and 1676 deletions

View File

@@ -79,7 +79,10 @@ export default async function Page(props: {
const doc = page.data
const MDX = doc.body
const neighbours = findNeighbour(source.pageTree, page.url)
const isChangelog = params.slug?.[0] === "changelog"
const neighbours = isChangelog
? { previous: null, next: null }
: findNeighbour(source.pageTree, page.url)
const raw = await page.data.getText("raw")
return (

View File

@@ -0,0 +1,140 @@
import Link from "next/link"
import { Button } from "@/examples/radix/ui/button"
import { mdxComponents } from "@/mdx-components"
import { IconRss } from "@tabler/icons-react"
import { getChangelogPages, type ChangelogPageData } from "@/lib/changelog"
import { absoluteUrl } from "@/lib/utils"
import { OpenInV0Cta } from "@/components/open-in-v0-cta"
export const revalidate = false
export const dynamic = "force-static"
export function generateMetadata() {
return {
title: "Changelog",
description: "Latest updates and announcements.",
openGraph: {
title: "Changelog",
description: "Latest updates and announcements.",
type: "article",
url: absoluteUrl("/docs/changelog"),
images: [
{
url: `/og?title=${encodeURIComponent(
"Changelog"
)}&description=${encodeURIComponent(
"Latest updates and announcements."
)}`,
},
],
},
}
}
export default function ChangelogPage() {
const pages = getChangelogPages()
const latestPages = pages.slice(0, 5)
const olderPages = pages.slice(5)
return (
<div
data-slot="docs"
className="flex scroll-mt-24 items-stretch pb-8 text-[1.05rem] sm:text-[15px] xl:w-full"
>
<div className="flex min-w-0 flex-1 flex-col">
<div className="h-(--top-spacing) shrink-0" />
<div className="mx-auto flex w-full max-w-[40rem] min-w-0 flex-1 flex-col gap-6 px-4 py-6 text-neutral-800 md:px-0 lg:py-8 dark:text-neutral-300">
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<h1 className="scroll-m-24 text-4xl font-semibold tracking-tight sm:text-3xl">
Changelog
</h1>
<Button variant="secondary" size="sm" asChild>
<a href="/rss.xml" target="_blank" rel="noopener noreferrer">
<IconRss />
RSS
</a>
</Button>
</div>
<p className="text-muted-foreground text-[1.05rem] sm:text-base sm:text-balance md:max-w-[80%]">
Latest updates and announcements.
</p>
</div>
<div className="w-full flex-1 pb-16 sm:pb-0">
{latestPages.map((page) => {
const data = page.data as ChangelogPageData
const MDX = page.data.body
return (
<article key={page.url} className="mb-12 border-b pb-12">
<h2 className="font-heading text-xl font-semibold tracking-tight">
{data.title}
</h2>
<div className="prose-changelog mt-6 *:first:mt-0">
<MDX components={mdxComponents} />
</div>
</article>
)
})}
{olderPages.length > 0 && (
<div id="more-updates" className="mb-24 scroll-mt-24">
<h2 className="font-heading mb-6 text-xl font-semibold tracking-tight">
More Updates
</h2>
<ul className="flex flex-col gap-4">
{olderPages.map((page) => {
const data = page.data as ChangelogPageData
return (
<li key={page.url} className="flex items-center gap-3">
<Link
href={page.url}
className="font-medium hover:underline"
>
{data.title}
</Link>
</li>
)
})}
</ul>
</div>
)}
</div>
</div>
</div>
<div className="sticky top-[calc(var(--header-height)+1px)] z-30 ml-auto hidden h-[90svh] w-72 flex-col gap-4 overflow-hidden overscroll-none pb-8 lg:flex">
<div className="h-(--top-spacing) shrink-0"></div>
<div className="no-scrollbar flex flex-col gap-8 overflow-y-auto px-8">
<div className="flex flex-col gap-2 p-4 pt-0 text-sm">
<p className="text-muted-foreground bg-background sticky top-0 h-6 text-xs font-medium">
On This Page
</p>
{latestPages.map((page) => {
const data = page.data as ChangelogPageData
return (
<Link
key={page.url}
href={page.url}
className="text-muted-foreground hover:text-foreground text-[0.8rem] no-underline transition-colors"
>
{data.title}
</Link>
)
})}
{olderPages.length > 0 && (
<a
href="#more-updates"
className="text-muted-foreground hover:text-foreground text-[0.8rem] no-underline transition-colors"
>
More Updates
</a>
)}
</div>
</div>
<div className="hidden flex-1 flex-col gap-6 px-6 xl:flex">
<OpenInV0Cta />
</div>
</div>
</div>
)
}

View File

@@ -57,6 +57,11 @@ export const metadata: Metadata = {
apple: "/apple-touch-icon.png",
},
manifest: `${siteConfig.url}/site.webmanifest`,
alternates: {
types: {
"application/rss+xml": `${siteConfig.url}/rss.xml`,
},
},
}
export default function RootLayout({

View File

@@ -0,0 +1,44 @@
import { NextResponse } from "next/server"
import { getChangelogPages, type ChangelogPageData } from "@/lib/changelog"
import { siteConfig } from "@/lib/config"
export const revalidate = false
export async function GET() {
const pages = getChangelogPages()
const items = pages
.map((page) => {
const data = page.data as ChangelogPageData
const date = page.date?.toUTCString() ?? new Date().toUTCString()
const link = `${siteConfig.url}/docs/${page.slugs.join("/")}`
return ` <item>
<title><![CDATA[${data.title}]]></title>
<link>${link}</link>
<guid>${link}</guid>
<description><![CDATA[${data.description || ""}]]></description>
<pubDate>${date}</pubDate>
</item>`
})
.join("\n")
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>${siteConfig.name} Changelog</title>
<link>${siteConfig.url}</link>
<description>${siteConfig.description}</description>
<language>en-us</language>
<atom:link href="${siteConfig.url}/rss.xml" rel="self" type="application/rss+xml"/>
${items}
</channel>
</rss>`
return new NextResponse(xml, {
headers: {
"Content-Type": "application/rss+xml; charset=utf-8",
},
})
}

View File

@@ -49,7 +49,7 @@ const TOP_LEVEL_SECTIONS = [
href: "/docs/changelog",
},
]
const EXCLUDED_SECTIONS = ["installation", "dark-mode"]
const EXCLUDED_SECTIONS = ["installation", "dark-mode", "changelog"]
const EXCLUDED_PAGES = ["/docs", "/docs/changelog"]
export function DocsSidebar({

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
"javascript",
"blocks",
"figma",
"changelog",
"[Changelog](/docs/changelog)",
"[llms.txt](/llms.txt)",
"legacy"
]

View File

@@ -0,0 +1,478 @@
---
title: June 2023 - New CLI, Styles and more
description: Complete CLI rewrite with new styles, theming options, and more.
date: 2023-06-22
---
I have a lot of updates to share with you today:
- [**New CLI**](#new-cli) - Rewrote the CLI from scratch. You can now add components, dependencies and configure import paths.
- [**Theming**](#theming-with-css-variables-or-tailwind-colors) - Choose between using CSS variables or Tailwind CSS utility classes for theming.
- [**Base color**](#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**](#react-server-components) - Opt out of using React Server Components. The CLI will automatically append or remove the `use client` directive.
- [**Styles**](#styles) - Introducing a new concept called _Style_. A style comes with its own set of components, animations, icons and more.
- [**Exit animations**](#exit-animations) - Added exit animations to all components.
- [**Other updates**](#other-updates) - New `icon` button size, updated `sheet` component and more.
- [**Updating your project**](#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`
```bash
npx shadcn@latest init
```
When you run the `init` command, you will be asked a few questions to configure `components.json`:
```txt showLineNumbers
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.
```json title="components.json" showLineNumbers
{
"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`
```bash
npx 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)
```bash
npx 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:
```bash
npx shadcn diff
```
```txt
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:
```bash
npx shadcn diff alert
```
```diff /pl-12/
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
```tsx /bg-zinc-950/ /text-zinc-50/ /dark:bg-white/ /dark:text-zinc-950/
<div className="bg-zinc-950 dark:bg-white" />
```
To use utility classes for theming set `tailwind.cssVariables` to `false` in your `components.json` file.
```json {6} title="components.json" showLineNumbers
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": false
}
}
```
#### CSS Variables
```tsx /bg-background/ /text-foreground/
<div className="bg-background text-foreground" />
```
To use CSS variables classes for theming set `tailwind.cssVariables` to `true` in your `components.json` file.
```json {6} title="components.json" showLineNumbers
{
"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.
```json {5} title="components.json" showLineNumbers
{
"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.
```json title="components.json" showLineNumbers
{
"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).
<Image
src="/images/style.jpg"
width="716"
height="402"
alt="Default vs New York style"
className="mt-6 overflow-hidden rounded-lg border"
/>
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](https://icons.radix-ui.com).
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.
```json title="components.json" showLineNumbers
{
"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.
<Image
src="/images/style-with-theming.jpg"
width="716"
height="402"
alt="Style with theming"
className="mt-6 overflow-hidden rounded-lg border"
/>
---
### Exit animations
I added exit animations to all components. Click on the combobox below to see the subtle exit animation.
<ComponentPreview name="combobox-demo" className="[&_.preview]:items-start" />
The animations can be customized using utility classes.
---
### Other updates
### Button
- Added a new button size `icon`:
<ComponentPreview name="button-icon" />
### Sheet
- Renamed `position` to `side` to match the other elements.
<ComponentPreview name="sheet-side" />
- Removed the `size` props. Use `className="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.
<Callout className="mt-4">
Note: we are working on a [`diff`](#diff-experimental) command to help you
keep track of upstream updates.
</Callout>
<Steps>
### Add `components.json`
Creating a `components.json` file at the root:
```json title="components.json" showLineNumbers
{
"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`:
```tsx {7} title="components/ui/button.tsx" showLineNumbers
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
1. Replace the content of `sheet.tsx` with the following:
```tsx title="components/ui/sheet.tsx" showLineNumbers
"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,
}
```
2. Rename `position` to `side`
```diff /position/ /side/
- <Sheet position="right" />
+ <Sheet side="right" />
```
</Steps>
### 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.

View File

@@ -0,0 +1,45 @@
---
title: July 2023 - JavaScript
description: JavaScript version of components available via the CLI.
date: 2023-07-04
---
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](/docs/cli).
```txt
Would you like to use TypeScript (recommended)? no
```
To opt-out of TypeScript, you can use the `tsx` flag in your `components.json` file.
```json {10} title="components.json" showLineNumbers
{
"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`:
```json {4} title="jsconfig.json" showLineNumbers
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
```

View File

@@ -0,0 +1,68 @@
---
title: December 2023 - New Components
description: Carousel, Drawer, Pagination, Resizable, Sonner, and CLI updates.
date: 2023-12-22
---
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**](#carousel) - A carousel component with motion, swipe gestures and keyboard support.
- [**Drawer**](#drawer) - A drawer component that looks amazing on mobile.
- [**Pagination**](#pagination) - A pagination component with page navigation, previous and next buttons.
- [**Resizable**](#resizable) - A resizable component for building resizable panel groups and layouts.
- [**Sonner**](#sonner) - The last toast component you'll ever need.
- [**CLI updates**](#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](https://www.embla-carousel.com).
It has support for infinite looping, autoplay, vertical orientation, and more.
<ComponentPreview name="carousel-demo" />
### Drawer
Oh the drawer component. Built on top of [Vaul](https://github.com/emilkowalski/vaul) by [emilkowalski](https://twitter.com/emilkowalski).
Try opening the following drawer on mobile. It looks amazing!
<ComponentPreview name="drawer-demo" />
### Pagination
We've added a pagination component with page navigation, previous and next buttons. Simple, flexible and works with your framework's `<Link />` component.
<ComponentPreview name="pagination-demo" />
### Resizable
Build resizable panel groups and layouts with this `<Resizable />` component.
<ComponentPreview name="resizable-demo-with-handle" />
`<Resizable />` is built using [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels) by [bvaughn](https://github.com/bvaughn). It has support for mouse, touch and keyboard.
### Sonner
Another one by [emilkowalski](https://twitter.com/emilkowalski). The last toast component you'll ever need. Sonner is now availabe in shadcn/ui.
<ComponentPreview name="sonner-demo" />
### 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.
```tsx /tw-/
<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.

View File

@@ -0,0 +1,99 @@
---
title: March 2024 - Introducing Blocks
description: Ready-made components for dashboards and authentication pages.
date: 2024-03-22
---
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)**.
<a href="/blocks">
<Image
src="/images/dashboard-1.jpg"
width="716"
height="430"
alt="Admin dashboard"
className="mt-6 w-full overflow-hidden rounded-lg border dark:hidden"
/>
<Image
src="/images/dashboard-1-dark.jpg"
width="716"
height="430"
alt="Admin dashboard"
className="mt-6 hidden w-full overflow-hidden rounded-lg border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
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.
<a href="/blocks">
<Image
src="/images/dashboard-2.jpg"
width="716"
height="420"
alt="AI Playground"
className="mt-6 w-full overflow-hidden rounded-lg border dark:hidden"
/>
<Image
src="/images/dashboard-2-dark.jpg"
width="716"
height="420"
alt="AI Playground"
className="mt-6 hidden w-full overflow-hidden rounded-lg border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
### 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.
<a href="/blocks">
<Image
src="/images/dashboard-3.jpg"
width="716"
height="420"
alt="Settings Page"
className="mt-6 w-full overflow-hidden rounded-lg border dark:hidden"
/>
<Image
src="/images/dashboard-3-dark.jpg"
width="716"
height="420"
alt="Settings Page"
className="mt-6 hidden w-full overflow-hidden rounded-lg border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
### v0
If you have a [v0](https://v0.dev) account, you can use the **Edit in v0** feature to open the code on v0 for prompting and further generation.
<div className="bg-background mt-6 flex aspect-video w-full items-center justify-center overflow-hidden rounded-lg border shadow-sm">
<svg
viewBox="0 0 40 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="text-foreground h-40 w-40"
>
<path
d="M23.3919 0H32.9188C36.7819 0 39.9136 3.13165 39.9136 6.99475V16.0805H36.0006V6.99475C36.0006 6.90167 35.9969 6.80925 35.9898 6.71766L26.4628 16.079C26.4949 16.08 26.5272 16.0805 26.5595 16.0805H36.0006V19.7762H26.5595C22.6964 19.7762 19.4788 16.6139 19.4788 12.7508V3.68923H23.3919V12.7508C23.3919 12.9253 23.4054 13.0977 23.4316 13.2668L33.1682 3.6995C33.0861 3.6927 33.003 3.68923 32.9188 3.68923H23.3919V0Z"
fill="currentColor"
></path>
<path
d="M13.7688 19.0956L0 3.68759H5.53933L13.6231 12.7337V3.68759H17.7535V17.5746C17.7535 19.6705 15.1654 20.6584 13.7688 19.0956Z"
fill="currentColor"
></path>
</svg>
</div>
That's it. _Looking forward to seeing what you build with Blocks_.

View File

@@ -0,0 +1,25 @@
---
title: March 2024 - Breadcrumb and Input OTP
description: New Breadcrumb and Input OTP components.
date: 2024-03-08
---
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.
<ComponentPreview name="breadcrumb-demo" />
[See more examples](/docs/components/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](https://github.com/guilhermerodz/input-otp) by [@guilherme_rodz](https://twitter.com/guilherme_rodz).
<ComponentPreview name="input-otp-demo" />
[Read the docs](/docs/components/input-otp)
If you have a [v0](https://v0.dev), the new components are available for generation.

View File

@@ -0,0 +1,31 @@
---
title: April 2024 - Lift Mode
description: A new mode for Blocks to lift smaller components for copy and paste.
date: 2024-04-05
---
We're introducing a new mode for [Blocks](/blocks) called **Lift Mode**.
Enable Lift Mode to automatically "lift" smaller components from a block template for copy and paste.
<a href="/blocks">
<Image
src="/images/lift-mode-light.png"
width="1432"
height="1050"
alt="Lift Mode"
className="mt-6 w-full overflow-hidden rounded-lg border dark:hidden"
/>
<Image
src="/images/lift-mode-dark.png"
width="1432"
height="1069"
alt="Lift Mode"
className="mt-6 hidden w-full overflow-hidden rounded-lg border shadow-sm dark:block"
/>
<span className="sr-only">View the blocks library</span>
</a>
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](/blocks) page to try it out.

View File

@@ -0,0 +1,45 @@
---
title: August 2024 - npx shadcn init
description: Complete CLI rewrite with support for all major React frameworks.
date: 2024-08-31
---
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.
1. 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.
2. 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.
3. You can also install remote components using url. `npx shadcn add https://acme.com/registry/navbar.json`.
4. 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`.
5. 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.
6. And a few more updates like better error handling and monorepo support.
You can try the new cli today.
```bash
npx 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**.
```json showLineNumbers {7-13} title="components.json"
{
"$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.

View File

@@ -0,0 +1,11 @@
---
title: October 2024 - React 19
description: shadcn/ui is now compatible with React 19 and Next.js 15.
date: 2024-10-29
---
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](/docs/react-19).

View File

@@ -0,0 +1,13 @@
---
title: October 2024 - Sidebar
description: 25 components to help you build all kinds of sidebars.
date: 2024-10-18
---
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](https://x.com/shadcn/status/1847359896557408461).

View File

@@ -0,0 +1,13 @@
---
title: November 2024 - Icons
description: The new-york style now uses Lucide as the default icon set.
date: 2024-11-06
---
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](https://x.com/shadcn/status/1853902179041702169).

View File

@@ -0,0 +1,18 @@
---
title: December 2024 - Monorepo Support
description: New monorepo support in the CLI.
date: 2024-12-20
---
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](/docs/monorepo).

View File

@@ -0,0 +1,11 @@
---
title: January 2025 - Blocks Community
description: Inviting the community to contribute to the blocks library.
date: 2025-01-14
---
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](/docs/blocks) page to get started.

View File

@@ -0,0 +1,13 @@
---
title: February 2025 - Updated Registry Schema
description: Updated registry schema to support more features.
date: 2025-02-06
---
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

View File

@@ -0,0 +1,22 @@
---
title: February 2025 - Tailwind v4
description: First preview of Tailwind v4 and React 19 support.
date: 2025-02-19
---
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](/docs/tailwind-v4).

View File

@@ -0,0 +1,9 @@
---
title: March 2025 - Cross-framework Route Support
description: The shadcn CLI can now auto-detect your framework and adapts routes for you.
date: 2025-04-09
---
The shadcn CLI can now auto-detect your framework and adapts routes for you.
Works with all frameworks including Laravel, Vite and React Router.

View File

@@ -0,0 +1,17 @@
---
title: April 2025 - MCP
description: Zero-config MCP support for shadcn/ui registry.
date: 2025-04-30
---
We're working on zero-config MCP support for shadcn/ui registry. One command `npx shadcn registry:mcp` to make any registry mcp-compatible.
<Image
src="/images/mcp.jpeg"
width="1432"
height="1050"
alt="Lift Mode"
className="mt-6 w-full overflow-hidden rounded-lg border"
/>
Learn more in the [thread here](https://x.com/shadcn/status/1917597228513853603).

View File

@@ -0,0 +1,11 @@
---
title: March 2025 - shadcn 2.5.0
description: Resolve anywhere - registries can now place files anywhere in an app.
date: 2025-04-26
---
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.

View File

@@ -0,0 +1,11 @@
---
title: May 2025 - New Site
description: Upgraded ui.shadcn.com to Next.js 15.3 and Tailwind v4.
date: 2025-05-30
---
We've upgraded [ui.shadcn.com](https://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.

View File

@@ -0,0 +1,15 @@
---
title: June 2025 - Calendar Component
description: Upgraded Calendar component with React DayPicker and 30+ calendar blocks.
date: 2025-06-06
---
We've upgraded the `Calendar` component to the latest version of [React DayPicker](https://daypicker.dev).
This is a major upgrade and includes a lot of new features and improvements. We've also built a collection of 30+ calendar blocks that you can use to build your own calendar components.
See all calendar blocks in the [Blocks Library](/blocks/calendar) page.
<Image src="/images/calendar-2.png" alt="Calendar" width={676} height={895} />
To upgrade your project to the latest version of the `Calendar` component, see the [upgrade guide](/docs/components/calendar#upgrade-guide).

View File

@@ -0,0 +1,22 @@
---
title: June 2025 - radix-ui Migration
description: A new command to migrate to the new radix-ui package.
date: 2025-06-11
---
We've added a new command to migrate to the new `radix-ui` package. This command will replace all `@radix-ui/react-*` imports with `radix-ui`.
```bash
npx shadcn@latest migrate radix
```
It will automatically update all imports in your `ui` components and install `radix-ui` as a dependency.
```diff showLineNumbers title="components/ui/alert-dialog.tsx"
- import * as AlertDialogPrimitive from "@radix-ui/react-dialog"
+ import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
```
Make sure to test your components and project after running the command.
**Note:** To update imports for newly added components, run the migration command again.

View File

@@ -0,0 +1,22 @@
---
title: July 2025 - Local File Support
description: Initialize projects and add components from local JSON files.
date: 2025-07-07
---
The shadcn CLI now supports local files. Initialize projects and add components, themes, hooks, utils and more from local JSON files.
```bash
# Initialize a project from a local file
npx shadcn init ./template.json
# Add a component from a local file
npx shadcn add ./block.json
```
This feature enables powerful new workflows:
- **Zero setup** - No remote registries required
- **Faster development** - Test registry items locally before publishing
- **Enhanced workflow for agents and MCP** - Generate and run registry items locally
- **Private components** - Keep proprietary components local and private.

View File

@@ -0,0 +1,11 @@
---
title: July 2025 - Universal Registry Items
description: Create registry items that can be distributed to any project.
date: 2025-07-11
---
We've added support for universal registry items. This allows you to create registry items that can be distributed to any project i.e. no framework, no components.json, no tailwind, no react required.
This new registry item type unlocks a lot of new workflows. You can now distribute code, config, rules, docs, anything to any code project.
See the [docs](/docs/registry/examples) for more details and examples.

View File

@@ -0,0 +1,206 @@
---
title: August 2025 - shadcn CLI 3.0 and MCP Server
description: Namespaced registries, advanced authentication, new commands and a completely rewritten registry engine.
date: 2025-08-27
---
We just shipped shadcn CLI 3.0 with support for namespaced registries, advanced authentication, new commands and a completely rewritten registry engine.
### What's New
- [Namespaced Registries](#namespaced-registries) - Install components using `@registry/name` format.
- [Private Registries](#private-registries) - Secure your registry with advanced authentication.
- [Search & Discovery](#search--discovery) - New commands to find and view code before installing.
- [MCP Server](#mcp-server) - MCP server for all registries.
- [Faster Everything](#faster-everything) - Completely rewritten registry resolution.
- [Improved Error Handling](#improved-error-handling) - Better error messages for users and LLMs.
- [Upgrade Guide](#upgrade-guide) - Migration notes for existing users.
### Namespaced Registries
The biggest change in 3.0 is namespaced registries. You can now install components from registries: a community registry, your company's private registry or internal registry, using the `@registry/name` format.
This makes it easier to distribute code across teams and projects.
Configure registries in your `components.json`:
```json title="components.json"
{
"registries": {
"@acme": "https://acme.com/r/{name}.json",
"@internal": {
"url": "https://registry.company.com/{name}",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
```
Then use the `@registry/name` format to install components:
```bash
npx shadcn add @acme/button @internal/auth-system
```
It's completely decentralized. There's no central registrar. Create any namespace you want and organize components however makes sense for your team.
```json title="components.json" showLineNumbers
{
"registries": {
"@design": "https://registry.company.com/create/{name}.json",
"@engineering": "https://registry.company.com/eng/{name}.json",
"@marketing": "https://registry.company.com/marketing/{name}.json"
}
}
```
Components can even depend on resources from different registries. Everything gets resolved and installed automatically from the right sources.
```json title="registry-item.json" showLineNumbers
{
"name": "dashboard",
"type": "registry:block",
"registryDependencies": [
"@shadcn/card", // From default registry
"@v0/chart", // From v0 registry
"@acme/data-table", // From acme registry
"@lib/data-fetcher", // Utility library
"@ai/analytics-prompt" // AI prompt resource
]
}
```
### Private Registries
Need to keep your components private? We've got you covered. Configure authentication with tokens, API keys, or custom headers:
```json title="components.json"
{
"registries": {
"@private": {
"url": "https://registry.company.com/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
```
Your private components stay private. Perfect for enterprise teams with proprietary UI libraries.
We support all major authentication methods: basic auth, bearer token, api key query params and custom headers.
See the [authentication docs](/docs/registry/authentication) for more details.
### Search & Discovery
Three new commands make it easy to find exactly what you need:
1. View items from the registry before installing
```bash
npx shadcn view @acme/auth-system
```
2. Search items from registries
```bash
npx shadcn search @tweakcn -q "dark"
```
3. List all items from a registry
```bash
npx shadcn list @acme
```
Preview components before installing them. Search across multiple registries. See the code and all dependencies upfront.
### MCP Server
<Image
src="/images/mcp.jpeg"
width="1432"
height="1050"
alt="Lift Mode"
className="mt-6 w-full overflow-hidden rounded-lg border"
/>
Back in April, we [introduced](https://x.com/shadcn/status/1917597228513853603) the first version of the MCP server. Since then, we've taken everything we learned and built a better MCP server.
Here's what's new:
- Works with all registries. Zero config
- One command to add to your favorite MCP clients
- We improved the underlying tools
- Better integration with the CLI and registries
- Support for multiple registries in the same project
Add the MCP server to your project:
```bash
npx shadcn@latest mcp init
```
See the [docs](/docs/mcp) for more details.
### Faster Everything
We completely rewrote the registry resolution engine from scratch. It's faster, smarter, and handles even the trickiest dependency trees.
- Up to 3x faster dependency resolution
- Smarter file deduplication and merging
- Better monorepo support out of the box
- Updated `build` command for registry authors
### Improved Error Handling
Registry developers can now provide custom error messages to help guide users (and LLMs) when things go wrong. The CLI displays helpful, actionable errors for common issues:
```txt
Unknown registry "@acme". Make sure it is defined in components.json as follows:
{
"registries": {
"@acme": "[URL_TO_REGISTRY]"
}
}
```
Missing environment variables? The CLI tells you exactly what's needed:
```txt
Registry "@private" requires the following environment variables:
• REGISTRY_TOKEN
Set the required environment variables to your .env or .env.local file.
```
Registry authors can provide custom error messages in their responses to help users and AI agents understand and fix issues quickly.
```txt
Error:
You are not authorized to access the item at http://example.com/r/component.
Message:
[Unauthorized] Your API key has expired. Renew it at https://example.com/api/renew-key.
```
### Upgrade Guide
Here's the best part: there are no breaking changes for users. Your existing `components.json` works exactly the same. All your installed components work exactly the same.
For developers, if you're using the programmatic APIs directly, we've deprecated a few functions in favor of better ones:
- `fetchRegistry` → `getRegistry`
- `resolveRegistryTree` → `resolveRegistryItems`
- Schema moved from `shadcn/registry` to `shadcn/schema` package
```diff
- import { registryItemSchema } from "shadcn/registry"
+ import { registryItemSchema } from "shadcn/schema"
```
That's it. Seriously. Everything else just works.

View File

@@ -0,0 +1,19 @@
---
title: September 2025 - Registry Index
description: An index of open source registries that you can install items from.
date: 2025-09-02
---
We've created an index of open source registries that you can install items from.
You can search, view and add items from the registry index without configuring the `.components.json` file.
They'll be automatically added to your `components.json` file for you.
```bash
npx shadcn add @ai-elements/prompt-input
```
The full list of registries is available at [https://ui.shadcn.com/r/registries.json](https://ui.shadcn.com/r/registries.json).
To add a registry to the index, submit a PR to the `shadcn/ui` repository. See the [registry index documentation](/docs/registry/registry-index) for more details.

View File

@@ -0,0 +1,399 @@
---
title: October 2025 - New Components
description: Spinner, Kbd, Button Group, Input Group, Field, Item, and Empty components.
date: 2025-10-03
---
For this round of components, I looked at what we build every day, the boring stuff we rebuild over and over, and made reusable abstractions you can actually use.
**These components work with every component library, Radix, Base UI, React Aria, you name it. Copy and paste to your projects.**
- [Spinner](#spinner): An indicator to show a loading state.
- [Kbd](#kbd): Display a keyboard key or group of keys.
- [Button Group](#button-group): A group of buttons for actions and split buttons.
- [Input Group](#input-group): Input with icons, buttons, labels and more.
- [Field](#field): One component. All your forms.
- [Item](#item): Display lists of items, cards, and more.
- [Empty](#empty): Use this one for empty states.
### Spinner
Okay let's start with the easiest ones: **Spinner** and **Kbd**. Pretty basic. We all know what they do.
Here's how you render a spinner:
```tsx
import { Spinner } from "@/components/ui/spinner"
```
```tsx
<Spinner />
```
Here's what it looks like:
<ComponentPreview
name="spinner-basic"
className="[&_.preview]:h-[250px] [&_pre]:!h-[250px]"
/>
Here's what it looks like in a button:
<ComponentPreview
name="spinner-button"
className="[&_.preview]:h-[250px] [&_pre]:!h-[250px]"
/>
You can edit the code and replace it with your own spinner.
<ComponentPreview
name="spinner-custom"
className="[&_.preview]:h-[250px] [&_pre]:!h-[250px]"
/>
### Kbd
Kbd is a component that renders a keyboard key.
```tsx
import { Kbd, KbdGroup } from "@/components/ui/kbd"
```
```tsx
<Kbd>Ctrl</Kbd>
```
Use `KbdGroup` to group keyboard keys together.
```tsx showLineNumbers
<KbdGroup>
<Kbd>Ctrl</Kbd>
<Kbd>B</Kbd>
</KbdGroup>
```
<ComponentPreview
name="kbd-demo"
className="[&_.preview]:h-[250px] [&_pre]:!h-[250px]"
/>
You can add it to buttons, tooltips, input groups, and more.
### Button Group
I got a lot of requests for this one: Button Group. It's a container that groups related buttons together with consistent styling. Great for action groups, split buttons, and more.
<ComponentPreview
name="button-group-demo"
className="[&_.preview]:h-[250px] [&_pre]:!h-[250px]"
/>
Here's the code:
```tsx
import { ButtonGroup } from "@/components/ui/button-group"
```
```tsx showLineNumbers
<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>
```
You can nest button groups to create more complex layouts with spacing.
```tsx showLineNumbers
<ButtonGroup>
<ButtonGroup>
<Button>Button 1</Button>
<Button>Button 2</Button>
</ButtonGroup>
<ButtonGroup>
<Button>Button 3</Button>
<Button>Button 4</Button>
</ButtonGroup>
</ButtonGroup>
```
Use `ButtonGroupSeparator` to create split buttons. Classic dropdown pattern.
<ComponentPreview
name="button-group-dropdown"
className="[&_.preview]:h-[250px] [&_pre]:!h-[250px]"
/>
You can also use it to add prefix or suffix buttons and text to inputs.
<ComponentPreview
name="button-group-select"
className="[&_.preview]:h-[250px] [&_pre]:!h-[250px]"
/>
```tsx showLineNumbers
<ButtonGroup>
<ButtonGroupText>Prefix</ButtonGroupText>
<Input placeholder="Type something here..." />
<Button>Button</Button>
</ButtonGroup>
```
### Input Group
Input Group lets you add icons, buttons, and more to your inputs. You know, all those little bits you always need around your inputs.
```tsx
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
} from "@/components/ui/input-group"
```
```tsx showLineNumbers
<InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
</InputGroup>
```
Here's a preview with icons:
<ComponentPreview
name="input-group-icon"
className="[&_.preview]:h-[300px] [&_pre]:!h-[300px]"
/>
You can also add buttons to the input group.
<ComponentPreview
name="input-group-button"
className="[&_.preview]:h-[300px] [&_pre]:!h-[300px]"
/>
Or text, labels, tooltips,...
<ComponentPreview
name="input-group-text"
className="[&_.preview]:h-[350px] [&_pre]:!h-[350px]"
/>
It also works with textareas so you can build really complex components with lots of knobs and dials or yet another prompt form.
<ComponentPreview
name="input-group-textarea"
className="[&_.preview]:h-[450px] [&_pre]:!h-[450px]"
/>
Oh here are some cool ones with spinners:
<ComponentPreview
name="input-group-spinner"
className="[&_.preview]:h-[350px] [&_pre]:!h-[350px]"
/>
### Field
Introducing **Field**, a component for building really complex forms. The abstraction here is beautiful.
It took me a long time to get it right but I made it work with all your form libraries: Server Actions, React Hook Form, TanStack Form, Bring Your Own Form.
```tsx
import {
Field,
FieldDescription,
FieldError,
FieldLabel,
} from "@/components/ui/field"
```
Here's a basic field with an input:
```tsx showLineNumbers
<Field>
<FieldLabel htmlFor="username">Username</FieldLabel>
<Input id="username" placeholder="Max Leiter" />
<FieldDescription>
Choose a unique username for your account.
</FieldDescription>
</Field>
```
<ComponentPreview
name="field-input"
className="[&_.preview]:h-[350px] [&_pre]:!h-[350px]"
/>
It works with all form controls. Inputs, textareas, selects, checkboxes, radios, switches, sliders, you name it. Here's a full example:
<ComponentPreview
name="field-demo"
className="[&_.preview]:h-[850px] [&_pre]:!h-[850px]"
/>
Here are some checkbox fields:
<ComponentPreview
name="field-checkbox"
className="[&_.preview]:h-[500px] [&_pre]:!h-[500px]"
/>
You can group fields together using `FieldGroup` and `FieldSet`. Perfect for
multi-section forms.
```tsx showLineNumbers
<FieldSet>
<FieldLegend />
<FieldGroup>
<Field />
<Field />
</FieldGroup>
</FieldSet>
```
<ComponentPreview
name="field-fieldset"
className="[&_.preview]:h-[500px] [&_pre]:!h-[500px]"
/>
Making it responsive is easy. Use `orientation="responsive"` and it switches
between vertical and horizontal layouts based on container width. Done.
<ComponentPreview
name="field-responsive"
className="[&_.preview]:h-[600px] [&_pre]:!h-[600px]"
/>
Wait here's more. Wrap your fields in `FieldLabel` to create a selectable field group. Really easy. And it looks great.
<ComponentPreview
name="field-choice-card"
className="[&_.preview]:h-[600px] [&_pre]:!h-[600px]"
/>
### Item
This one is a straightforward flex container that can house nearly any type of content.
I've built this so many times that I decided to create a component for it. Now I use it all the time. I use it to display lists of items, cards, and more.
```tsx
import {
Item,
ItemContent,
ItemDescription,
ItemMedia,
ItemTitle,
} from "@/components/ui/item"
```
Here's a basic item:
```tsx showLineNumbers
<Item>
<ItemMedia variant="icon">
<HomeIcon />
</ItemMedia>
<ItemContent>
<ItemTitle>Dashboard</ItemTitle>
<ItemDescription>Overview of your account and activity.</ItemDescription>
</ItemContent>
</Item>
```
<ComponentPreview
name="item-demo"
className="[&_.preview]:h-[300px] [&_.preview]:p-4 [&_pre]:!h-[300px]"
/>
You can add icons, avatars, or images to the item.
<ComponentPreview
name="item-icon"
className="[&_.preview]:h-[300px] [&_.preview]:p-4 [&_pre]:!h-[300px]"
/>
<ComponentPreview
name="item-avatar"
className="[&_.preview]:h-[300px] [&_.preview]:p-4 [&_pre]:!h-[300px]"
/>
And here's what a list of items looks like with `ItemGroup`:
<ComponentPreview
name="item-group"
className="[&_.preview]:h-[500px] [&_.preview]:p-4 [&_pre]:!h-[500px]"
/>
Need it as a link? Use the `asChild` prop:
```tsx showLineNumbers
<Item asChild>
<a href="/dashboard">
<ItemMedia variant="icon">
<HomeIcon />
</ItemMedia>
<ItemContent>
<ItemTitle>Dashboard</ItemTitle>
<ItemDescription>Overview of your account and activity.</ItemDescription>
</ItemContent>
</a>
</Item>
```
<ComponentPreview
name="item-link"
className="[&_.preview]:h-[400px] [&_.preview]:p-4 [&_pre]:!h-[400px]"
/>
### Empty
Okay last one: **Empty**. Use this to display empty states in your app.
```tsx
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyMedia,
EmptyTitle,
} from "@/components/ui/empty"
```
Here's how you use it:
```tsx showLineNumbers
<Empty>
<EmptyMedia variant="icon">
<InboxIcon />
</EmptyMedia>
<EmptyTitle>No messages</EmptyTitle>
<EmptyDescription>You don't have any messages yet.</EmptyDescription>
<EmptyContent>
<Button>Send a message</Button>
</EmptyContent>
</Empty>
```
<ComponentPreview
name="empty-demo"
className="[&_.preview]:h-[400px] [&_.preview]:p-4 [&_pre]:!h-[400px]"
/>
You can use it with avatars:
<ComponentPreview
name="empty-avatar"
className="[&_.preview]:h-[400px] [&_pre]:!h-[400px]"
/>
Or with input groups for things like search results or email subscriptions:
<ComponentPreview
name="empty-input-group"
className="[&_.preview]:h-[450px] [&_pre]:!h-[450px]"
/>
That's it. Seven new components. Works with all your libraries. Ready for your projects.

View File

@@ -0,0 +1,11 @@
---
title: October 2025 - Registry Directory
description: A list of code registries you can browse and pull code and components from.
date: 2025-10-28
---
We just published the Registry Directory: a list of code registries you can browse and pull code and components from.
https://ui.shadcn.com/docs/directory
Built into the CLI. No config required.

View File

@@ -0,0 +1,46 @@
---
title: December 2025 - npx shadcn create
description: Customize everything. Pick your component library, icons, base color, theme, fonts and create your own version of shadcn/ui.
date: 2025-12-12
---
From the very first commit, the goal of shadcn/ui was to make it customizable.
The idea is to give you solid defaults, spacing, color tokens, animations, accessibility, and then let you take it from there. Tweak the code. Add new components. Change the colors. Build your own version.
But somewhere along the way, all apps started looking the same. I guess the defaults were a little _too_ good. My bad.
Today, we're changing that: **npx shadcn create**.
Customize Everything. Pick your component library, icons, base color, theme, fonts and create your own version of shadcn/ui.
We're starting with **5 new visual styles,** designed to help your UI actually feel like _your_ UI.
- **Vega** The classic shadcn/ui look.
- **Nova** Reduced padding and margins for compact layouts.
- **Maia** Soft and rounded, with generous spacing.
- **Lyra** Boxy and sharp. Pairs well with mono fonts.
- **Mira** Compact. Made for dense interfaces.
**This goes beyond theming**.
Your config doesn't just change colors, it rewrites the component code to match your setup. Fonts, spacing, structure, even the libraries you use, everything adapts to your preferences.
The new CLI takes care of it all.
Start with a component library. Choose between Radix or Base UI.
We rebuilt every component for Base UI, keeping the same abstraction.
They are fully compatible with your existing components, even those pulled from remote registries.
When you pull down components, we auto-detect your library and apply the right transformations.
**It's time to build something that doesn't look like everything else.**
Now available for Next.js, Vite, TanStack Start and v0.
<Button asChild>
<Link href="/create" className="mt-6 no-underline!">
Get Started
</Link>
</Button>

View File

@@ -0,0 +1,45 @@
---
title: January 2026 - Base UI Documentation
description: Full documentation for Base UI components.
date: 2026-01-20
---
We've shipped full documentation for Base UI components.
<div className="bg-muted/50 mt-6 flex w-full items-center justify-center rounded-lg border py-32">
<svg width="17" height="24" viewBox="0 0 17 24" className="size-12">
<path
fill="currentColor"
d="M9.5001 7.01537C9.2245 6.99837 9 7.22385 9 7.49999V23C13.4183 23 17 19.4183 17 15C17 10.7497 13.6854 7.27351 9.5001 7.01537Z"
/>
<path
fill="currentColor"
d="M8 9.8V12V23C3.58172 23 0 19.0601 0 14.2V12V1C4.41828 1 8 4.93989 8 9.8Z"
/>
</svg>
</div>
When we launched `npx shadcn create` in December, we introduced the ability to choose between Radix and Base UI as your component library. Today, we're following up with complete documentation for all Base UI components.
### What's New
- **Full Base UI docs** - Every component now has dedicated documentation for Base UI, covering usage, props, and examples.
- **Rebuilt examples** - All component examples have been rebuilt for both Radix and Base UI. Switch between them to see the implementation differences.
- **Side-by-side comparison** - The docs make it easy to compare how components work across both libraries.
### Same Abstraction, Different Primitives
The goal remains the same: give you a consistent API regardless of which primitive library you choose. The components look and behave the same way. Only the underlying implementation changes.
```tsx
// Works the same whether you're using Radix or Base UI.
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"
```
If you're starting a new project, run `npx shadcn create` and pick your preferred library. The CLI handles the rest.
<Button asChild size="sm">
<Link href="/create" className="mt-6 no-underline!">
Try shadcn/create
</Link>
</Button>

View File

@@ -0,0 +1,6 @@
---
title: Changelog
description: Latest updates and announcements.
---
Latest updates and announcements for shadcn/ui.

View File

@@ -0,0 +1,4 @@
{
"title": "Changelog",
"pages": []
}

50
apps/v4/lib/changelog.ts Normal file
View File

@@ -0,0 +1,50 @@
import fs from "fs"
import path from "path"
import fm from "front-matter"
import { source } from "@/lib/source"
export type ChangelogPageData = {
title: string
description?: string
}
export type ChangelogPage = ReturnType<typeof source.getPages>[number] & {
date: Date | null
}
// Reads the date from the frontmatter of a changelog file.
export function getDateFromFile(slugs: string[]) {
const filePath = path.join(
process.cwd(),
"content/docs",
...slugs.slice(0, -1),
`${slugs[slugs.length - 1]}.mdx`
)
try {
const content = fs.readFileSync(filePath, "utf-8")
const { attributes } = fm<{ date?: string | Date }>(content)
if (attributes.date) {
return new Date(attributes.date)
}
} catch {
// File not found or parse error.
}
return null
}
// Gets all changelog pages sorted by date descending.
export function getChangelogPages() {
return source
.getPages()
.filter((page) => page.slugs[0] === "changelog" && page.slugs.length > 1)
.map((page) => ({
...page,
date: getDateFromFile(page.slugs),
}))
.sort((a, b) => {
const dateA = a.date?.getTime() ?? 0
const dateB = b.date?.getTime() ?? 0
return dateB - dateA
})
}