
Qwen Code WebShell 移动端空会话 Composer 底部锚定760px 断点布局修复与 E2E 验证【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code导读本文围绕 Qwen Code WebShell 在窄视口≤760px下的空会话new-chat布局展开聚焦「移动端 composer 底部锚定mobile composer-bottom」这一布局路径介绍断点激活条件、mobileWelcomeFooterMiddle等宿主 Props 的语义、CSS 修复方案绝对定位 footer 对齐聊天面板底部并梳理仓库中对应的 Chromium E2E 测试矩阵与可复现命令。读完本文你将掌握该布局的触发条件、修复前后差异、各变体有无欢迎页脚、自定义页脚的渲染行为以及如何在本地用 Playwright 复现与验证这一缺陷。场景窄视口下空会话的 Composer 布局在 WebShell 中当用户尚未打开任何会话空会话态时聊天面板会渲染欢迎头welcome header与欢迎脚welcome footer并竖直居中显示。在桌面宽度下composer 作为聊天面板的常规 flex 子项参与流式排版但在移动端窄视口下WebShell 切换为mobile composer-bottom 布局composer 需要「贴住」聊天面板底部而不是悬浮在内容流的某个位置。原设计文档2026-08-05-webshell-mobile-composer-bottom.md给出的复现场景是在无会话状态下打开 composer-layout 测试挂载harness启用mobileWelcomeFooterMiddle以及欢迎头/欢迎脚渲染器在760px 视口宽度下空聊天面板使用 mobile composer-bottom 布局随后把宽度调整到 761px 再调回 760px。这一场景同时涵盖了布局的激活、断点切换与恢复三个维度是验证该路径是否健壮的最小用例。修复前的缺陷419px 的页脚到面板底部间距在 CSS 修复之前内部 Chromium 挂载在760×900视口下实测到composer 页脚底部footer bottom与聊天面板底部chat pane bottom之间存在419px 的间距。这意味着窄屏用户打开 WebShell 时输入框并没有稳稳地贴在屏幕/面板底部而是悬浮在面板中部偏下的位置——视觉上「悬空」与底部工具栏、安全区之间出现大段空白体验割裂。缺陷的根源在于空会话态为了竖直居中欢迎内容聊天面板使用了居中布局而移动断点下的 composer 仍以流式元素参与排版没有获得「底部锚定」的定位上下文。修复的目标非常明确在 ≤760px 时让 composer 页脚绝对定位并贴住聊天面板底部。断点与锚定机制760px 的 CSS 实现移动布局的开关是媒体查询media (max-width: 760px)实现在 packages/web-shell/client/App.module.css 中。核心规则如下media (max-width: 760px) { .appChatEmpty .chatPaneWithMobileComposerBottom { position: relative; overflow: hidden; } .appChatEmpty .chatViewWithMobileComposerBottom .footer { position: absolute; right: 0; bottom: 0; left: 0; margin-top: 0; } }关键点逐一拆解position: relative建立定位上下文聊天面板.chatPaneWithMobileComposerBottom在空会话态下成为包含块同时overflow: hidden防止绝对定位的页脚溢出面板。position: absolute; bottom: 0完成锚定composer 页脚.footer被从文档流中取出直接贴住面板底部right/left: 0保证横向铺满。断点即开关在 761px 及以上该规则不生效页脚回到流式布局position: relative宽度回调到 760px 时底部锚定自动恢复——这正是文档场景中「761px→760px 往返」要验证的行为。为保证空会话态下该定位生效CSS 还配套了两条前置规则App.module.css.appChatEmpty .chatViewWrap { flex: 0 0 auto; overflow: visible; }注释解释了原因空会话态通过.appChatEmpty .chatPane { justify-content: center }实现欢迎内容竖直居中为此聊天视图包裹层必须收缩到内容尺寸flex: 0 0 auto而不是填满面板居中定位才能成立页脚则脱离该包裹层独立锚定到面板底部。触发布局的宿主 Propsmobile composer-bottom 布局并非默认启用而是由宿主宿主应用通过 Props 定制 WebShell显式声明。三个关键 Props 定义在 packages/web-shell/client/App.tsxProps类型作用renderWelcomeHeaderWelcomeHeaderRenderer空会话态欢迎头的自定义渲染器接收 version、cwd、model、mode 等参数renderWelcomeFooterWelcomeFooterRenderer空会话态显示在 composer 下方的自定义渲染器mobileWelcomeFooterMiddleboolean为true时在移动端空会话态把renderWelcomeFooter渲染到「欢迎头与 composer 之间」移动 CSS 重排依赖该开关三者的联动关系是mobileWelcomeFooterMiddle要求同时提供renderWelcomeFooter否则移动端 CSS 重排不会生效见 App.tsx 中的 JSDoc 注释。组合变体display: contents与页脚排序当同时存在欢迎脚与自定义页脚renderFooter时移动断点下的渲染顺序需要显式控制。CSS 中通过display: contents与order实现App.module.css.appChatEmpty .chatViewWithWelcomeMiddle .footerWithCustomFooter { display: contents; } .appChatEmpty .chatViewWithWelcomeMiddle .footerWithCustomFooter .composer { order: 2; width: min(100%, var(--chat-shell-width)); margin: 0 auto; padding-right: 20px; padding-left: 20px; } .appChatEmpty .chatViewWithWelcomeMiddle .mobileWelcomeFooterMiddle { display: flex; flex: 0 0 auto; align-items: flex-start; justify-content: center; width: min(100%, var(--chat-shell-width)); margin: 0 auto; padding-right: 20px; padding-left: 20px; } .appChatEmpty .chatViewWithWelcomeMiddle .customFooter { order: 1; display: flex; flex: 0 0 auto; ... }含义拆解display: contents自定义页脚变体下页脚容器自身不产生盒模型其子元素composer、欢迎脚、自定义页脚直接参与父级 flex 排布这保证了绝对定位的底部面板如状态面板仍能以上方内容为包含块正确锚定——对应 CSS 中针对.chatViewWithCustomFooter的position: relative兜底规则App.module.css。order控制纵向顺序自定义页脚order: 1在欢迎脚之上composerorder: 2沉底欢迎头则保持在最上方——对应文档场景中「welcome header 保持在 composer 上方」的检查项。居中与宽度约束composer 与欢迎脚都受--chat-shell-width约束并水平居中与桌面端视觉一致。与移动输入后端的配合移动 composer-bottom 布局同样适用于触摸设备上的 textarea 输入后端当宿主以mobile-chromium项目Pixel 7 模拟touch、coarse pointer、无 hover运行时composer 渲染为纯 textarea 而非 CodeMirror。移动端空会话锚定在 textarea 后端同样有专门的 E2E 覆盖见下文测试矩阵保证窄屏触控设备的锚定与输入可用性不因输入组件切换而退化。Chromium E2E 验证矩阵仓库围绕该布局提供了一组 Playwright 测试是文档中「可执行基线」的实体。主测试文件为 packages/web-shell/client/e2e/web-shell.smoke.spec.ts共 4 个相关用例测试用例关注点anchors the empty mobile composer to the chat pane across the breakpoint smokeL1602760px 锚定 → 761px 断点停用 → 调回 760px 恢复锚定并验证 composer 可键入anchors the empty mobile composer without a welcome footer smokeL1649无欢迎脚renderWelcomeFooter缺省时仍正确锚定keeps the bottom status panel visible in the custom footer mobile welcome variant smokeL1669自定义页脚变体中底部状态面板保持在聊天面板范围内anchors the empty mobile composer with a custom footer but no welcome footer smokeL1705自定义页脚 无欢迎脚的组合变体另外textarea 后端锚定由 packages/web-shell/client/e2e/web-shell.composer.mobile.spec.ts 中的anchors the empty mobile composer with the textarea backend覆盖在mobile-chromium项目下运行触摸点按输入并断言 textarea 值。锚定的量化断言expectEmptyMobileComposerAnchoredpackages/web-shell/client/e2e/utils/emptyMobileComposer.ts把「锚定正确」翻译为一组可判定的几何与样式断言expect(layout.footerPosition).toBe(absolute); expect(Math.abs(layout.footerBottom - layout.chatPaneBottom)).toBeLessThanOrEqual(1); expect(layout.chatViewPosition).toBe(static); expect(layout.chatViewIsPaneFlexItem).toBe(true); expect(layout.chatViewZIndex).toBe(auto); expect(layout.footerAnchoredToChatPane).toBe(true);要点页脚底与面板底偏差 ≤1px这是「贴住底部」的量化标准419px 的缺陷在该断言下会直接失败页脚offsetParent必须是聊天面板验证position: relative包含块关系确实建立聊天视图position: static、z-index: auto确保欢迎内容不被浮层干扰处于正常层叠上下文。复现与运行命令文档给出了可直接执行的复现命令--grep精确匹配锚定用例npx playwright test --config packages/web-shell/playwright.config.ts packages/web-shell/client/e2e/web-shell.smoke.spec.ts --grep anchors the empty mobile composer该命令同时覆盖across the breakpoint与without a welcome footer两个用例。修复后上游聚焦运行结果为3 passed含另一处锚定相关用例。移动触控后端用例则通过mobile-chromiumproject 运行可配合 Playwright 的--project参数执行。测试挂载harness如何构造场景场景由 packages/web-shell/client/e2e/composer-layout-harness.tsx 提供通过 URL 查询参数emptyMobileWelcometrue进入空欢迎态并注入mobileWelcomeFooterMiddle: true、renderWelcomeHeader、renderWelcomeFooterwelcomeFooterfalse时省略后者以及customFootertrue时注入renderFooter与bottomStatusItems。这印证了上文 Props 语义——布局完全由宿主 Props 驱动因此同一 harness 可枚举出「有/无欢迎脚 × 有/无自定义页脚」的组合矩阵。关于 CLI 基线不适用性的说明文档特别指出对该 host-only 布局路径针对全局qwenCLI 的基线 dry-run不适用——CLI 不渲染 WebShell DOM也不暴露mobileWelcomeFooterMiddle、renderWelcomeHeader、renderWelcomeFooter这些宿主 Props因此无法触发该布局。可执行的基线就是上文基于真实 Chromium 的 composer-layout 挂载它在 CSS 修复前以「页脚到面板底部 419px 间距」复现了缺陷。这一说明对读者有实用价值验证该路径无需也无法通过 CLI 完成请直接跑 Playwright 用例。修复效果小结综合设计文档与仓库源码本次修复达成的可验证目标包括底部锚定≤760px 时 composer 页脚以绝对定位贴住聊天面板底部偏差 ≤1px 的量化断言欢迎内容层级正确欢迎头位于 composer 上方欢迎脚mobileWelcomeFooterMiddle模式下位于欢迎头与 composer 之间不遮挡前景、不捕获指针事件断点往返稳定761px 时移动绝对定位规则停用回调 760px 后底部锚定自动恢复输入可用锚定状态下 composer 可正常键入、触控设备使用 textarea 后端、草稿可清空而不提交组合变体覆盖有无欢迎脚、有无自定义页脚、有无状态面板的矩阵均有用例保障且display: contents变体的测量限制无盒模型、断言必须拒绝而非误报在测试中被显式处理web-shell.smoke.spec.ts。对需要定制 WebShell 空会话欢迎区的宿主开发者而言本文涉及的三个 Props 与 760px 断点规则构成了完整的接入契约对维护者而言上述 Playwright 用例则是该布局路径的回归防线可随时在本地以文档中的命令复现验证。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考