Docs
Tailwind v4 的更新

Tailwind v4 的更新

如何将 shadcn/ui 与 Tailwind v4 结合使用。

它在这里!Tailwind v4 和 React 19。准备好让你试用。它在 CLI 的 canary 版本中可用。你今天就可以开始使用它。

¥It’s here! Tailwind v4 and React 19. Ready for you to try out. It's available in the canary release of the CLI. You can start using it today.

TLDR

如果你使用 Tailwind v4 和 React 19 启动新项目,请使用 canary 版本的命令行:

¥If you're starting a new project with Tailwind v4 and React 19, use the canary version of the command-line:

pnpm dlx shadcn@canary init

有什么新东西

¥What's New

  • CLI(canary)现在可以使用 Tailwind v4 初始化项目。

    ¥The CLI (canary) can now initialize projects with Tailwind v4.

  • 完全支持新的 @theme 指令和 @theme inline 选项。

    ¥Full support for the new @theme directive and @theme inline option.

  • 所有组件都针对 Tailwind v4 和 React 19 进行了更新。

    ¥All components are updated for Tailwind v4 and React 19.

  • 我们已经删除了 forwardRefs 并调整了类型。

    ¥We’ve removed the forwardRefs and adjusted the types.

  • 每个原语现在都有一个 data-slot 属性用于样式设置。

    ¥Every primitive now has a data-slot attribute for styling.

  • 我们已经修复并清理了组件的样式。

    ¥We've fixed and cleaned up the style of the components.

  • 我们弃用 toast 组件,转而使用 sonner

    ¥We're deprecating the toast component in favor of sonner.

  • 按钮现在使用默认光标。

    ¥Buttons now use the default cursor.

  • 我们弃用 default 样式。新项目将使用 new-york

    ¥We're deprecating the default style. New projects will use new-york.

注意:这不会造成任何影响。你现有的使用 Tailwind v3 和 React 18 的应用仍将正常工作。当你添加新组件时,它们仍将保留在 v3 和 React 18 中,直到你升级。只有新项目才从 Tailwind v4 和 React 19 开始。

¥Note: this is non-breaking. Your existing apps with Tailwind v3 and React 18 will still work. When you add new components, they'll still be in v3 and React 18 until you upgrade. Only new projects start with Tailwind v4 and React 19.

接下来会发生什么

¥What's Coming Next

以下内容仍在进行中。我很快就会发布更新。

¥The following is still being worked on. I'll post updates soon.

  • 将颜色迁移到 OKLCH。

    ¥Migrating colors to OKLCH.

  • 修复和改进动画。

    ¥Fix and improve animations.

实时查看

¥See it Live

我在这里整理了一个包含所有更新组件的演示:https://v4.shadcn.com

¥I put together a demo with all the updated components here: https://v4.shadcn.com

查看并测试组件。如果你发现任何错误,请在 GitHub 问题 上发表评论。

¥Take a look and test the components. If you find any bugs, leave a comment on the GitHub issue.

试用

¥Try It Out

你可以使用 CLI 的 canary 版本测试 Tailwind v4 + React 19。

¥You can test Tailwind v4 + React 19 today using the canary release of the CLI.

pnpm dlx shadcn@canary init

我仍在编写文档,但这里有一个测试新项目的快速指南:

¥I'm still working on the docs, but here's a quick guide to testing new projects:

Next.js

  1. 使用 Tailwind v4 和 React 19 开始一个新项目:

    ¥Start a new project with Tailwind v4 and React 19:

pnpm create next-app@canary --tailwind --eslint --typescript --app --no-src-dir
  1. 初始化 shadcn/ui。这将创建你的 components.json 并设置你的 CSS 变量:

    ¥Init shadcn/ui. This will create your components.json and set up your CSS variables:

pnpm dlx shadcn@canary init
  1. 你现在应该能够添加组件:

    ¥You should now be able to add components:

pnpm dlx shadcn@canary add button

Vite

  1. 使用 React 19 创建一个新项目:

    ¥Create a new project with React 19:

pnpm create vite --template=react-ts
  1. 按照官方指南添加 Tailwind CSS:https://tailwind.nodejs.cn/docs/installation/using-vite

    ¥Follow the official guide to add Tailwind CSS: https://tailwind.nodejs.cn/docs/installation/using-vite

  2. tsconfig.json 添加路径别名:

    ¥Add path aliases to tsconfig.json:

tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
  1. tsconfig.app.json 添加路径别名:

    ¥Add path aliases to tsconfig.app.json:

tsconfig.app.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
  1. 安装 @types/node

    ¥Install @types/node:

pnpm add -D @types/node
  1. vite.config.ts 添加解析别名配置:

    ¥Add resolve alias config to vite.config.ts:

vite.config.ts
import path from "path"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
 
export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
})
  1. 初始化 shadcn/ui。这将创建你的 components.json 并设置你的 CSS 变量:

    ¥Init shadcn/ui. This will create your components.json and set up your CSS variables:

pnpm dlx shadcn@canary init
  1. 你现在应该能够添加组件:

    ¥You should now be able to add components:

pnpm dlx shadcn@canary add button

(注意:如果你需要其他框架的帮助,请在下面发表评论。我会更新指南)

¥(Note: If you need help with other frameworks, drop a comment below. I'll update the guide)

升级你的项目

¥Upgrade Your Project

使用 shadcn/ui 的主要优势之一是你最终得到的代码正是你自己编写的代码。没有隐藏的抽象。

¥One of the major advantages of using shadcn/ui is that the code you end up with is exactly what you'd write yourself. There are no hidden abstractions.

这意味着当依赖有新版本时,你只需遵循官方升级路径即可。

¥This means when a dependency has a new release, you can just follow the official upgrade paths.

以下是如何升级你现有的项目(完整文档正在制作中):

¥Here's how to upgrade your existing projects (full docs are on the way):

1. 遵循 Tailwind v4 升级指南

¥ Follow the Tailwind v4 Upgrade Guide

2. 更新你的 CSS 变量

¥ Update your CSS variables

codemod 将迁移你的 CSS 变量作为 @theme 指令下的引用。

¥The codemod will migrate your CSS variables as references under the @theme directive.

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 0 0% 3.9%;
  }
}
 
@theme {
  --color-background: hsl(var(--background));
  --color-foreground: hsl(var(--foreground));
}

这有效。但为了更容易使用颜色和其他变量,我们需要移动 hsl 封装器并使用 @theme inline

¥This works. But to make it easier to work with colors and other variables, we'll need to move the hsl wrappers and use @theme inline.

以下是操作方法:

¥Here's how you do it:

  1. :root.dark 移出 @layer 基础。

    ¥Move :root and .dark out of the @layer base.

  2. 将颜色值封装在 hsl()

    ¥Wrap the color values in hsl()

  3. inline 选项添加到 @theme,即 @theme inline {

    ¥Add the inline option to @theme i.e @theme inline {

  4. @theme 中删除 hsl() 封装器

    ¥Remove the hsl() wrappers from @theme

:root {
  --background: hsl(0 0% 100%); // <-- Wrap in hsl
  --foreground: hsl(0 0% 3.9%);
}
 
dark {
  --background: hsl(0 0% 3.9%); // <-- Wrap in hsl
  --foreground: hsl(0 0% 98%);
}
 
@theme inline {
  --color-background: var(--background); // <-- Remove hsl
  --color-foreground: var(--foreground);
}

此更改使在实用程序类和 CSS 外部访问主题变量变得更加简单,例如使用 JavaScript 中的颜色值。

¥This change makes it much simpler to access your theme variables in both utility classes and outside of CSS for eg. using color values in JavaScript.

3. 更新颜色图表

¥ Update colors for charts

现在主题颜色随 hsl() 一起提供,你可以删除 chartConfig 中的封装器:

¥Now that the theme colors come with hsl(), you can remove the wrapper in your chartConfig:

const chartConfig = {
  desktop: {
    label: "Desktop",
-    color: "hsl(var(--chart-1))",
+    color: "var(--chart-1)",
  },
  mobile: {
    label: "Mobile",
-   color: "hsl(var(--chart-2))",
+   color: "var(--chart-2)",
  },
} satisfies ChartConfig

4. 使用新的 size-* 实用程序

¥ Use new size-* utility

新的 size-* 实用程序(在 Tailwind v3.4 中添加)现在完全受 tailwind-merge 支持。你可以用新的 size-* 实用程序替换 w-* h-*

¥The new size-* utility (added in Tailwind v3.4), is now fully supported by tailwind-merge. You can replace w-* h-* with the new size-* utility:

- w-4 h-4
+ size-4

5. 更新你的依赖

¥ Update your dependencies

pnpm up "@radix-ui/*" cmdk lucide-react recharts tailwind-merge clsx --latest

6. 删除 forwardRef

¥ Remove forwardRef

你可以使用 preset-19 codemod 将 forwardRef 迁移到 props 或手动更新原语。

¥You can use the preset-19 codemod to migrate your forwardRef to props or manually update the primitives.

有关 codemod,请参阅 https://react.nodejs.cn/blog/2024/04/25/react-19-upgrade-guide#typescript-changes

¥For the codemod, see https://react.nodejs.cn/blog/2024/04/25/react-19-upgrade-guide#typescript-changes.

如果你想手动执行此操作,请按照以下步骤操作:

¥If you want to do it manually, here's how to do it step by step:

  1. React.ComponentProps<...> 替换 React.forwardRef<...>

    ¥Replace React.forwardRef<...> with React.ComponentProps<...>

  2. 从组件中删除 ref={ref}

    ¥Remove ref={ref} from the component.

  3. 添加 data-slot 属性。这对于使用 Tailwind 进行样式设置非常有用。

    ¥Add a data-slot attribute. This will come in handy for styling with Tailwind.

  4. 你可以选择转换为命名函数并删除 displayName

    ¥You can optionally convert to a named function and remove the displayName.

之前

¥Before

const AccordionItem = React.forwardRef<
  React.ElementRef<typeof AccordionPrimitive.Item>,
  React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
  <AccordionPrimitive.Item
    ref={ref}
    className={cn("border-b last:border-b-0", className)}
    {...props}
  />
))
AccordionItem.displayName = "AccordionItem"

之后

¥After

function AccordionItem({
  className,
  ...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
  return (
    <AccordionPrimitive.Item
      data-slot="accordion-item"
      className={cn("border-b last:border-b-0", className)}
      {...props}
    />
  )
}

分享你的反馈

¥Share Your Feedback

我们希望你测试这些更新并分享你的反馈!如果你遇到任何奇怪的事情或有建议,请在下面添加评论。

¥We’d love for you to test these updates and share your feedback! If you run into anything weird or have suggestions, add a comment below.