Analog Liquid Glass for DeepSeek Harness
把 DeepSeek Harness 的输入框变成一片模拟质感的液态玻璃。
顶部镜面高光、内缘白线、边缘溢出的一圈柔光;模型思考时玻璃里往上冒泡; 深浅主题切换带 1.7 秒的从容过渡。
名字里的 Analog 指模拟仪表那种质感(弯液面、观液管、刻度),不是技术上的"模拟/数字" —— 对应插件里的玻璃容器、液位式进度与上升的气泡,也与"数字进度条"划清界线。图标即为此意。

安装
从 GitHub 安装(当前推荐,本包尚未发布到 npm):
dsh plugin --profile <你的 profile> add github:Siloet-phy/analog-liquid-glass-for-dsh
桌面版 DSH 的包管理需要先完全退出 DSH 再执行;装完重启生效。 profile 名一般是
desktop(桌面版)或web(dsh web起的服务)。
如果只想用短名(需要在 npm 上已发布同名包):
dsh plugin --profile <你的 profile> add analog-liquid-glass-for-dsh
它做了什么
| 元素 | 说明 |
|---|---|
| 磨砂层 | 白雾 + 重度模糊,是"玻璃感"的来源(不是简单叠一层半透明) |
| 顶部镜面高光 | 玻璃最容易辨认的那道柔光 |
| 内缘白线 | 上缘一道发丝白线 |
| 外扩散泛光 | 光从玻璃边缘微微溢到外面一圈 |
| 三点吐泡泡 | 只在模型思考时出现:三颗泡错开 1/3 周期、同一个出生点,一个破灭、一个新生 |
| 主题过渡 | 浅 ↔ 深切换时,玻璃比整页更慢地插值(1.7s vs 0.9s) |
| 真毛玻璃 | 为做出磨砂感,覆盖原生卡片的背景与 backdrop-filter(见下方"设计决定"第 2 条) |
两个我坚持的设计决定
- 玻璃里不放颜色。 真正的液态玻璃几乎是"无色"的——透白玻璃 + 染白的雾 + 白边色散。 颜色只允许出现在边缘的高光上。任何"玻璃内部有一团彩色在流动"的做法, 看着都会像彩色塑料。(我做出过六版彩色玻璃,全被否了。)
- 玻璃层只往 slot 里"加层",靠测量原生卡片的矩形贴合尺寸,不改它的 DOM 结构。
唯一例外是"真毛玻璃":为做出磨砂感,会覆盖
[data-composer-card]的背景与backdrop-filter(这是毛玻璃唯一能成立的物理位置——在卡片内容之上加雾会把文字压淡, 对它做backdrop-filter会把文字一起糊掉)。该段集中在client.js一处、带注释与旋钮, 删掉即回到纯加层模式;/菜单底板那处小修复同理可删。卸载后不留任何样式。
图标
icon.svg 的立意是模拟仪表,和"数字进度条"划清界线:
一根竖直的玻璃观液管(sight tube),里面一柱淡蓝液体,顶端一道弯液面 (液体贴管壁上翘的那道弧,是"模拟时代"最一眼可辨的符号),液柱里两点气泡正在上升。 —— 玻璃是容器、液位是进度、气泡是"模型正在思考",正好对应插件的三件事。
配色与插件本体一致(天蓝 112,176,244 为主、冷白为釉)。
多尺寸与深浅底的对照见 docs/icon-preview.html;
设计草图留在 docs/icon-concept.svg,
上一版图标备份在 docs/icon-previous.svg。
兼容性
- DSH:
0.2.0-rc.2及以上(依赖conversation.input.overlayslot 与ctx.theme的theme/change事件)。 - 平台:Web 客户端(桌面版内置浏览器 /
dsh web)。纯 CLI 会话不受影响。 - 浏览器:Chromium 系(Electron)。用到
backdrop-filter与color-mix(),需要现代内核。 - 无障碍:遵循
prefers-reduced-motion——开启后所有动画停止,只保留静态玻璃与状态色。
开发
node selftest.mjs # 19 项断言:替身环境,验证模块面与 apply() 行为
node livetest.mjs [react-umd 目录] # 30 项断言:真 React + 真 DOM,验证真的能渲染
selftest.mjs:用替身把客户端 bundle 完整跑一遍——语法、模块面(name/inject/apply)、apply()在有无服务时的行为、slot 注册目标、样式挂载、theme/change订阅、组件渲染。 改完client.js先跑它,因为客户端 bundle 一旦在最顶层抛错会牵连 Web 端模块系统。livetest.mjs:需要react/react-dom/jsdom(故意不进 package.json 依赖, 避免让插件包带上开发期重量)。它用真 React 把玻璃层真的挂进真 DOM,并验证 几何锚定(含"包含块非视口"时的差值归零)、fail-closed 行为、running状态翻转时data-busy/data-on跟着变、卸载后 DOM 清干净。
两个测试装置上的坑(都写进注释了): ①
document/window必须在require('react-dom')之前就位; ② 必须用createRoot+act(),不能用 legacyReactDOM.render—— legacy render 会把 passive effects 推到下一个任务,同步断言时会看到 "玻璃层没进 DOM"这种假失败。
技术笔记
- 主题:直接消费 DSH 的
--dsw-*token 与body[data-ds-dark-theme], 不自己管理主题状态;过渡窗口通过监听ctx.theme的theme/change事件实现。 - 挂点:
conversation.input.overlay(list,session 作用域); "模型是否在思考"来自标准 props 的useSession((s) => s.running), 取不到时退化为观察原生按钮的「发送 ↔ 停止」态(MutationObserver),保证气泡不会静默失效。 - 几何:玻璃层用
position:fixed+ 实测原生卡片矩形写进 CSS 变量。 ⚠ 取的是「卡片矩形 − 自身矩形」的差值,不能直接用卡片的视口坐标—— 卡片一旦带backdrop-filter就会成为 fixed 的包含块,直接写会偏移叠加两次。 找不到卡片则整体隐藏(fail-closed)。 - 踩过的坑(都写进注释了):
- 已删除的「镶边」:曾用"放大盒子 +
mask-composite只留边线"做 1.5px 绕行亮边, 深色下会变成一圈巨大的旋转发光矩形(用户点名要求删掉)。教训:mask-composite必须-webkit-前缀与标准属性双写,且绝不要放大盒子;要做镶边应让盒子就是玻璃本身。 - 玻璃里的彩色无论多淡都会显土;低饱和色块压在深底上还会变泥浆色。
- 循环动画必须让元素在关键帧里自己收束——曾做成"无限上浮",到顶被裁掉,看不出破灭。
- 给会动的元素做
scaleY调幅度时必须显式写transform-origin,否则元素会"消失"。 - 读
getComputedStyle/ 条件调用 hook 都会在真实环境里炸;前者要 try/catch,后者要定序。
- 已删除的「镶边」:曾用"放大盒子 +
- 参考: wxperia/liquid-glass-vue 与 rdev/liquid-glass-react(折射位移图的算法来源), 以及 Apple 的液态玻璃设计语言。
截图说明
docs/light.png 与 docs/dark.png 是设计稿(单文件 HTML 演示)在浏览器里的实拍;
插件的实现与设计稿逐像素对齐(同一套 CSS)。设计稿与全部探索过程在同一作者的
magic-cast 工作目录里,未随包发布。
卸载
dsh plugin --profile <你的 profile> remove analog-liquid-glass-for-dsh
卸载后输入框恢复原样,不会残留样式(样式表随插件生命周期移除)。
许可证
MIT
No comments yet. Be the first to write one.