小声 BB + 免责声明
最近开了一个短剧会员,纯娱乐,无脑短剧,真好看,真上头! 不参加任何活动,不代表任何技术立场!纯娱乐!
第一章:我,被踢出了 UI 团队
那天,空气湿热,蝉鸣聒噪,宋执坐在工位上,刚刚提交了一次 PR。他喝了口冰美式,盯着 GitHub Actions 成功的小绿勾,脸上浮现出一丝成就感。
这是他为公司主站重构的新组件——一个动态响应式的 Button 模块,使用 tailwind-variants 组合出了 12 种状态,集成了焦点环、loading 反馈、icon 支持,还做了无障碍键盘操作支持。
feat(button): add variants, dark mode, and full a11y support
commit message 格式依旧规范,是他当初要求团队统一的标准。每个组件都要有文档、预览图、Storybook 示例、ARIA 验证,甚至配套截图测试。
他沉浸在短暂的满足感中,直到 HR 拿着文件夹来到他面前:
“宋执,可以来会议室聊一下吗?”
会议室里冷气刺骨。墙上贴着 Agile 流程图,但现在什么都不敏捷。
HR 没有拐弯抹角:“公司决定解散 UI 技术中台,把你这个方向合并进 AI 视觉体验团队。”
宋执一愣:“合并是什么意思?我带的组件库团队怎么办?”
产品总监接过话,冷静地说:“新团队会用更智能的方案。AI 生成组件、设计图直接转代码、无需维护手写组件库,组件抽象这种事我们认为是冗余的。”
“你做的东西,太‘工程化’了。我们需要的是‘产品感’和‘设计感’。”
宋执看着那封调岗信,突然意识到自己像极了早期的 jQuery,曾经辉煌,但终究被当作“过时的遗产”。
整个 UI 团队被打包进“视觉体验小组”,技术栈从 React 切换到一个不知名的 DSL,组件通过 YAML 生成,每次改动都要重新跑 prompt。
他的 Button 组件,被评审为“写得太细、太重、不够灵活”。
连变量名 button--variant-danger 都被嫌弃不够美观,要求改成 btnRed.
这不是技术问题,这是政治。
离开会议室的时候,宋执默默看了一眼公司楼下的招牌灯箱,那个他参与设计的 logo 上还残留着他亲手调过的 box-shadow 值。他笑了笑,自嘲地想:
“连阴影都有人维护,程序员却说换就换。”
他回到工位,发现邮箱权限被撤销,Figma 项目中他的头像变成了“已离职成员”,而那套他花了整整一年构建的组件库,已经被新组踢出了项目依赖。
曾经的同事们避而不谈,唯有一个 UI 实习生私信他说:“哥,我一直在偷偷用你那套按钮,真的比他们那 AI 自动生成的好用多了。”
宋执没回。他关掉 VSCode,把自己维护的组件库代码从 GitHub clone 到本地,又静静打开 README.md,最后一行写着:
“为那些相信规范、抽象、可复用性和代码美学的开发者。”
他起身走出公司,阳光晃得他睁不开眼,地铁站旁边贴着巨大的广告牌:
“AI 将彻底改变前端开发,你准备好了吗?”
宋执站在那里,听着人群走过的脚步,突然意识到:
如果前端开发真的会被替代,那第一个下线的,不会是懂语义化和无障碍设计的人,而是那些放弃原则随波逐流的临时工。
他在心里默默说了一句话:
“你可以不要我,但我不会不要组件。”
第二章:重新开始,从 npm init 开始
夜色沉沉,宋执窝在出租屋的飘窗前,笔记本电脑的屏幕亮度开到最大,映在他脸上泛着一点冷白的光。
他刚刚离开公司,被“技术中台合并”的荒谬理由扫地出门。两年,他从零搭建的组件库被打包进“AI UI 模板引擎”,说是未来的趋势,但他知道,那根本不是趋势——那只是省事,是“用生成式代替思考”的懒惰。
桌上是一杯泡得过头的速溶咖啡,键盘旁边是他从工位上带走的便签纸,上面写着他最喜欢的一句代码哲学:
“组件不是样式的组合,是语义的抽象。”
他打开终端,敲下熟悉的命令:
npm init -y
那一刻,他感觉自己像是从荒原中徒步归来的术士,重新召唤出了第一个魔法圈。 他给项目起名叫:unicorn-ui。 他给项目起名叫:unicorn-ui。
为什么叫这个名字?
他也说不清。
可能是想要一点“稀有”“纯净”“不屈”的意味。
他用 Vite 搭建了项目骨架,集成了 TypeScript 和 Tailwind。选择 tailwind-variants 作为样式工具,因为相比传统 BEM 或 class 合并器,这套组合方式更灵活,也更符合现代前端的函数式审美。
项目结构清晰利落:
src/
├── components/
│ ├── Button.tsx
│ ├── Input.tsx
│ └── Tooltip.tsx
├── utils/
│ └── cn.ts
└── index.ts
第一步,他重写按钮组件。他没有复制以前的代码,而是从零写起。
// Button.tsx
import { cva } from 'tailwind-variants'
import { cn } from '../utils/cn'
const buttonVariants = cva(
'inline-flex items-center justify-center font-medium transition-colors focus:outline-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-zinc-900 text-white hover:bg-zinc-800',
outline: 'border border-zinc-300 text-zinc-700 hover:bg-zinc-100',
ghost: 'bg-transparent hover:bg-zinc-100',
},
size: {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4 text-base',
lg: 'h-12 px-6 text-lg',
},
},
defaultVariants: {
variant: 'default',
size: 'md',
},
}
)
export function Button({ className, variant, size, ...props }) {
return (
<button className={cn(buttonVariants({ variant, size }), className)} {...props} />
)
}
看着组件自动在 Storybook 里渲染出来的那一刻,他有种说不出的满足。
没有老板、没有会审、没有设计师拍脑袋决定 spacing 和圆角,只有自己和代码。****
他写了 README,添加了完整的 props 文档,甚至配置了 typedoc 生成静态 API 页面。
然后,他发布了第一个版本。
npm publish --access public
版本号是 0.0.1,他知道这个组件库还很弱小,但——
他给了它一个灵魂。
第二天醒来,他在 GitHub 收到一个陌生网友开了个 issue:
“Your Button component has very clean structure. Could I help translate the docs into Spanish?”
宋执愣住了。
这只是一个简简单单的按钮组件,一个还没人用的早期版本。居然已经有人主动来贡献翻译?
那一刻他意识到,他不是在战斗,而是在播种。****
他决定写一篇文章,发在 Dev.to 和国内的掘金上,标题是:
“我被AI组件库淘汰后,重写了自己的UI系统”
文章第一段写的是他离职的故事,后面是他对组件设计哲学的理解——包括:
-
为什么不要滥用 auto layout
-
为什么组件应先定义语义,再定义样式
-
为什么 aria-* 和键盘交互应该成为默认支持
这篇文章在短短 12 小时内被转发了上百次,GitHub 项目 star 从 1 变成了 87。
有 React 社区的开发者说:“这个库虽然简单,但比那些自动生成的组件更可控。”
也有人私信他说:“我打算从 Chakra UI 迁移到你的按钮体系。”
宋执心中一震。
他意识到自己曾经努力维护的东西——那些“很工程化”的事情,那些“过度关注细节”的坚持,其实并没有错。
只是在体制里,它们不值钱。
而在开源世界里,这些,才是信仰。
但问题也来了。
没有设计师。
没有 UX。
宋执一个人,要承担组件样式、视觉一致性、交互体验,还得做动画细节,处理兼容性 bug。
他开始焦虑。
为了解决这个问题,他灵感一闪,干脆建立一套“无设计者的设计系统流程”,他称之为:
Developer-first UI System
原则如下:
-
所有颜色必须使用语义命名,如 primary, accent, destructive,内部统一映射 HSL。
-
组件交互基于 keyboard-first:先考虑键盘可用性,再考虑鼠标与触屏。
-
动画必须基于 framer-motion 的 spring 动效,禁止使用硬切。
-
所有 spacing 单位统一用 Tailwind rem 体系,不使用任意 px 值。
他甚至写了个生成器,叫 gen-token.ts,自动从 tokens.json 生成 CSS variables、Tailwind config、Figma tokens 三套标准。
这个设计系统,从代码出发,反向约束了设计。
有人笑他:“这能叫设计系统?”
他笑着回了一句:
“你可以不认同,但你会用。”
深夜,窗外蟋蟀聒噪。
宋执坐在屏幕前,Review 一个刚刚来自印度开发者的 PR——
对方为 Tooltip 组件补充了 delay 参数,还修复了在 iOS Safari 中 pointer-events 的问题。
他点了 Approve,心中泛起暖流。
是的,他现在可能什么都没有。
但他有一件东西,越来越完整,越来越强大。
他自己写的组件库。
第三章:组件库爆火后,我成了“AI UI 的反对派”
距离宋执发布 unicorn-ui 的第一个版本已经过去了 23 天。
GitHub Star 数:1427
下载量:13,904
社区贡献者:27
Issue 数:38(其中 33 已关闭)
在没有任何流量支持、没有开源基金赞助、没有“设计指导”的前提下,这个小而美的组件库正逐渐走进更多开发者的视野。
也正因如此,主流的“AI UI”团队开始注意到他。
注意到他,并开始——讽刺他。
那天晚上,宋执刷着前端社区的直播频道,看到了熟悉的公司 LOGO。
是他前公司主办的一场“AI UI 智能组件设计”直播活动,主持人正是当初把他踢出团队的设计 VP 兼“AI UI 布道师”——许凡。
直播标题:
“传统组件库的尽头?AI 生成的 UI 编码新范式”
标题下方还有个讽刺意味极强的小副标题:
“评评那些还在手写 Button 的浪漫主义者”
宋执点进去,没过十分钟,就听到他的名字被点出来。
许凡笑着说:“比如最近有个很火的开源项目,叫 unicorn-ui,很努力地用 tailwind 和 TS 去写组件,还坚持什么 accessibility 和 variants。”
旁边的产品经理附和:“我看了他的 Tooltip 实现,光一个延迟动画就手搓了三百多行代码,现在谁还这么搞?”
许凡转向镜头:“我们 AI UI 系统只需要一句 prompt,就能生成同样的按钮,带 hover、dark mode、animation。人写的东西,终究会被模型替代。”
直播弹幕一边倒:
- “写那么复杂干啥,直接 prompt 多快”
- “哥们以为自己在写操作系统呢?”
- “代码洁癖吧,活该脱离团队”
只有零星几个弹幕说:“但他那个 Button 的结构确实更清晰”、“至少他的组件能读懂逻辑”
宋执没说话,他退出了直播。
但他把那段直播录了下来,剪成了一段三分钟的视频,配上标题:
“我手写了一个组件库,被说是浪漫主义者。”
然后,他把它发到了 B 站、抖音和 YouTube Shorts。
视频发出的第二天,他的邮箱被关注提醒炸满。
那条视频短短两天在全网播放量超过 30 万,评论上千。
人们突然意识到,原来在“AI 统治一切”的当下,还有人在用代码坚持架构思维、组件哲学和用户体验本质。
甚至还有某知名前端技术号发文支持他:
“我们不反对 AI 参与 UI 生成,但前端开发不是按钮堆叠游戏,而是交互、抽象、维护成本与工程边界的艺术。”
网友给他贴了个标签:
“代码理想主义者”
有人嘲笑,有人崇拜,但更多人,是好奇:
他,到底写了什么样的组件?
【社区的反击:fork storm】
就在直播第四天,unicorn-ui 项目迎来了史上最大的一次 fork 爆发。
从韩国的独立开发者,到巴西的 SaaS 创业者,再到国内某高校前端课程项目,全都开始 fork 他项目改造成自己的 UI 库。
有开发者将它集成进 vite-plugin-preview
有团队用它重写自己的内网后台系统
甚至有一个 React Native 方向的开发者,提交了一个 PR,开始适配移动端
宋执看着通知中心不断跳动的 PR 提醒,心脏砰砰跳动。
他明白,自己被骂的那一刻,反而让更多人看见了坚持的价值。*
但冲突没有结束。
一个叫「UIGEN」的 AI UI 公司向他发起了挑战:组件 Battle。
规则很简单:
-
双方各出一个组件主题(如 Modal、Dropdown、Tabs)
-
一方由人类写代码,另一方用 AI prompt 自动生成
-
评审标准为:性能、无障碍支持、设计一致性、二次封装能力、开发体验
这一次,社区来投票。
这个话题迅速登上 Twitter 热榜(国内 X 热榜),被称为“人类开发者与 AI 的第一次 UI 决斗”。
UIGEN 推出他们的 Modal Prompt:
“Create a responsive modal component with dark mode, keyboard navigation, and animation.”
不到 2 分钟,AI 生成了一段代码,样式炫酷,动画丝滑。
宋执没有立刻写代码。
他沉默了一夜。
然后打开 VSCode,开始写他的版本。
他用了:
-
Headless UI 的组合思想:行为与表现分离
-
React Context 控制状态:兼容嵌套与 Portal
-
Framer-motion 的 layout spring:自然闭合动画
-
焦点陷阱(Focus Trap) 与 键盘导航支持
他写了整整 280 行,写完后每一行都跑了测试,并加了完整文档,支持嵌套 Modal、异步加载内容与响应式布局。
他将这段代码 push 到 unicorn-ui 的 next 分支。
一小时后,GitHub 上出现了这样一条 Star 评论:
“这不是 Modal,这是手术级别的交互模块。”
最终的社区评审投票:
-
视觉一致性:AI 版本胜(因为用了一套自动化设计语言)
-
响应速度:平局
-
无障碍支持:人类版本胜(AI 版本缺失 focus trap)
-
二次封装能力:人类版本胜(AI 生成代码高度耦合)
-
开发者好评:人类版本压倒性胜出
宋执用代码赢了。
但他没有嘲讽、也没有开香槟。
他只是更新了 unicorn-ui 的 README,新增了一句引用:
“AI 可以加速实现,但无法替你思考架构。”
回到原来那家公司的前端组,有人在偷偷在项目中重新安装 unicorn-ui,把默认按钮样式覆盖到生成式组件之上。
许凡当然知道,但他没有阻止。
因为他明白——这个按钮,虽然是宋执写的,但已经不属于宋执了。
它属于开发者。
属于那些不愿意被 prompt 定义流程、不愿意被工具异化为机器的工程师。
宋执坐在电脑前,打开 Notion,记录下下一阶段的 roadmap:
-
Tabs 组件支持多语言布局方向
-
Dropdown 支持命令面板模式
-
Form 套件与 yup/zod 的集成计划
-
create-unicorn-app 脚手架构想
他喝了一口凉掉的美式,敲下一行标题