聊天「就地往下展开」+ 回答渲染 Markdown:三版才丝滑
2026-06-17约 2.5 小时体验聊天重构踩坑
目标
两个体验欠账:①三个聊天入口(hero 胶囊 / 导航胶囊 / 速览第七卡)都是 href="#twin" 锚点,点了直接跳到底部终章、跳过中间六屏正文;②分身回答常带 Markdown(**加粗**、- 列表),气泡却是纯文本、符号原样露。
三版迭代(值得记的全是被否的过程)
- 居中弹窗浮层——站主一句否:「就在这展开对话框,不是弹窗」。记下:「不跳转」≠「弹窗」。
- 退出剧场 + 滚到顶就地展开——点击即把首页退出 scrub 剧场、
scrollTo(0)、藏掉 hero 大字、对话框在 hero 中央展开。站主再否:「乱跳」。根因:从 scrub 中途位置点击 →scrollTo(0)一大跳 + 退出剧场使页面高度骤变 +display:none重排,三重跳动。 - 就地往下长出(最终):不碰剧场、不滚动、不重排——在被点元素位置
fixed锚一张深色聊天卡,clip-path: inset(... 100% ...) → inset(0)自上而下「长出来」(不挤压文字),打开时锁滚动把页面冻在原地。于是零跳动、丝滑。横向居中(胶囊本就居中=从胶囊处长出)、竖向从被点元素顶部往下、底部不溢出才上钳;透明点击区点外关闭,无遮罩压暗(页面照常可见,不是弹窗)。
结果
- 全局
ChatExpander(挂 layout,按 pathname 选中英):capture 阶段拦[data-chat-entry]点击 → 记录被点元素 rect → 锚定长出。ChatPanel懒加载;终章真窗聊天岛保留作无 JS 兜底(入口href="#twin"无 JS 时照常跳终章)。 - Markdown 渲染:
ChatMarkdown复用 react-markdown + remark-gfm(零新依赖),prose-invert渲染回答。
踩坑与纠正
- 聊天卡在白底 hero 上看不见:
ChatPanel是为终章黑底做的深色主题(bg-white/[0.06]、白字白按钮),搬到白底上几乎全隐形。改实色bg-[#1c1c1e]:白底上是清晰深色卡,黑底终章上是浮起卡,两处都对。 - 又踩 RSC 边界:客户端组件别收整个
content(含getProject函数,next build预渲染会炸),只传可序列化字段。 - clip-path 揭示而非 scaleY:用 scaleY 长出会把文字竖向挤压抖动;改 clip-path 自上而下揭示,文字不变形、真正「长出来」。
用时与备注
约 2.5 小时(含两版被否 + 重做)。lint/typecheck/build 全绿、49 页。生产构建实测:点击入口就地长出居中深色卡、页面 scrollY 不变(零跳动)、剧场不被打断;演示兜底 - 列表渲染成真列表。本批未部署(站主计划重购域名后再上线)。