feat(v0.6): add Home (⌂) button to reach Sessions/Projects from a session

Once a project/session tab was open, the home chooser (Sessions/Projects
segmented control) was hidden and only reachable by closing every tab — no
way back to the Projects view to open another project.

Add a ⌂ Home button to the tab bar that overlays the chooser on top of the
open tabs (homeForced flag; updateHomeView shows home when no tab OR forced,
hiding the terminal panes). Clicking ⌂ again, clicking a tab (activate resets
homeForced), or opening another session/project dismisses the overlay.
Closing the last tab resets the flag. The button highlights while active.

Tests: +3 (tabs.test.ts). Full suite 415 green; both typechecks clean;
verified in-browser (open tab → ⌂ → Projects panel reachable → ⌂ → terminal).
This commit is contained in:
Yaojia Wang
2026-06-30 11:39:38 +02:00
parent 7b4adf5072
commit 985ff8a178
4 changed files with 117 additions and 2 deletions

View File

@@ -463,3 +463,51 @@ describe('TabApp — P6 openProject + home segmented control', () => {
expect(app.snapshot()[0]!.title).toBe('bare-repo')
})
})
describe('TabApp — Home (⌂) button: reach the chooser from an open session', () => {
it('overlays the home chooser over an open tab, then toggles back', () => {
const { paneHost, tabBar } = makeHosts()
const app = new TabApp(paneHost, tabBar)
app.newTab()
const seg = paneHost.querySelector('.home-seg') as HTMLElement
const homeBtn = tabBar.querySelector('.tab-home') as HTMLButtonElement
expect(homeBtn).not.toBeNull()
expect(seg.style.display).toBe('none') // terminal owns the screen
homeBtn.click() // overlay the home chooser
expect(seg.style.display).toBe('flex')
expect(launcherVisible.value).toBe(true) // default sessions view
expect(homeBtn.classList.contains('active')).toBe(true)
homeBtn.click() // back to the terminal
expect(seg.style.display).toBe('none')
expect(launcherVisible.value).toBe(false)
expect(homeBtn.classList.contains('active')).toBe(false)
})
it('can switch to Projects from the overlay and open another project', () => {
const { paneHost, tabBar } = makeHosts()
const app = new TabApp(paneHost, tabBar)
app.openProject('/p/one', 'one')
;(tabBar.querySelector('.tab-home') as HTMLButtonElement).click() // overlay home
;(paneHost.querySelectorAll('.home-seg-btn')[1] as HTMLButtonElement).click() // Projects
expect(projectsVisible.value).toBe(true)
app.openProject('/p/two', 'two') // opening dismisses the overlay
expect(app.snapshot()).toHaveLength(2)
const seg = paneHost.querySelector('.home-seg') as HTMLElement
expect(seg.style.display).toBe('none')
expect(projectsVisible.value).toBe(false)
expect((tabBar.querySelector('.tab-home') as HTMLButtonElement).classList.contains('active')).toBe(false)
})
it('⌂ is a no-op when no tab is open (home already shown)', () => {
const { paneHost, tabBar } = makeHosts()
new TabApp(paneHost, tabBar)
const seg = paneHost.querySelector('.home-seg') as HTMLElement
expect(seg.style.display).toBe('flex')
;(tabBar.querySelector('.tab-home') as HTMLButtonElement).click()
expect(seg.style.display).toBe('flex') // still shown, no crash
})
})