Voyager 侧边栏自动隐藏(Sidebar Auto-Hide):让 Gemini 聊天界面更沉浸的完整指南
2026/9/21 15:24:42 网站建设 项目流程

Voyager 侧边栏自动隐藏(Sidebar Auto-Hide):让 Gemini 聊天界面更沉浸的完整指南

【免费下载链接】voyagerEnhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用于任意网站,如 DeepSeek Harness。项目地址: https://gitcode.com/gh_mirrors/ge/voyager

导读:本文讲解 Voyager 浏览器扩展为 Google Gemini 提供的侧边栏自动隐藏(Masquage automatique de la barre latérale)功能——当鼠标离开侧边栏区域时自动收起、移回时自动展开,从而最大化聊天区可视面积。你将掌握从面板开启该功能的完整操作步骤,并通过仓库源码深入理解它的底层实现:鼠标进出延迟、全隐藏(Full-Hide)模式、边缘触发区、预测式瞄准(Predictive Aiming)等关键机制,以及针对 Gemini 页面 DOM 的适配策略。

功能概述:什么是侧边栏自动隐藏

在 Gemini 的聊天界面中,左侧栏(会话列表、导航菜单)长期占据屏幕宽度。Voyager 提供的自动隐藏侧边栏功能专门解决这一问题:开启后,当鼠标离开侧边栏所在的区域,侧边栏自动收缩;当鼠标再次移入该区域,侧边栏自动展开。整体体验类似浏览器 DevTools 的自动隐藏抽屉,让聊天区在不需要侧边栏时获得完整的视觉宽度。

该功能面向“更沉浸的聊天体验”这一场景设计,特别适合需要长时间阅读长对话、宽屏显示时希望内容区铺满的 Gemini 用户。

当前支持范围

注意:该功能目前仅支持 Google Gemini 站点,不支持 AI Studio、Claude、ChatGPT 等其他站点。这与 docs/fr/guide/sidebar-auto-hide.md 中的说明一致——从源码角度看,其 DOM 适配(bard-sidenavside-navigation-content等选择器)完全是围绕 Gemini 的页面结构编写的。

如何开启:三步完成配置

按照以下步骤即可在 Voyager 面板中启用:

  1. 打开 Voyager 配置面板:点击浏览器工具栏中的 Voyager 扩展图标。
  2. 进入布局设置:在面板中找到侧边栏行为相关的设置分组(对应源码中的 “Sidebar Behavior” 卡片,见 PopupLayoutSettings.tsx)。
  3. 开启开关:找到Masquer auto barre latérale(自动隐藏侧边栏)选项并打开开关。

开启后无需刷新页面,扩展会立即生效——首次开启时若鼠标不在侧边栏上且没有弹窗打开,侧边栏会在约 500ms 后自动收起。

相关的第二个开关:完全隐藏(Full-Hide)

在同一个设置卡片中还有一个关联选项Masquer complètement la barre latérale(完全隐藏侧边栏)。它与自动隐藏配合使用:当侧边栏处于收起状态(无论是自动隐藏还是手动收起)时,将其宽度彻底归零,连收起的窄条也一并隐藏,进一步释放屏幕空间。法语版界面文案可在 messages.json 中查到。

这两个开关的偏好设置通过chrome.storage.sync持久化(存储键为gvSidebarAutoHidegvSidebarFullHide,见 common.ts),因此会跟随浏览器账号跨设备同步。

源码级实现:自动隐藏是怎么工作的

自动隐藏功能的核心实现位于 src/pages/content/sidebarAutoHide/index.ts,文件头注释(L1-L11)明确描述了其两大职责:

  • Auto-hide:鼠标离开时侧边栏自动收起,移入时自动展开;
  • Full-hide:侧边栏收起后(无论由自动隐藏还是手动触发)彻底隐藏,宽度归零。

实现通过点击 Gemini 页面的side-nav-menu-button切换按钮来改变侧边栏状态,而不是直接修改 Gemini 的样式表。

1. 设置读取与实时监听(入口逻辑)

入口函数startSidebarAutoHide()(index.ts)执行三件事:

  1. 首次读取存储中的两项设置(默认均为false),据此调用enable()/enableFullHide()
  2. 注册chrome.storage.onChanged监听器,仅响应sync区域的变更,实现开关切换时无需刷新页面即可热生效
  3. beforeunload时清理,确保页面卸载时关闭自动隐藏,避免影响其他页面。

2. 鼠标进出:延迟与防误触

自动隐藏对鼠标事件的响应采用双重延迟防抖策略(index.ts):

  • LEAVE_DELAY_MS = 400:鼠标离开侧边栏后等待 400ms 才收起,防止鼠标快速划过边缘时误触收起;
  • ENTER_DELAY_MS = 150:鼠标移入后等待 150ms 才展开,同样用于过滤“快速穿越”场景。

handleMouseEnterhandleMouseLeave(L681-L717)分别设置这两个定时器,并在对方事件到来时先取消未决定时器,避免“进入-离开-进入”的抖动。

测试用例专门验证了这一防误触逻辑:“does not expand on quick sidebar hover pass-through”(见 SidebarAutoHide.test.ts)——鼠标在 80ms(小于 150ms)内进出侧边栏,展开定时器不应触发。

3. 何时暂停收起:弹窗与菜单保护

侧边栏在以下场景下不会自动收起(collapseSidebar()的前置检查,见 L571-L583):

  • 存在keepExpandedLocks锁(如引导提示 Coachmark 持有期间);
  • 处于暂停窗口(isPaused(),例如用户刚点击过菜单项后 1500ms 内);
  • 有弹窗或对话框打开(isPopupOrDialogOpen(),包括 Material 对话框、菜单面板,以及 Voyager 自己的.gv-folder-dialog.gv-color-picker-dialog等自定义弹层,见 L458-L477);
  • 鼠标仍在侧边栏区域或其悬停的弹层上。

其中文件夹颜色选择器保护有对应的测试用例(“does not collapse when folder color picker is open”,见 SidebarAutoHide.test.ts):颜色选择器打开时触发 mouseleave 不应收起,关闭后再次 mouseleave 才正常收起。

4. 菜单点击暂停

handleMenuClick(L505-L547)在捕获阶段监听全局click事件:当点击侧边栏切换按钮、role="menuitem"菜单项、侧边栏内按钮或 “Options / 选项 / More” 类按钮时,会调用pauseAutoCollapse(1500)MENU_CLICK_PAUSE_MS),给后续弹出的对话框或菜单留出操作时间,避免刚点开菜单侧边栏就收起。

Full-Hide 完全隐藏:从收起窄条到零宽度

仅靠自动隐藏,Gemini 收起后仍保留一条窄侧栏。Full-Hide 通过注入 CSS 类的方式将其宽度压到 0:

两级 CSS 类控制

  • gv-sidebar-full-hide-collapsing:收起动画进行中的中间态——先将当前宽度固化为内联样式,再过渡到0px,实现平滑动画;
  • gv-sidebar-full-hide-collapsed:最终态——对bard-sidenavside-navigation-content及其内容容器强制width: 0min-width: 0max-width: 0flex-basis: 0overflow: hiddenpadding: 0(getFullHideStyle())。

过渡动画

getTransitionStyle()(L123-L133)为侧边栏及其内容层注入0.26s cubic-bezier(0.4, 0, 0.2, 1)的宽度/位移过渡,配合will-change提示,使收起与展开都平滑自然。

测试“delays full-hide after auto-collapse so the native close animation can run”(SidebarAutoHide.test.ts)验证了完整时序:自动收起后先进入collapsing中间态(宽度为0px且带!important优先级),260ms 后才进入collapsed终态,再过 240ms 动画类被清除。

边缘触发区:如何重新唤出

Full-Hide 启用后,页面左侧会注入一个 6px 宽、100vh 高的透明热区(gv-sidebar-edge-trigger,见createEdgeTrigger()L212-L230,EDGE_TRIGGER_WIDTH = 6)。鼠标移入该热区即触发handleMouseEnter展开侧边栏。

需要说明的是:Full-Hide 的边沿热区只在自动隐藏(Auto-Hide)同时开启时才参与展开逻辑;仅开启 Full-Hide 时,热区存在但不会响应鼠标展开(对应测试“does not reveal from the full-hide edge trigger when auto-hide is disabled”,L146-L184)。

预测式瞄准:消除“等待感”的细节优化

这是实现中非常有趣的一个细节(L60-L69 注释明确说明其灵感来自 “Amazon mega-menu” 技巧):在document级别监听mousemove,追踪鼠标速度与方向

  • 当鼠标位于距左边缘PREDICTIVE_ZONE_WIDTH = 100px范围内,且向左移动速度超过PREDICTIVE_VELOCITY_THRESHOLD = -0.5 px/ms时,在mouseenter事件触发之前就预展开侧边栏,彻底消除用户感知到的“等待”;
  • 采样节流PREDICTIVE_THROTTLE_MS = 50ms,并丢弃间隔超过 200ms 的陈旧采样(如切换标签页后的残留数据);
  • 安全兜底:若预展开后鼠标始终没有真正进入侧边栏(中途改变方向),PREDICTIVE_SAFETY_COLLAPSE_MS = 1200ms后自动重新收起。

测试套件中的 “predictive aiming” 分组(SidebarAutoHide.test.ts)覆盖了快速逼近展开、慢速不展开、仅 Full-Hide 时不展开、预展开后未进入则自动收回等四种场景。

与 Gemini 页面结构的适配:多种布局兼容

Gemini 页面结构随版本演化,Voyager 为此维护了多套选择器与状态判定策略

切换按钮发现

findToggleButton()(L255-L294)按优先级尝试:

  1. button[aria-label="Open sidebar"]/button[aria-label="Close sidebar"]
  2. side-nav-sparkle-button buttonbutton[data-test-id="side-nav-menu-button"]side-nav-menu-button button(旧版布局);
  3. 通过mat-icon[fonticon]side_nav/side_nav_expand)反查最近的<button>——因为 aria-label 是本地化的,而图标字形的 ligature 名称与语言无关,是 i18n 稳定的锚点。

此外,2026 新版布局会同时渲染两个匹配按钮(一个可见、一个 0×0 占位),因此代码用querySelectorAll遍历并过滤零几何元素,确保点击落到真正可见的按钮上(对应测试“picks the visible Close-sidebar button and skips the 0×0 invisible copy”,L554-L603;以及“finds the toggle via mat-icon fonticon when aria-label is localized”,L605-L640)。

收起状态判定

getStructuredSidebarCollapsedState()/isSidebarCollapsed()(L316-L346)综合多种信号:bard-sidenav或其内容容器上的collapsed类、切换按钮的 icon/aria-label 状态、mat-sidenav-openedbody 类,最后回退到侧边栏几何宽度(< 80px 视为收起)。这种多信号判定让功能在 Gemini 不同改版中都能正确识别当前状态。

动态 DOM 的韧性

Gemini 是单页应用,DOM 会不断重建。Voyager 采用三层机制保证监听不失效:

  • MutationObserver监听document.body的子树变更(OBSERVER_DEBOUNCE_MS = 100ms防抖,避免展开时数百行会话渲染引发的同步扫描风暴,注释 L45-L48);
  • windowresize事件(200ms 防抖,并在 600ms 后再复查一次);
  • 每秒一次的setInterval兜底轮询(SIDENAV_CHECK_INTERVAL_MS = 1000)。

三者共同驱动checkAndReattach():侧边栏节点被重建时自动重挂事件监听,并同步 Full-Hide 的边缘热区显隐。

工程配套:如何查看测试与本地验证

该功能的单元测试集中在 src/pages/content/sidebarAutoHide/tests/SidebarAutoHide.test.ts,使用 Vitest 的假定时器(vi.useFakeTimers())验证延迟逻辑,并 mockgetBoundingClientRect模拟可见几何。覆盖的关键行为包括:

  • 弹窗/颜色选择器打开时禁止收起;
  • 快速掠过不展开;
  • Full-Hide 的收起/展开时序与边沿热区显隐;
  • Coachmark 持锁期间保持展开(keepSidebarExpanded(),对应实现 index.ts);
  • 预测式瞄准的正反例与安全收回。

若想在本地运行这些测试,可执行bun test(仓库使用 Bun 作为包管理器,见根目录 bun.lock 与 package.json),或针对该文件运行bun test src/pages/content/sidebarAutoHide/__tests__/SidebarAutoHide.test.ts

小结

Voyager 的侧边栏自动隐藏远不止一个简单的“鼠标进出开关”:

  • 操作层面:面板中两个开关即可启用(自动隐藏 + 完全隐藏),偏好随账号同步;
  • 交互层面:400ms/150ms 的进出延迟防抖、弹窗与菜单保护、菜单点击暂停,把误触概率降到最低;
  • 体验层面:预测式瞄准让“滑向边缘展开”几乎无感知延迟,260ms 的 CSS 过渡让收起动画顺滑;
  • 工程层面:多选择器发现、多信号状态判定、MutationObserver + resize + 轮询三保险,让功能在 Gemini 页面改版后依然可靠。

对追求沉浸式聊天体验的 Gemini 用户来说,这是一组开箱即用、又能从源码中读出设计细节的高质量功能。它的完整实现与测试均可在此仓库中查看:实现见 src/pages/content/sidebarAutoHide/index.ts,面板入口见 src/pages/popup/components/PopupLayoutSettings.tsx,测试见 src/pages/content/sidebarAutoHide/tests/SidebarAutoHide.test.ts。

【免费下载链接】voyagerEnhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用于任意网站,如 DeepSeek Harness。项目地址: https://gitcode.com/gh_mirrors/ge/voyager

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询