Repository navigation
feat(app): keep narrow desktop windows in the desktop layout - #58894
kitlangton wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
The code looks sound. I couldn't see it working here: Chromium won't launch in this environment (missing system libraries), so the e2e and component specs didn't run, and the Electron minimum-size change needs the real desktop app. The window-state and session-panel-width unit tests pass, and typecheck:tsc is clean in app and desktop. I read through the room and hysteresis logic, how the sidebar auto-hide drives the peek and the toggle command, the sheet's Escape handling next to the peek's, and the move from width-only media queries to isMobileLayout. I found nothing blocking.
Public API: one behaviour change for GUI extensions. In @opencode/gui-extensions/sdk, Layout.narrow() changes from "viewport under 768px" to "touch screen without hover, under 768px". The type is unchanged, but an extension that used narrow() to adapt to a small desktop window will now get false there. @opencode/ui also gains a ./mobile-layout export, which is additive and internal to the workspace. Config, the server API, the CLI and the client SDK are unchanged.
A few width-only styles are left, so narrow mouse windows still get them: the md: padding in the timeline and session route, and @media (max-width: 767px) in session-ui/src/pierre/index.ts. The pierre rule looks like a deliberate width rule. Please check the padding ones are meant to stay.
The stills and clips you mentioned will help here, since none of this could be checked on screen.
Related: #50459
e74f7f8 to
fa68fc1
Compare
There was a problem hiding this comment.
The new commit only touches patch-sticky-header.spec.ts. Under 768px it now emulates touch, like the other phone-layout specs, so the 390px case still exercises the phone layout. The wrapper is small and easy to follow, and I have nothing new to raise. I couldn't run the spec here because headless Chromium won't start in this environment. The public API impact is unchanged from my previous review.
There was a problem hiding this comment.
The new commit makes sense. The sheet decision now uses the shell's full row width, is made while the panel is open and is kept while it closes. That matches how the sidebar gives way: with the side panel open, the sidebar only stays docked if the content still has the docking width, so re-docking on close shouldn't turn a docked panel into a sheet. The peek's focus return and toggle-hover fix look right. I checked this by reading the code: typecheck:tsc in app is clean and the session-panel-width unit tests pass. I couldn't run the e2e specs here because headless Chromium won't launch. The public API impact is unchanged from earlier.
One small thing in the new test, inline.
| // Records whether the side panel ever floats as a sheet, on any frame, through an open and a close. | ||
| await page.evaluate(() => { | ||
| const sample = () => { | ||
| if (document.querySelector('[data-slot="session-side-panel-presence"].z-20')) |
There was a problem hiding this comment.
This sampler finds the sheet by its Tailwind class (.z-20). If that styling changes, the selector never matches and the "never became a sheet" check passes even when the bug is back. A dedicated attribute on the presence element (e.g. data-sheet set from sideSheet()) would keep this test checking the right thing.
There was a problem hiding this comment.
The new commit fixes the test selector point: the sampler now uses a data-sheet attribute, set under the same condition as the sheet styling, so the "never became a sheet" check can't pass by accident. typecheck:tsc in app is clean. I couldn't run the e2e spec here because headless Chromium won't launch. The public API impact is unchanged.
327eb9f to
d14a779
Compare
There was a problem hiding this comment.
This push rebases the change onto dev. I compared the change's own diff before and after the rebase: the differences only adapt to dev, where the panel-pinning code (sideMotion.pinned()), the side-panel toggle replay and the peek-enabled setting don't exist, and the sidebar is wider. The sheet logic and data-sheet are unchanged. typecheck:tsc is clean in app and desktop, and the window-state and session-panel-width unit tests pass. I couldn't run the e2e specs here because headless Chromium won't launch. Nothing new to raise. The public API impact is unchanged.
There was a problem hiding this comment.
The new commits only touch tests. The narrow-window test now expects the 276px sidebar width that is the default on dev, and settings.spec.ts gets a blank line for lint. Both are correct and I have nothing new to raise. The earlier test-selector thread was addressed by the data-sheet attribute. The public API impact is unchanged.
A desktop window narrower than 768px keeps the desktop layout instead of switching to the phone layout.
Before, narrowing the window swapped in bottom navigation, no titlebar, no hover and phone density. Now panes make room the way native apps do, and the phone layout is only for touch screens under 768px.
❌ Before
✅ After
📊 Proof: a 700px window with a mouse, headless Chromium, mocked server.
Unit tests pass (
session-panel-width: 10,window-state: 6). The new end-to-end case intabs.spec.ts(700px mouse window: sidebar floats on demand, side panel becomes a sheet) and the specs that now emulate touch for phone-layout checks were run before the latest rebase, not after.Layout.narrow()in the GUI extension SDK now means "touch screen under 768px" (same type).👀 Read:
shell/room.ts(the width rules),session/screen.tsx(the side panel sheet, which stays a sheet through its own close animation) andshell/shell.tsx(when the sidebar hides).isMobileLayoutin@opencode/ui/mobile-layoutis now the one place that decides the phone layout. Right-to-left layouts use logical properties and a mirrored sheet transform; checked in code, not on screen. Real Electron window resizing and full screen weren't exercised.Rebased onto dev, resolving conflicts in the shell, session screen, sidebar toggle and Home route · no user reports
Checks run
bun typecheck(packages/app, packages/desktop, after the rebase): cleanbun test … src/session/session-panel-width.test.ts(packages/app): 10 passbun test src/main/windows/window-state.test.ts(packages/desktop): 6 passbun run check(lint and typecheck): passAdded by the opencode bot (AI-generated).
Related: #50459
Public API: changes the meaning of the GUI extension SDK's Layout.narrow() from "viewport under 768px" to "touch screen under 768px" (type-compatible)