功能做完了,但用起来总觉得"哪里不对"------颜色、间距、加载体验、空状态......这些细节以前要跟设计师反复沟通,现在用 Claude 自己来实现。本篇带你完成整体视觉升级、交互状态完善、微动画加入,产品从"能用"变成"好用"。
一、前言:功能做完了,但"颜值"不够
做产品经理这些年,你一定遇到过这种情况:
开发按你的 PRD 做出来了,功能都对,但你看了一眼,就是感觉"哪里不对"。
于是你去找设计师,说"这个间距太紧了"、"这个颜色不协调"、"这个 loading 状态太丑了"......设计师改一版,你再看,再提......来回三轮,才有了个还行的效果。
这种沟通成本,你现在可以省掉了。
你自己就是产品经理,你有审美,你知道好的 UI 是什么感觉。现在 Claude 是你的工具,你直接实现就好了。
本篇我们做的事很产品经理:不追求技术上多厉害,而是把这个产品打磨得更好用、更好看,让每一个交互细节都有应有的质感。
💡 本系列全程使用 weelinking 访问 Claude,国内可稳定使用
二、整体视觉升级
2.1 确定配色方案
颜色是视觉的第一印象。很多"不好看"的产品,往往只是配色出了问题。
你: 我在做一个需求管理平台,面向产品经理和研发团队使用,风格要专业、现代、简洁,给我推荐一套完整的配色方案,包括:主色、辅助色、成功色、警告色、错误色、背景色、文字颜色(主要、次要、禁用),并给出 CSS 变量的形式,我可以直接用在 React 项目里。
Claude 会给你一套专业的设计规范:
css
/* src/styles/variables.css */
:root {
/* 主色系 - 专业蓝 */
--color-primary: #2563EB;
--color-primary-hover: #1D4ED8;
--color-primary-light: #EFF6FF;
/* 功能色 */
--color-success: #16A34A;
--color-success-light: #F0FDF4;
--color-warning: #D97706;
--color-warning-light: #FFFBEB;
--color-error: #DC2626;
--color-error-light: #FEF2F2;
/* 中性色 */
--color-bg: #F8FAFC;
--color-surface: #FFFFFF;
--color-border: #E2E8F0;
--color-border-hover: #CBD5E1;
/* 文字色 */
--color-text-primary: #1E293B;
--color-text-secondary: #64748B;
--color-text-disabled: #CBD5E1;
/* 阴影 */
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
}
产品经理的直觉: 你的眼睛就是验收标准。让 Claude 应用这套配色,浏览器里开着看效果,不满意就继续调。这比跟设计师开评审会效率高 10 倍。
2.2 全局字体升级
你: 帮我在项目里接入 Google Fonts 的 Inter 字体,这是一款专为屏幕阅读设计的字体,适合后台系统。在 index.html 里引入,并在全局 CSS 里设置字体栈。
html
<!-- public/index.html -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
css
/* src/styles/global.css */
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
font-size: 14px;
line-height: 1.6;
color: var(--color-text-primary);
background-color: var(--color-bg);
-webkit-font-smoothing: antialiased;
}
2.3 整体布局调整
你: 帮我优化侧边栏导航的视觉设计:
- 整体宽度 240px,背景白色,右侧有 1px 的 border
- Logo 区域高度 64px,居中显示
- 菜单项高度 40px,左侧 16px padding,有 8px 圆角
- 当前激活菜单:蓝色背景(var(--color-primary-light)),文字蓝色
- 悬浮时:浅灰色背景(#F1F5F9)
- 菜单图标和文字之间间距 10px
三、交互体验优化
3.1 加载状态:别让用户盯着空白
你做过多少次需求:"列表加载时要有 loading 状态,不然用户以为产品挂了"。
现在自己实现:
你: 在需求列表页,数据加载期间展示骨架屏(Skeleton)效果,而不是 Loading 转圈。骨架屏要模拟出真实的列表行结构(每行有一个标题宽度的灰色条、一个标签宽度的短条、一个时间宽度的短条),使用 CSS 动画让它有光泽流动的效果。Antd 有现成的 Skeleton 组件,帮我集成。
jsx
// src/components/RequirementListSkeleton.jsx
import { Skeleton } from 'antd';
const RequirementListSkeleton = () => (
<div className="skeleton-list">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="skeleton-row">
<Skeleton active paragraph={{ rows: 1 }} title={{ width: '60%' }} />
</div>
))}
</div>
);
3.2 操作反馈:每个动作都要有回应
你在做产品设计时一定写过这样的验收标准:
- 点击"创建需求"按钮后,按钮变为 loading 状态
- 成功后,顶部出现绿色成功提示
- 失败时,顶部出现红色错误提示
现在把它实现:
你: 帮我实现全局 Toast 通知组件,需要:
- 成功(绿色)、失败(红色)、警告(橙色)三种类型
- 从右上角滑入,3秒后自动消失
- 同时最多显示3条
- 全局可以通过
toast.success('xxx')调用使用 antd 的 message 组件实现,并封装成一个
useMessagehook 让所有页面复用。
jsx
// src/hooks/useMessage.js
import { message } from 'antd';
export const useMessage = () => {
const success = (content) => message.success(content, 3);
const error = (content) => message.error(content, 4);
const warning = (content) => message.warning(content, 3);
const info = (content) => message.info(content, 3);
return { success, error, warning, info };
};
按钮防重复提交------这个细节很重要:
你: 创建需求的提交按钮,点击后要立即变成 loading 状态(显示转圈 + 文字变成"提交中..."),并且禁用,直到接口返回结果后恢复。防止用户连续点击提交多次。
jsx
const [submitting, setSubmitting] = useState(false);
const handleSubmit = async (values) => {
setSubmitting(true);
try {
await createRequirement(values);
message.success('需求创建成功');
navigate('/requirements');
} catch (err) {
message.error('创建失败,请重试');
} finally {
setSubmitting(false);
}
};
// 按钮
<Button type="primary" htmlType="submit" loading={submitting}>
{submitting ? '提交中...' : '创建需求'}
</Button>
3.3 删除确认------防止用户手滑
你: 点击删除需求时,先弹出 Modal 确认框。
- 标题:"确定要删除这个需求吗?"
- 内容:显示需求标题,警告文字"删除后无法恢复"
- 按钮:取消(灰色)、确认删除(红色,danger类型)
- 点击确认后,按钮变为 loading 状态
jsx
const handleDelete = (requirement) => {
Modal.confirm({
title: '确定要删除这个需求吗?',
content: (
<div>
<p>需求:<strong>{requirement.title}</strong></p>
<p style={{ color: '#DC2626', marginTop: 8 }}>⚠️ 删除后无法恢复</p>
</div>
),
okText: '确认删除',
okType: 'danger',
cancelText: '取消',
onOk: () => deleteRequirement(requirement.id),
});
};
3.4 表单体验优化
产品经理最讨厌的体验:填了一大表单,点提交,然后从头开始报错。
你: 把创建需求表单改为实时验证:用户填写时(blur 事件,离开输入框后)立即校验,不要等提交时才报错。同时:
- 必填字段标红星号
- 输入框聚焦时有蓝色边框
- 字符数限制字段(如标题200字、描述5000字)右下角显示实时计数
四、微动画让产品有生命感
4.1 页面切换过渡动画
你: 使用 React 的 CSSTransition 或 antd 的内置过渡,给页面切换加上淡入效果(fade in)。路由切换时,新页面从透明度0渐变到1,时间0.2秒。
css
/* src/styles/animations.css */
.page-enter {
opacity: 0;
transform: translateY(8px);
}
.page-enter-active {
opacity: 1;
transform: translateY(0);
transition: opacity 0.2s ease, transform 0.2s ease;
}
.page-exit {
opacity: 1;
}
.page-exit-active {
opacity: 0;
transition: opacity 0.15s ease;
}
4.2 列表项动画
你: 需求列表里,每条记录出现时加上从下往上淡入的动画,每条记录的延迟递增(第1条0ms,第2条50ms,第3条100ms......),制造出"逐一浮现"的效果。
jsx
// 在列表渲染时添加动画样式
{requirements.map((item, index) => (
<div
key={item.id}
className="requirement-item"
style={{
animationDelay: `${index * 50}ms`,
animationFillMode: 'both'
}}
>
{/* 内容 */}
</div>
))}
css
.requirement-item {
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
4.3 看板拖拽动效优化
你: 看板拖拽时,被拖拽的卡片要有明显的视觉反馈:
- 拖拽中:卡片旋转3度,加深阴影,半透明
- 目标列:高亮蓝色边框,提示"可以放置这里"
- 放置后:有一个弹跳的落地动画
五、细节是魔鬼
5.1 空状态设计
产品经理都知道:空状态是体验设计的关键。
你: 当需求列表为空时(没有任何需求,或筛选结果为空),不要直接显示空表格,而是:
- 有筛选条件导致的空:显示"没有找到符合条件的需求",副标题"试试调整筛选条件",一个"清除筛选"按钮
- 真正没有任何需求:显示插画(用 SVG 的空状态插画),标题"还没有需求",副标题"创建第一个需求,开始管理你的产品需求吧",一个"创建需求"按钮
jsx
// src/components/EmptyState.jsx
const EmptyState = ({ type = 'no-data', onClear, onAction }) => {
const configs = {
'no-data': {
icon: '📋',
title: '还没有需求',
description: '创建第一个需求,开始管理你的产品需求吧',
action: { text: '创建需求', onClick: onAction }
},
'no-result': {
icon: '🔍',
title: '没有找到符合条件的需求',
description: '试试调整筛选条件',
action: { text: '清除筛选', onClick: onClear }
}
};
const config = configs[type];
return (
<div className="empty-state">
<div className="empty-state__icon">{config.icon}</div>
<h3 className="empty-state__title">{config.title}</h3>
<p className="empty-state__desc">{config.description}</p>
{config.action && (
<Button type="primary" onClick={config.action.onClick}>
{config.action.text}
</Button>
)}
</div>
);
};
5.2 错误边界
你: 帮我实现一个错误边界组件(ErrorBoundary),当页面某个部分崩溃时,显示一个友好的错误提示,而不是让整个页面白屏。错误提示要包含:一个哭泣的表情、"这里出了点问题"的文案、"刷新重试"按钮。
5.3 404 页面
你: 帮我实现一个 404 页面:
- 大号的 404 数字(用 CSS 做成灰色渐变效果)
- "迷失方向了?" 的主标题
- "你要找的页面不存在,可能是链接出了问题" 的副标题
- "回到首页" 按钮
- 整体风格和产品主题保持一致
5.4 Favicon 和页面标题
你: 帮我给产品设置:
- Favicon:一个简单的需求管理相关的 emoji 图标(📋),用 SVG 格式,放在 public 目录
- 页面标题:每个路由有不同的
<title>,格式是 "页面名 - 需求管理平台"(比如 "需求列表 - 需求管理平台")
jsx
// 使用 react-helmet 或原生的方式设置 title
useEffect(() => {
document.title = `${pageName} - 需求管理平台`;
}, [pageName]);
5.5 深色/浅色模式
你: 帮我实现主题切换功能(深色/浅色):
- 右上角有一个主题切换按钮(☀️/🌙)
- 切换时,页面所有颜色平滑过渡(transition 0.3s)
- 用户的选择存入 localStorage,下次打开保持上次的选择
- 利用 CSS 变量实现,深色主题下只需要覆盖 :root 变量值
css
/* 深色主题变量 */
[data-theme='dark'] {
--color-bg: #0F172A;
--color-surface: #1E293B;
--color-border: #334155;
--color-text-primary: #F1F5F9;
--color-text-secondary: #94A3B8;
--color-primary-light: #1E3A5F;
}
* {
transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}
六、响应式适配------手机也要好用
作为产品经理,你知道要做移动端适配。现在自己来:
你: 帮我给需求列表页做移动端适配:
- 屏幕宽度 < 768px 时:
- 侧边栏隐藏,改为顶部 Drawer 抽屉导航
- 列表变为卡片模式(不用表格)
- 每个卡片显示:标题、优先级标签、状态标签、创建时间
- 操作按钮放在卡片右侧的下拉菜单里(...按钮)
使用 antd 的 useBreakpoint 钩子检测屏幕尺寸。
jsx
import { Grid } from 'antd';
const { useBreakpoint } = Grid;
const RequirementList = () => {
const screens = useBreakpoint();
const isMobile = !screens.md;
return (
<div>
{isMobile ? <MobileCardList /> : <DesktopTable />}
</div>
);
};
七、优化效果对比
打磨前后的变化一览:
| 优化项目 | 优化前 | 优化后 |
|---|---|---|
| 颜色体系 | 随机颜色,不统一 | 专业配色方案,CSS变量统一管理 |
| 字体 | 系统默认字体 | Inter 字体,更适合屏幕阅读 |
| 加载状态 | 空白等待 | 骨架屏,不让用户盯着空白 |
| 操作反馈 | 点完没反应 | Toast 通知,按钮 loading 状态 |
| 删除确认 | 直接删除 | 二次确认弹窗,防止手滑 |
| 表单验证 | 提交时才报错 | 实时验证,离开输入框即校验 |
| 空状态 | 空表格 | 有引导文案和操作按钮 |
| 404页面 | 浏览器默认 | 品牌化设计 |
| 主题切换 | 无 | 深色/浅色一键切换 |
| 移动端 | 布局错乱 | 响应式适配,卡片式列表 |
| 动画 | 无 | 页面切换、列表项入场、拖拽动效 |
八、总结与下期预告
🎯 本篇核心要点
1. UI 打磨不需要学设计,需要有"产品经理的眼睛"。 你知道什么样的体验是好的,Claude 帮你实现。
2. 配色方案 + CSS 变量,是视觉升级的基础。 一次定义,全局生效,修改颜色不再是噩梦。
3. 每个操作都要有反馈。 Loading、Toast、确认弹窗------这是产品设计的基本功,也是真正让用户感到"这个产品靠谱"的关键。
4. 空状态是体验的窗口。 空列表、错误页面、404------别忽视这些"边缘状态",它们往往决定用户对产品的第一印象。
5. 微动画是产品质感的秘密武器。 不需要复杂,0.2秒的淡入效果就能让产品从"够用"变成"好用"。
📌 记住这句话
你以前跟设计师说"这里的颜色不对"、"这里的间距太小了"------现在你自己说,Claude 自己改,从此不再等评审。这才是技术型 PM 的效率。
📣 下期预告
第16篇:《数据可视化------用图表讲述产品数据的故事》
核心功能加上好看的界面,产品已经很完整了。下一篇,我们来做数据统计看板------
作为产品经理,你每周都要做数据周报。现在,让你自己的产品生成实时的图表,把「需求管理平台」变成真正的数据驾驶舱:状态分布饼图、需求趋势折线图、优先级分布柱状图,全部实时更新。
💡 本系列全程使用 weelinking 访问 Claude,国内可稳定使用
📎 配套资源
📋 UI 打磨检查清单
□ 视觉基础
□ 配色方案已定义为 CSS 变量
□ 字体已统一(Inter 或其他专业字体)
□ 间距系统统一(8px 基础单位)
□ 阴影层级统一(sm/md/lg)
□ 加载状态
□ 所有列表页有骨架屏或 loading 状态
□ 所有提交按钮有 loading 状态
□ 页面级别加载有顶部进度条
□ 操作反馈
□ 增删改操作都有 Toast 通知
□ 删除操作有二次确认弹窗
□ 表单提交失败有错误提示
□ 表单体验
□ 必填字段有红星标注
□ 实时校验(blur 事件触发)
□ 有字数限制的字段有计数器
□ 提交按钮在表单校验不通过时禁用
□ 空状态
□ 列表为空时有空状态组件
□ 搜索/筛选无结果时有对应提示
□ 空状态有引导操作按钮
□ 错误处理
□ 错误边界组件已添加
□ 404 页面已实现
□ 网络错误有友好提示
□ 动画与过渡
□ 页面切换有淡入效果
□ 列表项有入场动画
□ 主题切换有平滑过渡
□ 响应式
□ 移动端(< 768px)布局正常
□ 侧边栏在移动端改为抽屉形式
□ 列表在移动端改为卡片形式
📋 常用 UI 提示词模板
配色方案:
我在做一个[产品类型],面向[用户群体],风格要[风格描述]。
请给我推荐一套完整配色方案,包含:主色、辅助色、功能色(成功/警告/错误)、中性色(背景/表面/边框)、文字色(主/次/禁用)。
以 CSS 变量形式输出,可以直接在项目里用。
加载状态:
帮我给[页面/组件名]加上骨架屏效果:
- 模拟真实数据结构(标题行/内容行/操作行)
- 使用 Antd 的 Skeleton 组件实现
- loading 状态从 props 传入,loading=true 显示骨架屏,false 显示真实内容
空状态:
帮我实现空状态组件 EmptyState:
场景1:列表真正为空 - 标题"[标题]",描述"[描述]",按钮"[操作]"
场景2:筛选无结果 - 标题"没有找到结果",描述"试试调整筛选条件",按钮"清除筛选"
通过 type prop 区分两种场景。
微动画:
帮我给[组件名]加上动画效果:
- 出现时:从下方 12px 处上移 + 透明度 0 到 1,时长 0.3s
- 消失时:透明度 1 到 0,时长 0.15s
- 多个元素依次出现时,每个延迟 [N]ms
用纯 CSS animation 实现,不引入额外动画库。
🌟 如果这篇文章对你有帮助,请点赞👍 收藏⭐ 关注🔔
你的支持是我持续更新的最大动力!
💬 评论区聊聊:你觉得一个"好用"的产品,最重要的体验细节是什么?
📌 系列导航: 产品经理用 Claude 实现产品 · 系列目录
⏪ 上一篇: 第14篇:用户登录与权限------你最熟悉的"角色权限"落地了
⏩ 下一篇: 第16篇:数据可视化------用图表讲述产品数据的故事
💡 本系列全程使用 weelinking 访问 Claude,国内可稳定使用🚀 整个系列的核心理念:你不需要变成程序员,你只需要从"找人做"变成"自己能做"。