Skip to content

fix(desktop): keep the window controls and the context popover usable beside the work panel - #221

Merged
vastsa merged 2 commits into
vastsa:mainfrom
molicherry:fix/workpanel-controls-drag
Sep 11, 2026
Merged

vastsa merged 2 commits into
vastsa:mainfrom
molicherry:fix/workpanel-controls-drag

Conversation

@molicherry

Copy link
Copy Markdown
Contributor

Problem

Two surfaces break when the work panel is open on Windows/Linux.

  1. Window controls. minimize/maximize/close are renderer-drawn in a 120px band
    fixed to the window's top-right. With the panel open that band sits over the
    panel header, which is a -webkit-app-region: drag region and only padded its
    content clear of the band. A native drag rectangle is the element's border box,
    so the rectangle still spanned the band, and Electron consumed the controls'
    hover and click: they looked greyed out and did nothing.

  2. Context popover. The composer's context-usage popover is portaled to
    document.body and clamped horizontally against the viewport. With the panel
    open the trigger sits at the conversation pane's right edge, so the clamp
    pushed the popover onto the panel's column — where the panel's native browser
    and plugin views, which composite above every renderer layer, covered it. No
    z-index can lift a renderer layer over a native surface, so the summary read
    as clipped mid-glyph.

Change

  • work-panel.css: the win32/linux header reservation ends the header's box
    before the band (margin-right) instead of padding its content. The base 46px
    right padding keeps the content inset identical, so the panel layout is
    unchanged and the band's opaque surface covers the strip the header no longer
    paints. This restores the rule the stylesheet already applies to every other
    drag rectangle ("End every native drag rectangle before the window-control hit
    targets").
  • lib/context-inspector-position.ts (new) + ContextUsageInspector.tsx: the
    popover clamps to the conversation pane, whose right edge is exactly where the
    panel begins, and narrows with a narrow pane instead of crossing that edge.

Tests

  • context-inspector-position.test.mjs (new, 8 cases) — the first is the
    regression: with the trigger at the pane's right edge the popover must end
    inside the pane.
  • window-menu / work-panel / sidebar-navigation require the box-terminating
    reservation and reject the padding-only form.
  • E2E: the Windows/Linux chrome scenario asserts the window controls themselves
    take hover and click while the panel is open; the composer-inspector scenario
    gains a work-panel-open step.

Docs

Design system (geometric termination, and the native-surface rule for portaled
popovers), component spec, and both E2E scenarios updated; zh-CN mirrors synced.

Verification

  • pnpm --filter @pi-desktop/desktop typecheck — clean.
  • node --test test/*.test.mjs in apps/desktop — 1362 tests, 1340 pass, 20
    environment-only failures (macOS release scripts need bash/WSL and a POSIX exec
    bit; the fs-scope suite needs symlink privileges on Windows).
  • node scripts/check-style-tokens.mjs — OK.
  • Reported and re-tested by the user on a dev build of this branch.

@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

@molicherry is attempting to deploy a commit to the vastsa's projects Team on Vercel.

A member of the Team first needs to authorize it.

Windows/Linux draw minimize/maximize/close in a 120px band fixed to the
window's top-right corner. With the work panel open that band sits over the
panel header, which is a `-webkit-app-region: drag` region. The header only
padded its content clear of the band, and a native drag rectangle is the
element's border box, so the rectangle still spanned the band. Electron
consumes mouse input over a drag rectangle, so the controls received neither
hover nor click: they read as greyed out and did nothing.

End the header's box before the band instead (margin-right rather than
padding-right). The base 46px right padding keeps the content inset identical,
so the panel layout is unchanged and the band's opaque surface covers the strip
the header no longer paints.

Tests now require the box-terminating reservation and reject the padding-only
form. The design system, the component spec, and the Windows/Linux chrome E2E
scenario state the geometric termination rule, and that scenario now asserts
the window controls themselves take hover and click while the panel is open.
zh-CN mirrors are synced.
The composer's context-usage popover is portaled to `document.body`, positioned
in viewport coordinates, and clamped horizontally against the viewport
(`window.innerWidth`). With the work panel open the trigger sits at the
conversation pane's right edge, so that clamp pushed the popover onto the
panel's column — where the panel's native browser and plugin views, which
composite above every renderer layer, covered it. No z-index in the ladder can
lift a renderer layer over a native surface, so the summary read as clipped
mid-glyph.

Clamp against the conversation pane instead: its right edge is exactly where the
panel begins. `placeContextInspector` takes the trigger, popover, pane, and
viewport rects and returns the placement plus the widest box the pane can still
afford, so a pane narrower than the popover narrows the popover rather than
letting it cross the edge. The vertical above/below fallback is unchanged.

The design system, the component spec, and the composer-inspector E2E scenario
record the pane clamp and why a viewport clamp cannot work against native
surfaces; zh-CN mirrors are synced.
@molicherry
molicherry force-pushed the fix/workpanel-controls-drag branch from a864fbc to f10c370 Compare September 11, 2026 05:52
@vastsa
vastsa merged commit ac28d37 into vastsa:main Sep 11, 2026
3 of 4 checks passed
@vastsa

vastsa commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Reviewed and verified. The principle is sound: the pre-PR code left the work-panel header's native drag rectangle across the fixed Windows/Linux control band, and the body-portaled context inspector could be clamped into the native work-panel surface. The PR fixes both within the existing shell architecture and adds focused regression coverage plus synchronized specs/E2E documentation.

Validation against the fork head:

  • desktop typecheck passed
  • 1,364 desktop tests passed
  • style-token and 77-pair locale checks passed
  • Electron boot probe passed
  • protocol smoke passed 18/18; 2 credential-gated live-model cases skipped

The PR was merged intact into main as ac28d372. The only remote status failure was Vercel deployment authorization, unrelated to the code change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants