OpsMind UI 重构实录(三):消息区、侧边栏和输入框,终于变成我喜欢的样子
OpsMind UI 重构实录(三):消息区、侧边栏和输入框,终于变成我喜欢的样子
wwxdsg如果说前两天分别解决了“链路”和“体系”,那第三天终于轮到我最想做的那部分了:
把这个聊天界面一点一点磨到我自己真心喜欢。
这种喜欢不只是“它看起来更现代”,而是你会明显感觉到,页面终于开始顺手、顺眼,也顺逻辑。
很多改动单看都不算惊天动地:
- 字号从 14px 改到 16px
- 对话区从 720px 放到 760px
- 消息间距从 16px 拉到 24px
- 侧边栏从 248px 调到 288px
- 输入框阴影、边框、圆角全部重做
但 UI 这件事常常就是这样。
真正决定质感的,往往不是某一个“设计大招”,而是一堆你愿意认真对待的小地方。
我最先动的是阅读感
第三天里,我最确定的一件事是:消息区必须更像“能读很久的地方”,而不是一个把字堆进去的容器。
所以我直接把几个核心参数都抬了一档:
- AI 正文 14px → 16px
- 用户消息 14px → 16px
- 输入框字号 14px → 16px
- 行高 1.7 → 1.8
- 消息间距 16px → 24px
- 顶部留白 20px → 32px
- 对话区最大宽度 720px → 760px
这些数字表面上只是微调,但组合起来,阅读感会一下子变得很不一样。
我尤其喜欢“外层滚动 + 内层居中约束”这个布局:
<div style={{ flex: 1, overflowY: 'auto', padding: '32px 24px 12px' }}> |
它会让聊天区域一下子从“铺满屏幕的内容区”变成“真正被设计过的阅读区”。
这种感觉很重要。
因为对话产品本质上是长时间阅读产品,不是单次扫一眼的运营页。
没装 react-markdown,那就自己写一个
第三天另一个特别有意思的部分,是我干脆手写了一个零依赖 Markdown 渲染器。
原因也很现实:项目依赖受保护,不能想加什么就加什么。
那与其卡在“没有库”,不如自己写一个够用而且可控的版本。
我最后支持的语法其实已经覆盖了聊天场景里最常见的部分:
- 标题
- 有序 / 无序列表
- 行内代码
- 代码块
- 粗体和斜体
- 分割线
- 段落空行
实现方式也不是搞一个完整 parser,而是按聊天场景去做一套轻量状态机:
let listBuffer: { type: 'ul' | 'ol'; items: string[] } | null = null |
遇到多行列表和代码块时先缓存,再在合适时机统一 flush。
这种写法我很喜欢,因为它很朴素,也很贴场景。
它不是为了实现“世界上最标准的 Markdown”,而是为了让 AI 回复在这个产品里看起来足够自然。
流式光标这个细节,我最后也没放过
还有一个我特别想做好的点,是流式消息最后那个闪烁光标。
如果它单独占一行,会显得很笨;
如果它能嵌在最后一段文字末尾,整个流式过程就会顺很多。
所以最后是用 cloneElement 把光标塞回最后一个可渲染节点的 children 里。
这个细节用户可能不会单独注意到,但它确实会影响一种很微妙的感受:
系统到底是在“打印一段文字”,还是在“持续生成一句还没说完的话”。
我希望它更像后者。
侧边栏终于不再像一个拥挤的抽屉
第三天我也把侧边栏认真收拾了一遍。
最直观的变化当然是宽度:248px 调到 288px。
但真正重要的不是它更宽了,而是它终于有空间呼吸了。
对话项的字号、padding、圆角、最小高度都往上调了一点,马上就从“能点”变成了“愿意点”。
同时我还修了一个很容易被忽略、但很影响观感的问题:Sidebar.tsx 宽了以后,chat/layout.tsx 里那三处历史宽度也得一起改。不然抽屉动画和推入布局会出现溢出,最后像一块侧边面板压到主内容上。
这种问题很像前端世界自己的冷笑话:
你以为自己在调美术,结果最后抓到的是三个埋了很久的 260px。
激活态、Hover 和按钮风格都要收一收
我对侧边栏还有个很明确的偏好:
它不应该一直在抢主内容的戏。
所以会话项的激活态,我没有继续用很硬的 border,而是改成 Gemini 那种更轻的背景差分。
新建对话按钮也从实心品牌色改成 ghost 风格,尽量减少“侧边栏一打开先看到一大块醒目按钮”的感觉。
这次越做越觉得,一个成熟界面的克制感往往来自这种地方:
- 激活态不吼
- hover 不喧宾夺主
- 操作按钮只在需要时出现
比如重命名 / 删除按钮,我最后就只让它在 hover 或删除确认态里显示。
不是因为写不出来常驻,而是因为常驻真的很吵。
状态栏和输入框,是我最满意的两块小东西
原来的状态栏是三个带边框的卡片,信息不是不能看,但总有点“为了告诉你状态,专门搭了三块小牌子”的感觉。
我后来把它们改成三条很轻的 dot + label + value:
- 绿点表示正常
- 灰点表示中性
- 黄点表示警告
没有大边框,没有视觉噪音,信息却更清楚了。
它看起来像退了一步,实际是更成熟了一步。
输入框也是同样的思路。
这次我很想要那种更接近 Claude 的药丸感,所以把圆角直接抬到 22px,同时配上更柔和的边框和阴影,再让整个输入区和消息区使用同样的宽度约束。
更重要的是我把输入字号固定到了 16px。
这不仅是为了视觉统一,也是在顺手避开 iOS Safari 对小字号输入框的自动缩放。
这种“顺便把坑填了”的感觉特别好。
你知道自己改的不只是外观,而是把真实使用过程也一起照顾到了。
第三天结束时,我最喜欢的是它终于有“自己的气质”
前两天的工作更像是理性建设:
- 修 bug
- 补接口
- 建 token
- 做主题
到了第三天,整个界面才开始真正长出一点气质。
这种气质不是某个设计网站截图式的漂亮,而是:
- 字看着舒服
- 层级是顺的
- 切主题不别扭
- 聊天区能一直读下去
- 侧边栏不吵
- 输入框有分量但不笨重
我后来回头看这三天,最喜欢的其实就是第三天。
因为它最接近我一开始那个很模糊但很坚定的目标:
把 OpsMind 从“功能可用”真的往“我自己也会喜欢的产品感”推一截。
而这种喜欢,最后几乎都落在了细节上。
也许这就是 UI 工作里最让人上瘾的地方。
你花很多时间,不是为了做出一个“变化很大”的页面,而是为了把一个已经存在的界面,慢慢修到它终于开始像它自己。