在奇舞精选之前发布的一篇文章里盘点了 2024 年最受欢迎的前端项目,其中 shadcn/ui 和去年一样再次成为2024年最热门的项目。这篇文章我们将对 shadcn/ui 进行简单介绍。
什么是Shadcn
Github:github.com/shadcn-ui/u…
在 shadcn 文档 ui.shadcn.com/docs,可以看到相关介绍:
- shadcn/ui 不是组件库,而是可重复使用的组件的集合
- 开发者可以将其复制粘贴到您的应用中,而不是作为依赖项进行安装
shadcn/ui 目前包括了常用的组件,并且在持续更新中。
接下来:我们初始化一个 Next.js 项目,然后使用 shadcn/ui 来理解上面的定义:
初始化Next.js项目
npx create-next-app@latest
Need to install the following packages:
create-next-app@15.1.5
Ok to proceed? (y)
✔ What is your project named? … shadcn-ui-example
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack for `next dev`? … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
Creating a new Next.js app in /shadcn-ui-example.
安装shadcn/ui
npx shadcn@latest init -d
将组件添加到项目
npx shadcn@latest add button
在 package.json 中我们并没有找到关于 button 的依赖:
而是在 shadcn-ui-example/components/ui 目录下,生成了一个 button.jsx。
button.jsx 具体代码如下:
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva } from "class-variance-authority";
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
(<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props} />)
);
})
Button.displayName = "Button"
export { Button, buttonVariants }
可以看到 shadcn/ui 直接把组件代码增加的了我们的项目中。这样的好处显而易见,对比我们使用类似 Ant Design 之类的组件库,如果想要高度定制样式 shadcn/ui 会更容易一些。我们把button添加到页面中运行看一下效果:
"use client";
import { Button } from "@/components/ui/button";
export default function Home() {
return (
<div className="flex w-full h-full items-center justify-center">
<Button>Click me</Button>
</div>
);
}
我们再添加一个 Accordion 组件:
npx shadcn@latest add accordion
"use client"
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
const Accordion = AccordionPrimitive.Root
const AccordionItem = React.forwardRef(({ className, ...props }, ref) => (
<AccordionPrimitive.Item ref={ref} className={cn("border-b", className)} {...props} />
))
AccordionItem.displayName = "AccordionItem"
const AccordionTrigger = React.forwardRef(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}>
{children}
<ChevronDown
className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
const AccordionContent = React.forwardRef(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
这次在 package.json 中添加了 radix-ui 相关依赖:
"@radix-ui/react-accordion": "^1.2.2"
什么是radix-ui
Github:github.com/radix-ui/pr…
Radix 提供了无样式、访问性友好的 React 原子级组件,允许开发者在完全掌控样式的情况下构建自己的设计系统。
Radix 的核心功能
Unstyled
Radix UI 组件本身不带有任何设计或样式,它只提供了基础的结构和交互功能。开发者可以完全自定义样式,适应自己的设计需求。
Stateless
Radix 组件不维护内部状态,而是依赖外部传入的 props 来管理组件的状态。
Accessibility
Radix UI 对可访问性有很高的关注,所有组件都遵循 WCAG(Web Content Accessibility Guidelines)标准。
高度可定制
Radix UI 组件提供了许多灵活的 API,可以根据项目需求进行定制。
原子化
Radix 提供的组件是高度模块化的,可以按需引入。每个组件都只处理单一的功能,避免了将多个功能捆绑到一起的复杂性,增强了代码的复用性和可维护性。
Shadcn、Radix UI、Ant Design对比
特性 | Shadcn | Radix UI | Ant Design |
---|---|---|---|
定位 | 基于 Radix 的功能,提供预置样式 | 原子级组件逻辑,无样式,提供基础功能 | 全功能企业级设计系统 |
可定制性 | 极高,依赖 Tailwind CSS,完全控制样式 | 极高,无内置样式,自定义完全由开发者负责 | 中等,通过主题和配置文件进行定制 |
开发效率 | 较高,灵活但需要搭配 Tailwind CSS | 较低,需花时间自定义样式和集成其他工具 | 很高,组件丰富且开箱即用 |
适用场景 | 需要灵活样式控制的项目,尤其是基于 Tailwind CSS 的应用 | 需要完全定制的应用,适合追求细节和功能控制的场景 | 复杂、正式的企业级系统或快速交付的商业项目 |
Shadcn定制主题
在 ui.shadcn.com/themes 选择主题然后点击 Copy code 即可:
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 72.2% 50.6%;
--primary-foreground: 0 85.7% 97.3%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 72.2% 50.6%;
--radius: 0.5rem;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 72.2% 50.6%;
--primary-foreground: 0 85.7% 97.3%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 72.2% 50.6%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
Shadcn与v0结合
v0.dev 是由 Vercel 推出的一款 AI 驱动的界面设计工具,它通过自然语言描述生成用户界面代码。v0.dev 的核心优势在于其强大的 AI 引擎,能够根据用户的简单文本提示快速生成高质量的 React 代码,并且这些代码与 Shadcn UI 和 Tailwind CSS 完美兼容。v0.dev 的界面设计功能不仅支持实时预览,还允许开发者对生成的代码进行进一步的自定义和优化。开发者可以通过描述需求,让 v0.dev 自动更新代码。
天气页面
prompt:A weather page
代码:
页面:
总结
Shadcn 基于 Radix UI,使开发者可以轻松调整组件的样式获得开发者青睐,同时由于 Shadcn 的样式需要开发者自行维护,因此在项目迭代过程中可能需要投入更多精力。因此在开发过程中可根据需求自行选择。相信未来 Shadcn 会进一步优化组件性能、丰富组件库,为开发者提供更有力的帮助。