shadcn_ui:2024年最受欢迎的前端项目

·825 字·4 分钟

什么是Shadcn #

image.png

官网: https://ui.shadcn.com/

Github: https://github.com/shadcn-ui/ui

shadcn 文档 https://ui.shadcn.com/docs,可以看到相关介绍:

image_1_.png

  • shadcn/ui 不是组件库,而是可重复使用的组件的集合
  • 开发者可以将其复制粘贴到您的应用中,而不是作为依赖项进行安装

shadcn/ui 目前包括了常用的组件,并且在持续更新中。

image <em>2</em>.png

接下来:我们初始化一个 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 /Users/yangpeng/shadcn-ui-example.

安装shadcn/ui #

npx shadcn@latest init -d

将组件添加到项目 #

npx shadcn@latest add button

在 package.json 中我们并没有找到关于 button 的依赖:

image <em>3</em>.png

而是在 shadcn-ui-example/components/ui 目录下,生成了一个 button.jsx。

image <em>4</em>.png

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>
  );
}

image <em>5</em>.png

我们再添加一个 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 #

image <em>6</em>.png

官网: https://www.radix-ui.com

Github: https://github.com/radix-ui/primitives

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定制主题 #

https://ui.shadcn.com/themes 选择主题然后点击 Copy code 即可:

image <em>7</em>.png


@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结合 #

https://v0.dev 是由 Vercel 推出的一款 AI 驱动的界面设计工具,它通过自然语言描述生成用户界面代码。 https://v0.dev 的核心优势在于其强大的 AI 引擎,能够根据用户的简单文本提示快速生成高质量的 React 代码,并且这些代码与 Shadcn UI 和 Tailwind CSS 完美兼容。 https://v0.dev 的界面设计功能不仅支持实时预览,还允许开发者对生成的代码进行进一步的自定义和优化。开发者可以通过描述需求,让 https://v0.dev 自动更新代码。

天气页面 #

prompt:A weather page

代码:

image <em>8</em>.png

页面:

image <em>9</em>.png

总结 #

Shadcn 基于 Radix UI,使开发者可以轻松调整组件的样式获得开发者青睐,同时由于 Shadcn 的样式需要开发者自行维护,因此在项目迭代过程中可能需要投入更多精力。因此在开发过程中可根据需求自行选择。相信未来 Shadcn 会进一步优化组件性能、丰富组件库,为开发者提供更有力的帮助。