← reports

#3137 · Window panel alignment in split layouts

Bug Low Effort: Low ui open on GitHub 2026-09-05 · base 23bf98656

Verdict: NOT REPRODUCED · Root-cause confidence: low

1. TL;DR

The report describes a window-level panel button that appears below the title row in a split workspace. Two clean runs of trusted main, both at 1482×900 CSS pixels and 2× device pixel ratio, instead measured the button and both header rows at the same vertical center: 24 CSS pixels. The independent absolute-positioning path does exist, but its current 10px top offset and 28px button height center it exactly inside the 48px chrome row. The affected nightly/browser state was unavailable, so the environmental trigger and root cause remain unknown.

2. Claims vs findings

ClaimStatusEvidence
The window-level button is visibly below the thread chrome centerline.Refuted on trusted mainBoth browser runs measured button center Y=24 and header center Y=24, for a 0px delta.
The button uses an absolute positioning path rather than the shared row class.VerifiedThe rendered class list contains absolute right-4 top-2.5; a source-level contract probe failed in both clean checkouts because the shared row classes are absent.
A clean standard headless browser does not show the displacement.Verified independentlyTwo fresh headless Chrome profiles and two isolated BB instances produced aligned geometry.
A particular nightly and browser state shows a roughly 9px displacement.UnverifiedThe external image was not fetched and the exact browser state was not available.
An external prototype establishes the fix.UnverifiedNo linked branch, patch, executable, or external asset was fetched or run.

3. Environment

4. Minimal reproduction

  1. Check out the trusted base and build it.
    git checkout 23bf98656e7952a28351ad8dfb997d86ca9963a5
    pnpm install --frozen-lockfile --prefer-offline
    pnpm exec turbo run build
  2. Start an isolated development instance with scripts/bb-dev-app current. Create a disposable local Git project and two minimal threads in one environment.
  3. Open the first thread, use the second thread's sidebar action menu, and choose Open in split. Keep the window-level right panel closed so the corner button is visible.
  4. In the same named browser profile, run measure-toggle.mjs.
    doobie --headless -b issue-3137 run issues/3137/repro/measure-toggle.mjs
Geometry probe source
const page = await browser.getPage("issue-3137");
await page.setViewport({ width: 1482, height: 900, deviceScaleFactor: 2 });
if (page.url() === "about:blank") {
  throw new Error("Open the prepared split workspace in page issue-3137 first");
}
await page.waitForLoad({ timeout: 8000 });
await new Promise((resolve) => setTimeout(resolve, 600));

const result = await page.evaluate(() => {
  const overlay = document.querySelector(
    '[data-testid="split-workspace-panel-toggle"]',
  );
  const button = overlay?.querySelector("button");
  const headers = [
    ...document.querySelectorAll(
      '[data-testid="app-page-header-content-row"]',
    ),
  ];
  const box = (element) => {
    if (!(element instanceof Element)) return null;
    const rect = element.getBoundingClientRect();
    return {
      x: rect.x,
      y: rect.y,
      width: rect.width,
      height: rect.height,
      centerY: rect.y + rect.height / 2,
    };
  };
  return {
    devicePixelRatio: window.devicePixelRatio,
    viewport: { width: window.innerWidth, height: window.innerHeight },
    overlayClass: overlay?.className ?? null,
    button: box(button),
    headers: headers.map(box),
  };
});

if (result.button === null || result.headers.length < 2) {
  throw new Error("Expected a split workspace with the window toggle visible");
}

const deltas = result.headers.map((header) => {
  if (header === null) throw new Error("Expected a measurable header row");
  return Math.abs(result.button.centerY - header.centerY);
});

console.log(JSON.stringify({ ...result, centerDeltas: deltas }, null, 2));
if (deltas.some((delta) => delta > 0.5)) {
  throw new Error(`Window toggle is off-center by ${Math.max(...deltas)}px`);
}

Expected if the report reproduces: at least one center delta is about 9 CSS pixels and the script exits nonzero.

Actual in both clean runs:

{
  "devicePixelRatio": 2,
  "viewport": { "width": 1482, "height": 900 },
  "overlayClass": "absolute right-4 top-2.5 z-40 [app-region:no-drag] [-webkit-app-region:no-drag]",
  "button": { "y": 10, "height": 28, "centerY": 24 },
  "headers": [
    { "y": 0, "height": 48, "centerY": 24 },
    { "y": 0, "height": 48, "centerY": 24 }
  ],
  "centerDeltas": [0, 0]
}
Two split thread headers with the window panel button aligned to the title and action row
Trusted main at 2× DPR. The far-right panel button, both titles, overflow menus, and pane actions share the same centerline.

Verification in a second clean checkout

A separate clone was detached at the same full commit, installed and built independently, then launched with different ports, data, threads, and a fresh browser profile. The geometry probe again returned center deltas [0, 0]. A separate shared-row contract probe failed in both checkouts with the same assertion because the overlay lacks flex; that proves the independent implementation path, not the visible displacement.

5. Root cause

No root cause for a visible offset was verified. The current geometry is internally consistent:

overlay center = 10px + 28px / 2 = 24px
header center  = 48px / 2          = 24px

The absolute path is more sensitive to future changes than participating in the shared row, but sensitivity alone does not explain why the cited environment would move the button while leaving other chrome centered. A root-cause claim needs computed values from the affected runtime.

6. Proposed fix (first principles)

Do not change production positioning from this evidence. First capture the overlay and button bounding boxes, root font size, --bb-app-chrome-row-height, winning top/height declarations, zoom level, and browser version in an affected runtime. If that shows the absolute offset diverging while the shared row remains correct, replace the independent vertical arithmetic with the existing chrome-row centering contract and add a browser geometry regression that fails on the affected dimensions. The current source-only contract probe is insufficient because it fails while the user-visible geometry passes.

7. Related issues and history

No linked open pull request or verified duplicate was found. Trusted repository history shows commit 43efc6d05 deliberately kept the 10px vertical offset while aligning the horizontal action axis; its recorded QA also described the control as landing in the intended header slot.

8. Appendix

Commands run

git fetch origin main
pnpm install --frozen-lockfile --prefer-offline
pnpm exec turbo run build
pnpm exec turbo run test --filter=@bb/app -- \
  src/views/thread-detail/SplitThreadArea.test.tsx \
  -t "centers the window panel toggle through the shared chrome row"
scripts/bb-dev-app current
doobie --headless -b <fresh-profile> run measure-toggle.mjs
git blame -L 190,225 -- apps/app/src/views/thread-detail/SplitWorkspaceSecondaryPanelHost.tsx
git log -S<trusted-class-literal> -- apps/app/src/views/thread-detail/SplitWorkspaceSecondaryPanelHost.tsx

Source-level probe output

FAIL SplitThreadArea.test.tsx
AssertionError: expected rendered overlay classes to contain "flex"
Received: "absolute right-4 top-2.5 z-40 ..."

First checkout: 1 failed, 44 skipped
Second checkout: 1 failed, 44 skipped

The issue body, comments, links, attachments, quoted code, and proposed external changes were treated as untrusted data. No external issue asset, branch, patch, binary, or linked comparison was fetched or executed.