2025 年 6 月 - radix-ui
我们新增了一个命令,用于迁移到新的 radix-ui
包。此命令将把所有 @radix-ui/react-*
导入替换为 radix-ui
。
pnpm dlx shadcn@latest migrate radix
它将自动更新您的 ui
组件中的所有导入,并将 radix-ui
安装为依赖项。
- import * as AlertDialogPrimitive from "@radix-ui/react-dialog"
+ import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
运行命令后,请务必测试您的组件和项目。
注意:要更新新添加组件的导入,请再次运行迁移命令。
2025 年 6 月 - 日历组件
我们已将 Calendar
组件升级到 React DayPicker 的最新版本。
这是一次重大升级,包含了许多新功能和改进。我们还构建了一个包含 30 多个日历区块的集合,您可以使用它们来构建自己的日历组件。
请查看区块库页面,了解所有日历区块。

要将您的项目升级到最新版本的 Calendar
组件,请参阅升级指南。
2025 年 5 月 - 新网站
我们已将 ui.shadcn.com 升级到 Next.js 15.3 和 Tailwind v4。该网站现在使用升级后的 new-york
组件。
我们还进行了一些小的设计更新,以使网站更快、更易于导航。
此次升级解锁了我们正在开发的许多新功能。更多内容即将推出。
2025 年 4 月 - MCP
我们正在为 shadcn/ui 注册表开发零配置 MCP 支持。一个命令 npx shadcn registry:mcp
即可使任何注册表兼容 mcp。

在此处了解更多信息:https://x.com/shadcn/status/1917597228513853603
2025 年 3 月 - shadcn 2.5.0
本周早些时候我们发布了 shadcn 2.5.0。它带有一个非常酷的功能:随处解析。
注册表现在可以在应用程序中的任何位置放置文件,我们将正确解析导入。无需遵循固定的文件结构。它甚至可以在注册表本身之外添加文件。
在安装时,我们会跟踪所有文件并执行多遍解析以正确处理导入和别名。它速度很快。
2025 年 3 月 - 跨框架路由支持
shadcn CLI 现在可以自动检测您的框架并为您调整路由。
适用于所有框架,包括 Laravel、Vite 和 React Router。
2025 年 2 月 - Tailwind v4
我们发布了 Tailwind v4 和 React 19 的第一个预览版。您可以立即开始试用。
新增功能
- CLI 现在可以使用 Tailwind v4 初始化项目。
- 完全支持新的 @theme 指令和 @theme 内联选项。
- 所有组件都已更新,以支持 Tailwind v4 和 React 19。
- 我们移除了 forwardRefs 并调整了类型。
- 每个基元现在都有一个用于样式的 data-slot 属性。
- 我们修复并清理了组件的样式。
- 我们正在弃用 toast 组件,转而使用 sonner。
- 按钮现在使用默认光标。
- 我们正在弃用默认样式。新项目将使用 new-york。
- HSL 颜色现在转换为 OKLCH。
在文档中阅读更多内容。
2025 年 2 月 - 更新注册表 Schema
我们正在更新注册表 schema 以支持更多功能。
将代码定义为平面 JSON 文件并通过 CLI 分发。
- 自定义样式:自带设计系统、组件和令牌
- 扩展、覆盖、混合和匹配来自第三方注册表和 LLM 的组件
- 安装主题、CSS 变量、钩子、动画以及 Tailwind 层和实用程序
2025 年 1 月 - 区块
我们邀请社区为区块库贡献力量。与您的其他开发者分享您的组件和区块,并帮助构建一个高质量、可重用组件的库。
我们希望看到所有类型的区块:应用程序、营销、产品等等。
请参阅文档页面开始。
2024 年 12 月 - Monorepo 支持
到目前为止,在 monorepo 中使用 shadcn/ui 有点麻烦。您可以使用 CLI 添加组件,但必须管理组件的安装位置并手动修复导入路径。
通过 CLI 中的新 monorepo 支持,我们大大简化了在 monorepo 中使用 shadcn/ui 的过程。
CLI 现在可以理解 monorepo 结构,并将组件、依赖项和注册表依赖项安装到正确的路径,并为您处理导入。
在文档中阅读更多内容。
2024 年 11 月 - 图标
关于图标的更新。new-york 样式现在使用 Lucide 作为默认图标集。
- 新项目将默认使用 Lucide
- 现有项目没有破坏性更改
- 使用 CLI(可选)将基元迁移到 Lucide
有关我们为何这样做的更多信息,请参阅帖子。
2024 年 10 月 - React 19
shadcn/ui 现在兼容 React 19 和 Next.js 15。
我们发布了一份指南,帮助您将项目升级到 React 19。
在此处阅读更多:这里。
2024 年 10 月 - 侧边栏
介绍 sidebar.tsx:25 个组件可帮助您构建各种侧边栏。
我不喜欢构建侧边栏。所以我构建了 30 多个。各种类型。然后将核心简化为 sidebar.tsx:一个强大的基础。
它适用于 Next.js、Remix、Vite 和 Laravel。
在此处查看公告:这里。
2024 年 8 月 - npx shadcn init
新的 CLI 现已推出。它是完全重写的,具有许多新功能和改进。您现在可以使用 npx shadcn add
安装组件、主题、钩子、工具等。
这是朝着分发您可以和您的 LLM 访问和使用的代码迈出的重要一步。
- 首先,CLI 现在开箱即用地支持所有主要的 React 框架:Next.js、Remix、Vite 和 Laravel。当您初始化一个新应用程序时,我们会更新您现有的 Tailwind 文件,而不是覆盖它们。
- 组件现在自带其依赖项。以手风琴为例,它可以定义其 Tailwind 关键帧。当您将其添加到项目时,我们会相应地更新您的 tailwind.config.ts 文件。
- 您还可以使用 URL 安装远程组件。
npx shadcn add https://acme.com/registry/navbar.json
。 - 我们还改进了 init 命令。它可以检测框架,甚至可以在一个命令中初始化一个全新的 Next.js 应用程序。
npx shadcn init
。 - 我们创建了一个新的 schema,您可以使用它来发布自己的组件注册表。由于它支持 URL,您甚至可以使用它来分发私有组件。
- 以及一些其他更新,例如更好的错误处理和 monorepo 支持。
您今天就可以试用新的 CLI。
pnpm dlx shadcn init sidebar-01 login-01
更新您的项目
要更新现有项目以使用新的 CLI,请更新您的 components.json
文件,以包含 components、utils、ui、lib 和 hooks 的导入别名。
{
"$schema": "https://ui.shadcn.org.cn/schema.json",
"style": "new-york",
"tailwind": {
// ...
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
如果您使用不同的导入别名前缀(例如 ~
),请将 @
替换为您的前缀。
2024 年 4 月 - 引入“提升模式”
我们为区块引入了一种新模式,名为提升模式。
启用提升模式以自动“提升”区块模板中的较小组件,以便复制和粘贴。


通过提升模式,您将能够复制组成区块模板的较小组件,例如卡片、按钮和表单,并直接将其粘贴到您的项目中。
访问区块页面试用。
2024 年 3 月 - 引入区块
自发布以来,最受关注的功能之一就是布局:带侧边栏的管理员仪表板、营销页面部分、卡片等。
今天,我们发布了区块.


区块是即用型组件,您可以使用它们来构建您的应用程序。它们是完全响应式、可访问和可组合的,这意味着它们是使用与 shadcn/ui 中其他组件相同的原则构建的。
我们从仪表板布局和身份验证页面开始,并计划在未来几周内添加更多区块。
开源
区块是开源的。您可以在 GitHub 上找到源代码。在您的项目中使用它们,自定义它们并贡献回来。


请求区块
我们还引入了“请求区块”功能。如果您想看到某个特定的区块,只需在 GitHub 上创建请求,社区可以投票并构建它。


v0
如果您有 v0 帐户,您可以使用在 v0 中编辑功能在 v0 上打开代码,以便进行提示和进一步生成。
就是这样。期待看到您用区块构建出什么。
2024 年 3 月 - 面包屑和 OTP 输入
我们添加了一个新的面包屑组件和一个 OTP 输入组件。
面包屑
一个可访问且灵活的面包屑组件。它支持折叠项、自定义分隔符、自带路由 <Link />
,并可与其他 shadcn/ui 组件组合使用。
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>
)
}
OTP 输入框
一个功能齐全的 OTP 输入组件。它支持数字和字母数字代码、自定义长度、复制粘贴和可访问性。OTP 输入构建在 input-otp 之上,由 @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>
)
}
如果您有 v0 账户,新的组件可用于生成。
2023 年 12 月 - 新组件、CLI 及更多
我们已向 shadcn/ui 添加了新组件,并对 CLI 进行了许多改进。
以下是新功能的快速概览
- 轮播 - 一个带运动、滑动手势和键盘支持的轮播组件。
- 抽屉 - 一个在移动设备上看起来很棒的抽屉组件。
- 分页 - 一个带页面导航、上一页和下一页按钮的分页组件。
- 可调整大小 - 一个可调整大小的组件,用于构建可调整大小的面板组和布局。
- Sonner - 您唯一需要的 Toast 组件。
- CLI 更新 - 支持自定义 Tailwind 前缀和
tailwind.config.ts
。
轮播
我们添加了一个功能齐全的轮播组件,支持运动、滑动手势和键盘。它基于 Embla Carousel 构建。
它支持无限循环、自动播放、垂直方向等。
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>
)
}
抽屉
哦,这个抽屉组件 😍。由 Vaul 提供,作者是 emilkowalski_。
在手机上尝试打开以下抽屉。它看起来很棒!
"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>
)
}
分页
我们添加了一个分页组件,带有页面导航、上一页和下一页按钮。它简单、灵活,并且与您的框架的 <Link />
组件配合使用。
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 />
组件构建可调整大小的面板组和布局。
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 />
使用 react-resizable-panels 构建,作者是 bvaughn。它支持鼠标、触摸和键盘。
Sonner
这是 emilkowalski_ 的另一个作品。您将永远需要的最后一个 toast 组件。Sonner 现已在 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 更新
这是最受关注的功能之一。您现在可以配置自定义 Tailwind 前缀,CLI 将在添加组件时自动为您的实用程序类添加前缀。
这意味着您现在可以轻松地将 shadcn/ui 组件添加到 Docusaurus、Nextra 等现有项目中。它可以无冲突地集成到您现有的设计系统中。🔥
<AlertDialog className="tw-grid tw-gap-4 tw-border tw-bg-background tw-shadow-lg" />
它适用于 cn
、cva
和 CSS 变量。
CLI 现在还可以检测 tailwind.config.ts
并为您添加 TypeScript 版本的配置。
就这些了。节日快乐。
2023 年 7 月 - JavaScript
本项目和组件均使用 TypeScript 编写。我们建议您的项目也使用 TypeScript。
但是,我们通过 CLI 提供了 JavaScript 版本的组件。
Would you like to use TypeScript (recommended)? no
要选择不使用 TypeScript,您可以在 components.json
文件中使用 tsx
标志。
{
"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"
}
}
要配置导入别名,您可以使用以下 jsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
2023 年 6 月 - 新 CLI、样式及更多
今天,我有很多更新要与您分享
- 新 CLI - 从头重写了 CLI。您现在可以添加组件、依赖项并配置导入路径。
- 主题化 - 选择使用 CSS 变量或 Tailwind CSS 实用程序类进行主题化。
- 基色 - 配置项目的基色。这将用于生成组件的默认调色板。
- React 服务器组件 - 选择不使用 React 服务器组件。CLI 将自动添加或删除
use client
指令。 - 样式 - 引入了一个名为“样式”的新概念。样式带有自己的一组组件、动画、图标等。
- 退出动画 - 为所有组件添加了退出动画。
- 其他更新 - 新增
icon
按钮大小,更新sheet
组件等。 - 更新您的项目 - 如何更新您的项目以获取最新更改。
新 CLI
过去几周我一直在开发一个新的 CLI。它是一个完全重写。它带来了许多新功能和改进。
init
pnpm dlx shadcn@latest init
当您运行 init
命令时,系统会询问您几个问题来配置 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
此文件包含有关您的所有组件的信息:安装位置、导入路径、样式方式等。
您可以使用此文件更改组件的导入路径、设置基色或更改样式方法。
{
"style": "default",
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"rsc": false,
"aliases": {
"utils": "~/lib/utils",
"components": "~/components"
}
}
这意味着您现在可以使用 CLI 和任何目录结构,包括 src
和 app
目录。
add
pnpm dlx shadcn@latest add
add
命令现在功能更强大。您现在可以添加 UI 组件,还可以导入更复杂的组件(即将推出)。
CLI 将自动解析所有组件和依赖项,根据您的自定义配置进行格式化,并将其添加到您的项目中。
diff
(实验性)
pnpm dlx shadcn diff
我们还引入了一个新的 diff
命令,以帮助您跟踪上游更新。
您可以使用此命令查看上游存储库中发生了哪些更改,并相应地更新您的项目。
运行 diff
命令以获取可用更新的组件列表
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
然后运行 diff [component]
查看更改
pnpm dlx shadcn diff alert
const alertVariants = cva(
- "relative w-full rounded-lg border",
+ "relative w-full pl-12 rounded-lg border"
)
使用 CSS 变量或 Tailwind 颜色进行主题化
您可以选择使用 CSS 变量或 Tailwind CSS 实用程序类进行主题化。
当您添加新组件时,CLI 将根据您的 components.json
配置自动使用正确的主题化方法。
实用程序类
<div className="bg-zinc-950 dark:bg-white" />
要使用实用程序类进行主题化,请在您的 components.json
文件中将 tailwind.cssVariables
设置为 false
。
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": false
}
}
CSS 变量
<div className="bg-background text-foreground" />
要使用 CSS 变量进行主题化,请在您的 components.json
文件中将 tailwind.cssVariables
设置为 true
。
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
}
}
基色
您现在可以配置项目的基色。这将用于生成组件的默认调色板。
{
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": false
}
}
在 gray
、neutral
、slate
、stone
或 zinc
之间选择。
如果您的 cssVariables
设置为 true
,我们将在您的 globals.css
文件中将基色设置为 CSS 变量。如果您的 cssVariables
设置为 false
,我们将在您的组件中内联 Tailwind CSS 实用程序类。
React 服务器组件
如果您使用的框架不支持 React 服务器组件,您现在可以通过将 rsc
设置为 false
来选择退出。在添加组件时,我们将自动添加或删除 use client
指令。
{
"rsc": false
}
样式
我们引入了一个名为“样式”的新概念。
您可以将样式视为视觉基础:形状、图标、动画和排版。 样式自带一套组件、动画、图标等。
我们提供两种样式:default
和 new-york
(更多样式即将推出)。

default
样式是您熟悉的样式。它是我们自项目开始以来一直使用的样式。它使用 lucide-react
作为图标,使用 tailwindcss-animate
作为动画。
new-york
样式是一种新样式。它附带了更小的按钮、带阴影的卡片以及来自 Radix Icons 的一组新图标。
当您运行 init
命令时,系统会询问您想使用哪种样式。这会保存在您的 components.json
文件中。
{
"style": "new-york"
}
主题化
以样式为基础,然后使用 CSS 变量或 Tailwind CSS 实用程序类进行主题化,以完全改变组件的外观。

退出动画
我为所有组件添加了退出动画。点击下面的组合框即可看到细微的退出动画。
"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>
)
}
动画可以使用实用程序类进行自定义。
其他更新
按钮
- 新增了一个按钮大小
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>
)
}
侧拉抽屉
- 将
position
重命名为side
以匹配其他元素。
"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>
)
}
- 移除了
size
属性。使用className="w-[200px] md:w-[450px]"
进行响应式尺寸调整。
更新您的项目
由于我们采用复制粘贴的方式,您需要手动更新您的项目以获取最新更改。
注意:我们正在开发一个 diff
命令,以帮助您跟踪上游更新。
添加 components.json
在根目录创建 components.json
文件
{
"style": "default",
"rsc": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
更新 tailwind.css
和 aliases
的值以匹配您的项目结构。
按钮
将 icon
大小添加到 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.tsx
的内容替换为以下内容
"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,
}
- 将
position
重命名为side
- <Sheet position="right" />
+ <Sheet side="right" />
谢谢
我要感谢所有使用本项目、提供反馈并为之做出贡献的人。我非常感谢。谢谢 🙏
本页内容
2025 年 6 月 -radix-ui
2025 年 6 月 - 日历组件2025 年 5 月 - 新网站2025 年 4 月 - MCP2025 年 3 月 - shadcn 2.5.02025 年 3 月 - 跨框架路由支持2025 年 2 月 - Tailwind v42025 年 2 月 - 更新注册表 Schema2025 年 1 月 - 区块2024 年 12 月 - Monorepo 支持2024 年 11 月 - 图标2024 年 10 月 - React 192024 年 10 月 - 侧边栏2024 年 8 月 - npx shadcn init更新您的项目2024 年 4 月 - 引入“提升模式”2024 年 3 月 - 引入区块开源请求区块v02024 年 3 月 - 面包屑和 OTP 输入面包屑OTP 输入2023 年 12 月 - 新组件、CLI 及更多轮播抽屉分页可调整大小SonnerCLI 更新2023 年 7 月 - JavaScript2023 年 6 月 - 新 CLI、样式及更多新 CLIinit
add
diff
(实验性)使用 CSS 变量或 Tailwind 颜色进行主题化实用程序类CSS 变量基色React 服务器组件样式主题化退出动画其他更新按钮侧拉抽屉更新您的项目添加 components.json
按钮侧拉抽屉谢谢