feat: 内容型打开自动展开承载面板(宽视口)

宽视口下 openTab 带 path/url seed 时,承载落点 pane 的面板折叠则自动展开:
落点在底部树展开底部面板,否则展开右侧面板;去重聚焦既有 tab 同样展开
(打开必须落在视野内)。窄视口抽屉逻辑不变;类型型打开(+ 菜单、agent
终端自动补 tab)不展开。同步 AGENTS.md / README 文档与测试。
This commit is contained in:
Menghuan1918
2026-08-12 18:39:17 +08:00
parent ffc2270d77
commit cb9a7cf751
4 changed files with 90 additions and 14 deletions
+28 -9
View File
@@ -22,7 +22,7 @@
import type { ReactNode } from 'react'
import type { Context } from '../context-types.ts'
import {
activateTab, allLeaves, closeTab as closeTabReducer, openTabInActivePane, patchTab, togglePanel,
activateTab, allLeaves, closeTab as closeTabReducer, openTabInActivePane, patchTab, togglePanel, treeOf,
type SidebarState, type SidebarStore, type SidebarTab,
} from './state.ts'
import { isNarrowWidth } from './breakpoints.ts'
@@ -199,6 +199,13 @@ export interface BetterSidebarService {
* pre-set to the URL (the browser tab's navigation seed; the caller
* usually pairs it with a hostname `title`). A disabled tab type is a
* no-op.
*
* A CONTENT open (a `path` or `url` seed) must land in sight: when the
* panel hosting the landing pane is collapsed, it is expanded
* automatically (the right panel by default, the bottom panel when the
* active pane lives there; on narrow viewports the merged drawer opens).
* Type-only opens (the + menu, agent-terminal auto-tabs) never expand —
* the panel behavior is their caller's business.
*/
openTab(seed: { type: string; title?: string; path?: string; diff?: SidebarTab['diff']; id?: string; url?: string }): void
/** Close a tab by id. */
@@ -345,18 +352,30 @@ export function createBetterSidebarService(store: SidebarStore): BetterSidebarSe
} else {
landed = next
}
// Narrow-viewport drawer: a CONTENT open (file / browser) must be
// visible — expand the collapsed drawer so the open lands in sight.
// Type-only opens (+ menu, agent-terminal auto-tabs) never expand; on
// wide viewports nothing here changes (the panel behavior is the
// caller's business).
// A CONTENT open (file / browser) must land in sight: when the panel
// hosting the landing pane is collapsed, expand it. On narrow
// viewports the two workbenches merge into one drawer, so the drawer
// (panelOpen) is the only lever; on wide viewports the landing pane's
// own panel opens — the bottom panel when the active pane lives in the
// bottom tree, else the right panel. Type-only opens (+ menu,
// agent-terminal auto-tabs) never expand (the panel behavior is their
// caller's business). The check runs on the post-dedupe state, so a
// content open that merely FOCUSES an existing tab expands the panel
// too — the open must never land out of sight.
if (
typeof window !== 'undefined'
&& isNarrowWidth(window.innerWidth)
&& (seed.path !== undefined || seed.url !== undefined)
&& !landed.panelOpen
) {
return togglePanel(landed)
if (isNarrowWidth(window.innerWidth)) {
if (!landed.panelOpen) return togglePanel(landed)
} else {
const hostKey = treeOf(landed, landed.activePane ?? '')
if (hostKey === 'bottomSplits') {
if (!landed.bottomOpen) return { ...landed, bottomOpen: true }
} else if (!landed.panelOpen) {
return togglePanel(landed)
}
}
}
return landed
})