# 添加 Tailwind CSS v4 暗色模式的提示

> AI 代理提示：使用 Tailwind CSS v4 CSS 变量和 next-themes 为 Next.js 应用添加系统感知的暗色模式，加载时无闪烁。

**Type:** Prompt  
**Tools:** Cursor, Claude Code, Codex, Windsurf  
**Stack:** Next.js, TypeScript, Tailwind  
**Difficulty:** easy  
**Updated:** 2026-06-08

---

将此提示交给您的代理，以便使用 Tailwind v4 的基于 CSS 变量的主题系统和 `next-themes` 添加暗色模式——防止困扰简单 `localStorage` 实现的未样式内容闪烁。

## 主要提示

```txt title="Main Prompt"
You are working in a Next.js App Router project with TypeScript and Tailwind CSS v4.

Task: add dark mode with system preference detection and a manual toggle.

Requirements:
- Install `next-themes`.
- In `src/app/layout.tsx`, wrap the app in `<ThemeProvider attribute="class" defaultTheme="system" enableSystem>`.
  The `ThemeProvider` is a Client Component — create a wrapper `src/components/Providers.tsx` if
  the root layout must remain a Server Component.
- In `src/styles/global.css`, define CSS custom properties for both themes using the Tailwind v4
  `@theme` directive:
    - Light: `--color-bg: oklch(100% 0 0)`, `--color-text: oklch(9% 0 0)`.
    - Dark (inside `[class="dark"]` selector): override those variables.
  Apply them to the body as `background: var(--color-bg)` and `color: var(--color-text)`.
- Create `src/components/ThemeToggle.tsx` (Client Component) using `useTheme` from `next-themes`.
  It should cycle through light → dark → system on click and show a sun/moon/monitor icon.
  Use Tailwind's built-in `dark:` variant for icon visibility — do NOT use conditional classNames
  based on the `theme` string for icon color.
- Do not use `tailwind.config.ts` `darkMode: 'class'` — that is Tailwind v3 API. In v4, the
  `dark:` variant is class-based by default.
- Do NOT install lucide-react or any icon library — use SVG inline.

Stop and list all planned file changes before writing any code.
```

## 实现说明

- 在 Tailwind v4 中，通过 `dark:` 前缀的暗色模式会自动与 `html` 元素上的 `.dark` 类配合使用——无需配置项。
- `next-themes` 从 `localStorage` 读取已保存的主题，并在首次渲染前设置类，从而防止 FOUC（未样式内容闪烁）。
- `ThemeProvider` 必须在客户端，但根 `layout.tsx` 可以保持服务端，通过将 provider 提取到标记为 `'use client'` 的 `Providers.tsx` 包装组件中。

## 预期文件更改

```txt
src/app/layout.tsx                     (edited — add Providers wrapper)
src/components/Providers.tsx           (new — Client Component with ThemeProvider)
src/components/ThemeToggle.tsx         (new — Client Component)
src/styles/global.css                  (edited — CSS custom properties for light/dark)
package.json                           (edited — add next-themes)
```

## 验收标准

- 首次加载时，如果系统设置为暗色，页面应无闪烁地渲染暗色。
- 切换 ThemeToggle 将循环显示亮色、暗色和系统模式；偏好设置会在重新加载后保留。
- 所有现有的 `dark:` Tailwind 工具无需任何配置更改即可工作。
- `bun run build` 退出码为 0。

## 测试命令

```bash
bun add next-themes
bun run typecheck
bun run build
bun run dev
# open DevTools, set system dark mode, reload — confirm no white flash
# click ThemeToggle three times and confirm cycle: light → dark → system
```

## 常见的 AI 错误

- 向 v4 项目中不存在的 `tailwind.config.ts` 添加 `darkMode: 'class'`。
- 用 `'use client'` 包裹根服务器组件 `layout.tsx`，而不是提取一个 Providers 组件。
- 使用 `theme === 'dark'` 条件渲染而不是 Tailwind 的 `dark:` 变体，导致水合不匹配。
- 忘记在 `ThemeProvider` 上设置 `enableSystem`，导致系统偏好检测无法正常工作。

## 修复提示

```txt title="Fix Prompt"
There's a white flash on load or a hydration mismatch. Fix in order:
1. Ensure `ThemeProvider` has `attribute="class"` and `enableSystem` props.
2. Make sure `Providers.tsx` (not `layout.tsx`) is marked `'use client'`.
3. Remove any `theme === 'dark'` conditional rendering from `ThemeToggle` — use `dark:` Tailwind
   variants instead so the server and client render the same HTML.
Show only the corrected diff.
```