默认技术栈:Tailwind v4、`motion/react`、四个图标库与 RSC 隔离
本文所有仓库信息核对日为 2026-08-09,以上游仓库最新内容为准。
taste-skill 默认 skill(文件夹 skills/taste-skill,install name design-taste-frontend,共 1206 行)的 §3 是全篇最”硬”的一节 —— 它直接点名了框架、样式、动画、字体、图标该用什么。很多人扫一眼就当成”作者的技术偏好”,其实这节有明确的触发前提,也有明确的 Override 路径。搞不清这两件事,你要么会在不该套的项目上套,要么会误以为它把你的选型锁死了。
一、先确认这套栈到底什么时候才生效
§3 的标题里就带着条件:它是「当 §2.A 没命中真实设计系统时」的默认架构与约定。
§2.A 是一张需求到官方设计系统的映射表。需求读起来像 Microsoft / 企业 SaaS 就用 @fluentui/react-components 或 @fluentui/web-components,像 IBM 风 B2B 就用 @carbon/react + @carbon/styles,英国公共部门服务用 govuk-frontend,美国公共部门 / 信任优先用 uswds。这张表配了两条硬规则:一条叫 Honesty rule —— 需求命中就安装并使用官方包,不许手抄它的 CSS,也不许引了 token 又覆盖掉 90%;另一条叫 One system per project —— 不许在同一棵树里混 Fluent React 和 Carbon,不许把 shadcn/ui 组件塞进 Material 3 应用。
这张映射表我们另有一篇专门讲,这里只需要记住它对本篇的意义:§3 的默认栈是兜底方案,不是首选方案。如果你的项目是政府服务站,那么按 skill 自己的口径,正确动作是去装 govuk-frontend,而不是拿 Tailwind v4 手搓一套看起来很像的东西。
另外还要记住整份 SKILL.md 开篇那两行原文的定调:适用范围是 landing page、portfolio、redesign,明确排除 dashboard、data table 和多步产品 UI;而且 “Every rule below is contextual. None of it fires automatically.”。连它自己都说没有一条规则自动生效,那 §3 这套栈自然也不是无条件套用。
二、四条默认:框架、样式、动画、字体
§3.A 给的四条默认,逐条抄一遍原文口径:
- 框架:React 或 Next.js,默认走 Server Components(RSC)。
- 样式:Tailwind v4 是默认,v3 仅在既有项目要求时用。v4 有一条具体注意:不要在
postcss.config.js里用tailwindcss插件,改用@tailwindcss/postcss或 Vite 插件。 - 动画:Motion(Framer Motion 的新名),从
motion/react引入,写法是import { motion } from "motion/react"。framer-motion这个包仍作为 legacy alias 可用,但新代码优先motion/react。 - 字体:一律用
next/font(Next.js 项目)或@font-face自托管配font-display: swap。生产环境绝不用<link>引 Google Fonts。
这四条里,样式和动画那两条的价值密度最高,因为它们卡的都是版本迁移期最容易写错的那一处。Tailwind 从 v3 到 v4,PostCSS 插件的包名换了地方;Motion 改名之后,两个 import 路径并存了一段时间。这两条规则做的事,就是把生成时的写法明确钉在新路径上:@tailwindcss/postcss 而不是 tailwindcss 插件,motion/react 而不是 framer-motion。要判断该不该照做也简单——看你项目里 Tailwind 是 v3 还是 v4、动画包装的是哪一个,两处对不上就说明这条规则不适用于你,而不是你写错了。
字体那条要注意它禁的是生产环境用 <link> 引 Google Fonts,给的替代是自托管路线。这一条和其它几条的性质不太一样 —— 它不是审美偏好,落地后是能被真实检查出来的(后面第七节会展开)。
三、RSC 隔离是这套栈的承重墙
§3.A 里跟着框架那条的,是两句大写强调的约束,原文措辞如下:
- RSC SAFETY:全局状态只在 Client Components 里可用;在 Next.js 里要把 provider 包进一个
"use client"组件。 - INTERACTIVITY ISOLATION:任何用到 Motion、滚动监听、指针物理的组件,必须是一个顶部带
'use client'的孤立叶子节点;Server Components 只渲染静态布局。
为什么说这是承重墙?因为 §3 后面所有的动效野心,全靠这条规则兜住。你可以把动画调得很凶,但只要动效组件是孤立叶子,服务端渲染的那部分布局就不会被拖下水。反过来,如果有人图省事在页面根组件顶上写了一行 'use client',这套默认栈的其余部分基本就白配了 —— 整棵树都变成客户端组件,RSC 那部分收益不存在了。
§3.B 讲状态,有一条同样是大写的禁令:NEVER 用 useState 去追踪由用户输入驱动的连续值 —— 鼠标位置、滚动进度、指针物理、磁吸悬停都在这个清单里。替代方案是 Motion 自己的 useMotionValue / useTransform / useScroll。skill 给出的理由写得很直白:useState 每次变化都会重渲染 React 树,在移动端会垮。
这条禁令和上一条是配套的。孤立叶子解决的是”哪些组件进客户端”,useMotionValue 解决的是”进了客户端之后每帧要不要重渲染”。两条都守住,动效才不至于变成性能事故;只守一条,另一条照样会漏。
至于全局状态,§3.B 的口径是:孤立 UI 用本地 useState / useReducer;全局状态只为避免深层 prop drilling 才引入,可选 Zustand、Jotai 或 React context。注意这个”只”字 —— 它把全局状态的正当理由限定到了一个具体场景,而不是笼统地推荐某个状态库。
四、图标:四个允许的库,一个不建议的库
§3.C 给了一份按优先级排的允许清单:
| 优先级 | 包名 |
|---|---|
| 1 | @phosphor-icons/react |
| 2 | hugeicons-react |
| 3 | @radix-ui/react-icons |
| 4 | @tabler/icons-react |
被单独点名不建议的是 lucide-react,附带的 Override 条件写得很清楚:仅在用户明确要求、或项目已经依赖它时可接受。
围绕图标还有三条纪律:绝不手绘 SVG 图标 —— 缺字形就装第二个库或者用原语拼,不许从零画 icon path;一个项目一个图标字体家族 —— 不许 Phosphor 和 Lucide 混在同一棵组件树里;全局统一 strokeWidth,原文给的例子是 1.5 或 2.0。
这三条里,“一个项目一个家族”和 §2.A 那条 One system per project 是同一个思路的两次应用:混用会在细节上露馅,而露馅的位置往往是笔画粗细和圆角处理这类肉眼说不清但一看就不对的地方。“不许手绘 icon path”这条则是直接冲着模型的一个常见行为去的 —— 找不到现成图标时自己编一段 path 数据。
顺带提一句 §3.D 的 Emoji 策略:代码、标记和可见文本里默认不建议用 emoji,用图标库字形替代。Override 是仅当用户明确要 playful / 聊天风 / 社交原生的调性时才允许,且要克制、有意图地用。
五、布局机制里两条不留余地的话
§3.E 先给了一组统一断点:sm 640、md 768、lg 1024、xl 1280、2xl 1536;页面用 max-w-[1400px] mx-auto 或 max-w-7xl 收口。这部分是约定,好理解。
真正值得单拎的是后面两条:
Viewport Stability:全高 Hero 绝不用 h-screen,永远用 min-h-[100dvh]。skill 把原因也写明了 —— 防 iOS Safari 地址栏引起的布局跳动。
Grid over Flex-Math:绝不用复杂 flexbox 百分比数学,原文举的反例就是 w-[calc(33%-1rem)] 这种写法;永远用 CSS Grid,正例是 grid grid-cols-1 md:grid-cols-3 gap-6。
这两条的共同点是:都能给出一个可以机械替换的具体写法。这在整份 SKILL.md 里不算多数 —— 大量规则说的是倾向,而这两条说的是”把 A 换成 B”。对你自己判断该不该照做也友好:你只要问一句”我的项目里有没有 iOS Safari 流量""我的三栏是不是用百分比算出来的”,答案基本就出来了。
六、§3.F:引库之前先看 package.json
§3.F 只有一件事,但标着强制:引入任何第三方库之前先查 package.json;包不存在,就先输出安装命令。原文那句是 Never assume a library exists。
这条针对的是一个非常具体的失败模式:模型直接写了 import { motion } from "motion/react",而项目里根本没装。代码看着完全正常,跑起来直接挂在模块解析上。放在 §3 的末尾很合理 —— 前面刚点了 Tailwind v4、Motion、四个图标库一堆包名,如果没有这条兜底,等于在鼓励模型凭记忆写 import。
七、哪些能变成真检查,哪些只能靠模型听话
这是本篇最想留给你的判断依据。
必须重复一遍前提:SKILL.md 是写给模型看的提示词,不是工程保障。实读这个仓库的顶层目录可以确认:没有 src/、没有 npm 包、没有构建产物,核心资产就是 skills/*/SKILL.md 这些 Markdown 文件。也就是说,装了 skill 之后没有任何东西会在你的项目里执行这些规则。“绝不用 h-screen”是一条指令,不是”装了之后你的代码里就不会出现 h-screen”的结果。
但 §3 有个特点值得利用:它的多数条款指向的是可静态检查的事实。同样是规则文本,落地能力其实分三档:
- 能直接机械校验的:
postcss.config.js里用的是不是@tailwindcss/postcss、代码里有没有h-screen、有没有from "framer-motion"的残留、有没有<link>引 Google Fonts、package.json里 icon 库是不是只有一个。这些都能写成 grep 或者 lint 规则。 - 需要人看一眼才能判的:
'use client'是不是真的落在叶子节点上、全局状态是不是只为解决 prop drilling 而存在。语法能查,意图查不了。 - 只能靠倾向调节的:
strokeWidth全局是否一致、emoji 用得克不克制、Grid 用得合不合理。
所以如果你要把 §3 当成团队规范用,正确姿势是把第一档抄进你自己的构建链,让 skill 只负责第二、三档的倾向。反过来指望装个 skill 就能替代 lint,那是把指令当成了结果。
另外提醒一点:§3 是默认栈,不是 §1 定义、§7 分档的那三个旋钮(DESIGN_VARIANCE / MOTION_INTENSITY / VISUAL_DENSITY)的替代品。§7 里 MOTION_INTENSITY 的 1-3 档明写着”无自动动画,只有 CSS :hover / :active” —— 也就是说,即便你按 §3 装好了 Motion,落到一个低动效读数的项目上,该不用还是不用。装依赖和用依赖是两件事,旋钮那条线我们另有一篇讲。
八、把 Override 路径列在一起
这套栈里所有官方留的口子,集中在这里:
| 默认 | Override 条件 |
|---|---|
| 整套 §3 默认栈 | §2.A 命中真实设计系统时,改用官方包 |
| Tailwind v4 | 既有项目要求 v3 时用 v3 |
motion/react | framer-motion 作为 legacy alias 仍可用 |
| 四个图标库 | 用户明确要求、或项目已依赖时可用 lucide-react |
| 不用 emoji | 用户明确要 playful / 聊天风 / 社交原生调性 |
没列进这张表的那些(min-h-[100dvh]、Grid over Flex-Math、NEVER useState 追连续值、Never assume a library exists、绝不手绘 icon path),在 §3 原文里都没给条件分支。这不代表你不能在自己项目里破例,只代表破例这件事 skill 没替你背书,得你自己拿理由。
最后按惯例交代一次口径:默认 skill 自标 v2 (experimental),README 原文说 “It is still iterating”。上面这些默认值随上游更新会变,真要落进团队规范,请对着仓库当前内容再核一遍。
本文依据 taste-skill 官方仓库(github.com/Leonxlnx/taste-skill)的 README、CHANGELOG、
skills/ 下的 SKILL.md 与 .claude-plugin/ 清单整理,核对日 2026-08-09。
本文内容为仓库文档口径,我们没有安装或运行过其中任何一个 skill,
文中所有规则均为写给模型的提示词约束,不构成对输出结果的保证。
skill 内容随上游更新而变动,默认 skill 当前自标为 v2 (experimental) 且仍在迭代,请以仓库最新内容为准。