观瞻:作为一个接触ai-agent框架不久的开发者,最近在学习 Next + LangChain 技术栈时,决定做一个 AI 聊天 demo 来巩固知识。在这个过程中尝试了多个 UI 框架,最终选择了 shadcn/ui。记录下这段学习经历,希望未来能查漏补缺。
起因:为什么选择 shadcn/ui?
现如今ui框架百花齐放,不过对组件库的选择还是有点困惑:
- Ant Design?感觉太重了,而且主要是面向后台系统的
- MUI?React 生态里很火,但配置主题有点复杂
- Tailwind CSS?听说很流行,但自己写组件太费时间
第一个坑:它根本不是 npm 包!
按照网上教程,我兴冲冲地运行:
csharp
bash
编辑
1pnpm add shadcn-ui
结果发现根本找不到这个包!一脸懵逼的我跑去 GitHub 看文档,才发现:
shadcn/ui 不是一个传统的组件库,而是一套可以复制到你项目里的组件代码
这完全颠覆了我对 "UI 框架" 的认知。以前用 Ant Design 或 Element UI,都是 npm install 就完事了,但 shadcn/ui 却要你把每个组件的源码直接放进自己的项目里。
一开始我觉得这很麻烦,但后来发现这其实是它的最大优势。
正确的安装姿势
第一步:初始化项目
首先要在你的 Next.js 项目根目录运行:
kotlin
bash
编辑
1pnpm dlx shadcn@latest init
这个命令会问你几个问题,比如是否使用 TypeScript、Tailwind CSS 配置路径等。我的项目已经配置好了 Tailwind,所以一路回车就行。
第二步:按需添加组件
这里又踩了个小坑。我一开始以为要一个一个添加:
sql
bash
编辑
1# 错误的想法
2pnpm dlx shadcn@latest add button
3pnpm dlx shadcn@latest add input
4pnpm dlx shadcn@latest add card
5# ... 还要输入7次
后来发现其实可以一次性添加所有需要的组件:
less
bash
编辑
1pnpm dlx shadcn@latest add button input card scroll-area spinner toast separator label
注意 :一定要用 pnpm dlx,而不是直接 pnpm shadcn,否则终端会报错找不到命令。
第三步:看看生成了什么
运行完命令后,我发现项目里多了一个 components/ui/ 目录,里面是我刚才添加的所有组件文件:
css
text
编辑
1components/
2└── ui/
3 ├── button.tsx
4 ├── input.tsx
5 ├── card.tsx
6 ├── scroll-area.tsx
7 ├── spinner.tsx
8 ├── toast.tsx
9 ├── separator.tsx
10 └── label.tsx
每个文件都是独立的,我可以随时打开修改,比如我想把按钮的圆角改大一点,直接编辑 button.tsx 就行,不用去查文档找怎么覆盖样式。
为什么我觉得 shadcn/ui 特别适合聊天应用?
做聊天应用有几个特殊需求:
- 消息气泡要区分用户和 AI
- 输入框要有发送按钮
- 聊天历史要能滚动
- AI 回复时要有加载状态
shadcn/ui 的这几个组件完美解决了这些问题:
消息气泡(Card 组件)
typescript
tsx
编辑
1// components/message-bubble.tsx
2import { Card, CardContent } from "@/components/ui/card";
3
4export function MessageBubble({ isUser = false, content }: { isUser: boolean; content: string }) {
5 return (
6
7
8 <p>{content}</p>
9
10
11 );
12}
聊天输入区域(Input + Button + Spinner)
javascript
tsx
编辑
1// components/chat-input.tsx
2import { Input } from "@/components/ui/input";
3import { Button } from "@/components/ui/button";
4import { Spinner } from "@/components/ui/spinner";
5
6export function ChatInput({ message, setMessage, onSubmit, isLoading }: any) {
7 return (
8 <div>
9 setMessage(e.target.value)}
12 placeholder="输入消息..."
13 onKeyDown={(e) => e.key === 'Enter' && onSubmit()}
14 disabled={isLoading}
15 />
16
17 {isLoading ? : "发送"}
18
19 </div>
20 );
21}
聊天历史滚动(ScrollArea)
javascript
tsx
编辑
1// app/page.tsx
2import { ScrollArea } from "@/components/ui/scroll-area";
3
4export default function ChatPage() {
5 // ... 其他逻辑
6
7 return (
8 <div>
9
10 {messages.map((msg, i) => (
11
12 ))}
13
14
15 </div>
16 );
17}
主题定制:比想象中简单
最让我惊喜的是主题定制。因为我的项目已经用了 Tailwind CSS,所以只需要在 tailwind.config.js 里配置颜色:
less
js
编辑
1// tailwind.config.js
2module.exports = {
3 theme: {
4 extend: {
5 colors: {
6 primary: {
7 500: "#60a5fa", // 蓝色 - 用户消息
8 },
9 secondary: {
10 500: "#22c55e", // 绿色 - AI 消息
11 }
12 }
13 }
14 }
15}
然后在组件里直接用 bg-primary-500、bg-secondary-500 就行了,完全不需要额外的配置。
遇到的问题和解决方案
问题1:DevTools 小图标太烦人
Next.js 16 开发模式右下角有个小图标,特别影响调试。试了很多方法都不行,最后用 CSS 强制隐藏:
ini
tsx
编辑
1// app/layout.tsx
2if (typeof window !== "undefined" && process.env.NODE_ENV === "development") {
3 const hideDevtools = () => {
4 const style = document.createElement("style");
5 style.innerHTML = `
6 #devtools-indicator,
7 .nextjs-toast {
8 display: none !important;
9 }
10 `;
11 document.head.appendChild(style);
12 };
13
14 if (document.readyState === "loading") {
15 document.addEventListener("DOMContentLoaded", hideDevtools);
16 } else {
17 hideDevtools();
18 }
19}
问题2:组件太多不知道选哪些
一开始我也想把所有组件都装上,后来发现完全没必要。对于聊天应用,其实就那几个核心组件:
- Button:发送按钮
- Input:消息输入
- Card:消息气泡
- ScrollArea:聊天滚动
- Spinner:加载状态
其他像 Toast、Separator、Label 这些是提升体验用的,可以根据需要再加。
总结:shadcn/ui 到底值不值得用?
作为一个初学者,我觉得 shadcn/ui 有这些优点:
✅ 学习成本低 :基于 Tailwind CSS,样式直观易懂
✅ 高度可定制 :组件代码就在你项目里,想怎么改都行
✅ 按需使用 :不会引入没用的代码,包体积小
✅ Next.js 友好:完美支持 React Server Components
当然也有缺点: ❌ 不是传统 npm 包 :需要适应新的使用方式
❌ 需要手动管理:组件更新需要自己同步官方代码
但总的来说,如果你在用 Next.js + Tailwind CSS,shadcn/ui 绝对值得一试。特别是做聊天应用这种需要高度定制 UI 的场景,它能让你快速搭建出专业级的界面。
最后的建议
- 不要试图一次装所有组件,按需添加就好
- 善用 Tailwind 的主题配置,让整个应用风格统一
- 把组件当成自己的代码,大胆修改以适应需求
- 遇到问题先看官方文档,shadcn/ui 的文档写得非常清晰