# Tailwind CSS 和 shadcn/ui 的 Cursor 规则

> 强制遵循 Tailwind v4 约定和 shadcn/ui 组件模式的 Cursor 规则，防止代理重复发明已有的基础组件。

**Type:** Rule  
**Tools:** Cursor  
**Stack:** Next.js, TypeScript, Tailwind  
**Updated:** 2026-06-08

---

将此内容粘贴到 `.cursor/rules/tailwind-shadcn.mdc`（或你的项目级 Cursor 规则文件）。Cursor 会在项目打开时自动加载 `.cursor/rules/` 中的所有 `.mdc` 文件。

## Cursor 规则文件

```txt title="Cursor Rules"
# Tailwind CSS + shadcn/ui Rules

## Tailwind conventions
- Use Tailwind CSS v4. Class names follow the v4 API — do NOT use deprecated v3
  class names (e.g. use `shadow-sm` not `drop-shadow-sm` for box shadows on elements).
- All utility classes must be static strings so Tailwind's content scanner can detect
  them. Never build class names with string concatenation or template literals unless
  the full class name is in the source (e.g. `bg-${color}` is forbidden; use a lookup
  object instead).
- Class order: layout → box model → typography → visual (bg, border, shadow) →
  interactive (hover, focus) → responsive breakpoints. Use `prettier-plugin-tailwindcss`
  to enforce this automatically — do not manually reorder.
- Never write custom CSS for spacing, color, or typography that can be expressed with a
  Tailwind utility. Custom CSS lives in `src/styles/` and must be justified by a comment.
- Use `cn()` from `@/lib/utils` to merge conditional classes. Never use `clsx` or
  `classnames` directly elsewhere — they are already re-exported from `cn()`.

## shadcn/ui conventions
- Before creating a new UI component, check `src/components/ui/` for an existing
  shadcn/ui primitive. Use it. Do not re-implement Button, Dialog, Input, Select,
  Tooltip, or any other component that shadcn already provides.
- Add new shadcn components with `npx shadcn@latest add <component>` — never copy-paste
  component source manually from the docs.
- Extend shadcn components by wrapping them, not by editing the file in
  `src/components/ui/` directly. Edits there are overwritten by future `shadcn add` runs.
- Use shadcn's `variant` and `size` props before adding className overrides. If a new
  variant is needed, add it to the component's `cva()` definition in `src/components/ui/`.
- Dark mode is handled by the `dark` class on `<html>`. Never use `prefers-color-scheme`
  media queries alongside shadcn — they conflict with the class strategy.
- Do not install `@radix-ui/*` packages directly. They are transitive dependencies of
  shadcn components; adding them directly risks version mismatches.

## Accessibility
- Every interactive shadcn component must have an accessible label. Use `aria-label`,
  `aria-labelledby`, or a visually-hidden `<span>` — never omit it.
- Icon-only buttons must include `<span className="sr-only">Description</span>`.

## Definition of done
- `bun run build` completes without Tailwind class warnings.
- No `className` strings contain dynamic concatenation (`bg-` + variable).
- No new Radix packages in `package.json` that aren't installed via `shadcn add`.
- Storybook (if present) renders the new/modified component without console errors.
```

## 为何制定这些规则

- **"在创建任何内容之前检查 `src/components/ui/`"** 是 shadcn 项目中价值最高的规则。代理默认会编写定制组件——自定义的 `<Button>`、手动实现的 `<Select>`——这些组件与仓库中已有的 shadcn 基础组件重复。这会浪费 token、导致不一致，并绕过 shadcn 免费提供的无障碍功能。
- **静态类名字符串**是 Tailwind 扫描器的一个硬性约束。代理经常生成 `bg-${color}-500` 这种插值样式，虽然能编译，但在运行时不会产生 CSS，导致仅在生产构建中出现的隐形样式错误。

## 适用场景

- 已经使用 shadcn/ui 和 Tailwind v4 的 Next.js 或 Astro 项目，主要风险是代理重复现有的基础组件或与设计系统冲突。

## 不适用场景

- 使用 CSS Modules、Emotion 或 Styled Components 的项目——Tailwind 类顺序规则不相关，且 `cn()` 不存在。