Skip to Content
开发者指南守护进程 UIWebShell 侧边栏 — 自定义指南

WebShell 侧边栏 — 自定义指南

WebShellSidebar 是在 web-shell App 组件中渲染的会话列表和导航面板。本文档将每个可视区域映射到其当前的自定义能力,并标识没有外部注入点的区域。

启用侧边栏

侧边栏默认禁用。传递 sidebar prop 以启用:

import { WebShellWithProviders } from '@qwen-code/web-shell'; <WebShellWithProviders baseUrl="http://localhost:4170" sidebar={true} // 简单启用 // 或使用细粒度选项: // sidebar={{ enabled: true, defaultCollapsed: false, ... }} />;

布局概览

┌─────────────────────────────────────┐ │ ① 品牌区(topRow) │ ✅ 可自定义 ├─────────────────────────────────────┤ │ ② 主导航 │ ✅ 可自定义 │ [+ 新任务] [🧩 插件] │ │ [📅 定时任务] [🎯 目标] │ │ [自定义渲染...] │ ├─────────────────────────────────────┤ │ ③ 项目头部 │ ✅ 显示/隐藏 │ 📁 项目 ▼ [🔍] [+] │ │ 会话列表条目... │ │ 📦 已归档会话 │ ├─────────────────────────────────────┤ │ ④ 底部操作栏 │ ✅ 可自定义 │ [⚙ 设置] v0.19 [☀] [▦] [◧] │ ├─────────────────────────────────────┤ │ ⑤ 拖拽手柄 │ ❌ 不可自定义 └─────────────────────────────────────┘

可自定义区域

① 品牌区 — branding

interface WebShellSidebarBranding { render?: () => ReactNode; // 替换整个品牌行 hideWhenCompact?: boolean; // 侧边栏折叠时隐藏(默认:true) }
效果
undefined(默认)已解析品牌:brand prop → daemon GET /brand → 内置 Qwen logo + “Qwen Code” 文本
false完全隐藏品牌行
{ render: () => <MyHeader /> }使用自定义内容完全替换
{ hideWhenCompact: false }在折叠的图标栏模式下保持品牌区可见

默认行是数据驱动的,而非固定不变:提供 ui.brand 配置的 daemon 会替换文本和标识,嵌入宿主可以通过 shell 组件的 brand prop 覆盖两者(onBrandResolved 会向宿主自身的 chrome 报告解析结果)。branding.render 仍然是最高优先级的覆盖——它优先于 prop 和 daemon 解析的值,与之前完全一致。

sidebar={{ branding: { render: () => ( <div style={{ display: 'flex', gap: 8 }}> <img src="/my-logo.svg" alt="" width={24} /> <span>My App</span> </div> ), }, }}

② 主导航 — primaryNav

type WebShellSidebarPrimaryNavItem = | 'newTask' // ✏️ 新任务按钮 | 'plugins' // 🧩 插件按钮 | 'scheduledTasks' // 📅 定时任务按钮 | 'goals'; // 🎯 目标按钮 interface WebShellSidebarPrimaryNavOptions { items?: readonly WebShellSidebarPrimaryNavItem[]; // 显示哪些内置按钮(默认:全部) render?: () => ReactNode; // 内置按钮之后的额外自定义内容 }

主导航区域包含由 items 控制的内置按钮:

  • 未指定 items 时默认显示所有按钮
  • 提供 items 时仅显示列出的按钮
  • 可通过 render() 在内置按钮之后添加自定义内容
效果
undefined(默认)显示所有内置按钮
{ items: ['plugins'] }仅插件按钮
{ items: ['plugins', 'scheduledTasks'] }插件 + 定时任务
{ items: [], render: () => ... }隐藏所有内置按钮,仅显示自定义内容
sidebar={{ primaryNav: { items: ['plugins', 'scheduledTasks'], // 隐藏 newTask 和 goals render: () => ( <button onClick={() => console.log('custom action')}> 🔗 数据同步 </button> ), }, }}
type WebShellSidebarFooterItem = | 'settings' // ⚙ 设置面板 | 'version' // 版本标签(例如 "v0.19.10") | 'theme' // ☀/🌙 亮色/暗色切换 | 'sessionsOverview' // ▦ 会话概览面板 | 'splitView' // ◧ 分屏视图(仅大屏幕) | 'daemonStatus' // 📊 daemon 状态面板 | 'collapse'; // ◁/▷ 折叠/展开切换 interface WebShellSidebarFooterOptions { items?: readonly WebShellSidebarFooterItem[]; // 显示哪些内置项(默认:全部) render?: () => ReactNode; // 在左侧、内置项之前渲染的自定义内容 }
效果
undefined(默认)显示所有项
false完全隐藏底部栏;移动端抽屉仅保留关闭控件
{ items: ['settings', 'theme', 'collapse'] }仅显示列出的项;移动端抽屉始终保留关闭控件

底部栏会自动适应窄宽度:标签会被隐藏,版本信息在某些阈值以下会被移除。

sidebar={{ footer: { items: ['theme', 'collapse'] }, // 极简底部栏 }}

通过 render() 添加的自定义内容出现在底部栏的左侧,在内置项之前:

sidebar={{ footer: { items: ['collapse'], render: () => ( <button onClick={() => openHelpCenter()}> ❓ 帮助 </button> ), }, }}

注意: 'scheduledTasks''goals' 已移至主导航区域(②),默认显示。它们由 primaryNav.items 控制,而非 footer.items

其他顶级选项

interface WebShellSidebarOptions { enabled?: boolean; // 显示/隐藏侧边栏(传入时为 true) defaultCollapsed?: boolean; // 初始折叠状态(持久化到 localStorage) showCompactToggle?: boolean; // 在聊天区域显示折叠按钮(默认:true) showSessionSourceSwitch?: boolean; // 显示 Tasks/Channels 切换(默认:true) showLive?: boolean; // 显示 daemon 拥有的 Live 会话(默认:false) branding?: false | WebShellSidebarBranding; primaryNav?: WebShellSidebarPrimaryNavOptions; hideProjectHeader?: boolean; // 隐藏"项目"头部行(默认:false = 显示) sessionActions?: WebShellSidebarSessionActionsOptions; footer?: false | WebShellSidebarFooterOptions; }

Session source switch — showSessionSourceSwitch

当嵌入宿主只需显示普通任务会话时,将 showSessionSourceSwitch 设为 false

sidebar={{ showSessionSourceSwitch: false, }}

这会移除 Tasks/Channels 切换,并将所有活跃、已归档、主会话和次级会话查询固定为 sourceType: "default"。省略该选项则保持当前的切换和 channel-session 访问不变。

Live 会话 — showLive

Live 会话默认对嵌入宿主隐藏。当宿主需要暴露 daemon 拥有的 Live 分组时,选择启用:

之前的版本在没有显式选项的情况下显示此分组,因此依赖它的宿主在升级时必须设置 showLive: true

sidebar={{ showLive: true, }}

③ 项目头部 — hideProjectHeader

控制”项目”头部行的可见性(包含折叠切换、搜索图标和添加 workspace 按钮的那一行)。默认为 false(显示)。

sidebar={{ hideProjectHeader: true, // 隐藏"项目 ▼ [🔍] [+]"行 }}

隐藏后,会话列表条目和已归档会话仍然显示——带有操作按钮的头部行和会话搜索栏会被移除。

会话行操作 — sessionActions

type WebShellSidebarSessionActionItem = | 'details' // 📝 详情(下拉子菜单) | 'rename' // ✏️ 重命名(下拉菜单) | 'group' // 📁 分组/移动到文件夹(下拉菜单) | 'export' // 📤 导出聊天记录(下拉菜单) | 'delete' // 🗑 删除会话(下拉菜单) | 'pin' // 📌 置顶/取消置顶(内联按钮) | 'archive'; // 📦 归档(下拉菜单) /** Subset with working inline (hover-button) handlers. */ type WebShellSidebarSessionInlineActionItem = | 'pin' | 'rename' | 'export' | 'delete'; interface WebShellSidebarSessionActionsOptions { items?: readonly WebShellSidebarSessionActionItem[]; // 显示哪些操作(默认:全部) inlineItems?: readonly WebShellSidebarSessionInlineActionItem[]; // 哪些项作为内联按钮显示(默认:['pin']) }

控制会话行上显示哪些操作按钮:

  • items:所有操作的主控(包括内联和下拉)。如果某项不在 items 中,则在各处隐藏。
  • inlineItems:控制哪些项作为内联按钮(hover 时)显示。默认为 ['pin']。只有具有可用内联处理程序的项才能使用:'pin''rename''export''delete''details''group''archive' 仅支持下拉。

可见性优先级items AND 该项的内置条件 AND inlineItems 三者都必须通过,内联按钮才会显示。例如,delete 作为内联按钮需要 items 包含 'delete' AND inlineItems 包含 'delete'

效果
undefined(默认)显示所有操作,仅 pin 作为内联按钮
{ inlineItems: ['pin', 'delete'] }Pin + delete 作为内联按钮
{ inlineItems: [] }完全没有内联按钮
{ inlineItems: ['rename', 'export'] }Rename + export 作为内联按钮

当没有启用下拉项时,下拉触发器(⋮)会自动隐藏。内联按钮仅在其能力条件和 items 都包含它们时才会显示。Archive 在当前会话以及任何正在运行实时轮次的会话上会被禁用,因为 daemon 在归档时会关闭实时会话。

sidebar={{ sessionActions: { items: ['details', 'rename', 'export', 'delete', 'pin'], // 显示哪些操作(主控) inlineItems: ['pin', 'delete'], // pin + delete 作为内联按钮 }, }}

不可自定义区域

项目 / Workspaces(会话列表内部)

当会话列表可见时,以下子区域会被渲染但不可单独自定义

方面详情
数据来源useSessions() hook → daemon API(/sessions 端点)
会话列表排序按创建时间降序
会话行渲染内部 renderSessionRow useCallback — 不可注入
搜索 / 过滤内置搜索栏,客户端文本匹配
会话分组SessionGroupSection 组件,6 种预设颜色 + 自定义 hex
Workspace 分区每个 daemon workspace 一个 WorkspaceSection,不可替换
添加 workspace 对话框内置 AddWorkspaceDialog

⑤ 拖拽手柄

  • 右侧边缘的拖拽手柄,用于调整侧边栏宽度
  • 宽度持久化到 localStorage
  • 不可配置

运行时行为 props

这些 WebShellProps 间接影响侧边栏行为:

Prop效果
onNewSession覆盖新建会话处理程序
onLoadSession覆盖会话加载逻辑
onSessionIdChange响应会话切换
splitSessionIds从外部控制分屏会话
theme / onThemeChange控制 / 观察主题
language / onLanguageChange控制 / 观察 UI 语言

折叠和移动端状态

状态行为
展开带有文本标签的完整侧边栏
折叠图标栏模式(仅 logo、笔图标、操作图标)
移动端抽屉使用其容器的 70% 宽度,在宽度限制内,带有背景遮罩和底部栏关闭控件

折叠状态持久化在 localStorage 中,键名为 qwen-code-web-shell-sidebar-collapsed

调整后的桌面端宽度仅在展开布局中恢复。打开或关闭移动端抽屉不会覆盖该宽度或持久化的桌面端折叠偏好。

源码位置

组件文件
WebShellSidebarpackages/web-shell/client/components/sidebar/WebShellSidebar.tsx
SessionGroupSectionpackages/web-shell/client/components/sidebar/SessionGroupSection.tsx
WorkspaceSectionpackages/web-shell/client/components/sidebar/WorkspaceSection.tsx
Sidebar stylespackages/web-shell/client/components/sidebar/WebShellSidebar.module.css
App integrationpackages/web-shell/client/App.tsx(搜索 WebShellSidebar
Entry point (dev)packages/web-shell/client/main.tsxsidebar: { enabled: true, showLive: true }
Last updated on