shadcn/ui: 2024年最受欢迎的前端项目

862 阅读6分钟

在奇舞精选之前发布的一篇文章里盘点了 2024 年最受欢迎的前端项目,其中 shadcn/ui 和去年一样再次成为2024年最热门的项目。这篇文章我们将对 shadcn/ui 进行简单介绍。

什么是Shadcn

官网:ui.shadcn.com/

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

官网:www.radix-ui.com

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对比

特性ShadcnRadix UIAnt 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 会进一步优化组件性能、丰富组件库,为开发者提供更有力的帮助。