Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/app/src/context/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ const DEFAULT_FILE_TREE_WIDTH = 200
// amicode#105: single-pane Work Column — it no longer hosts the review
// panel's two-pane split, so it doesn't need the old 400px. Resize handle
// retained; persisted widths still override this default.
const DEFAULT_PANEL_COLUMN_WIDTH = 320
// Must be >= WORK_COLUMN_WIDTH_MIN (330) so the default never triggers the
// floor in clampWorkColumnWidth, which would make the container wider than
// the side panel's <aside> and create an asymmetric right-side gap.
const DEFAULT_PANEL_COLUMN_WIDTH = 330
const DEFAULT_SESSION_WIDTH = 600
const DEFAULT_TERMINAL_HEIGHT = 280
const DEFAULT_REVIEW_PANEL_OPENED = false
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/pages/session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ export default function Page() {
const sessionPanelAvailable = createMemo(() => {
const width = panelRowWidth()
if (width === undefined) return undefined
return width - (settings.general.newLayoutDesigns() ? 8 : 0)
return width - (settings.general.newLayoutDesigns() ? 6 : 0)
})
const sessionPanelMax = createMemo(() => {
const available = sessionPanelAvailable()
Expand Down Expand Up @@ -2409,7 +2409,7 @@ export default function Page() {
ref={panelRow}
class="flex-1 min-h-0 flex flex-col md:flex-row"
classList={{
"gap-2 p-2": settings.general.newLayoutDesigns(),
"gap-1.5 px-1.5 py-2": settings.general.newLayoutDesigns(),
}}
>
<Show when={!isDesktop() && !!params.id && !settings.general.newLayoutDesigns()}>{mobileTabs()}</Show>
Expand Down
16 changes: 16 additions & 0 deletions packages/app/src/pages/session/session-panel-width.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"
import {
clampSessionPanelWidth,
clampWorkColumnWidth,
floorPanelColumnWidth,
REVIEW_PANE_WIDTH_MIN,
REVIEW_PANE_WIDTH_MIN_SPLIT,
SESSION_PANEL_WIDTH_MIN,
Expand Down Expand Up @@ -78,4 +79,19 @@ describe("work column width (amicode#105 — the column is bounded, the CHAT is
expect(sessionChatTakesRemainder({ newDesign: true, columnVisible: false })).toBe(false)
expect(sessionChatTakesRemainder({ newDesign: false, columnVisible: true })).toBe(false)
})

test("floorPanelColumnWidth lifts a stored width below the work column minimum", () => {
// Regression: DEFAULT_PANEL_COLUMN_WIDTH was 320 while WORK_COLUMN_WIDTH_MIN
// was 330. The work column container used clampWorkColumnWidth (which floors
// at 330) but the side panel's <aside> used the raw stored width (320),
// leaving a 10px transparent gap that merged with the 8px panelRow padding
// for 18px of right-side gap vs only 8px on the left.
expect(floorPanelColumnWidth(320)).toBe(WORK_COLUMN_WIDTH_MIN)
expect(floorPanelColumnWidth(100)).toBe(WORK_COLUMN_WIDTH_MIN)
})

test("floorPanelColumnWidth passes through widths at or above the minimum", () => {
expect(floorPanelColumnWidth(WORK_COLUMN_WIDTH_MIN)).toBe(WORK_COLUMN_WIDTH_MIN)
expect(floorPanelColumnWidth(500)).toBe(500)
})
})
9 changes: 9 additions & 0 deletions packages/app/src/pages/session/session-panel-width.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ export function clampWorkColumnWidth(input: { width: number; available: number |
return Math.min(Math.max(input.width, WORK_COLUMN_WIDTH_MIN), workColumnWidthMax(input.available))
}

/** Floor for the side panel's own width — ensures the `<aside>` never renders
* narrower than its work column container (which uses `clampWorkColumnWidth`).
* Without this, a stored width below the column floor creates a transparent gap
* between the panel's right edge and the column boundary, inflating the
* perceived right-side padding. */
export function floorPanelColumnWidth(width: number): number {
return Math.max(width, WORK_COLUMN_WIDTH_MIN)
}

/** In v2 with the work column visible, the chat is the flex remainder (no
* fixed pixel width). Classic layout keeps the historical fixed chat width. */
export function sessionChatTakesRemainder(input: { newDesign: boolean; columnVisible: boolean }): boolean {
Expand Down
7 changes: 5 additions & 2 deletions packages/app/src/pages/session/session-side-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import {
} from "@/pages/session/helpers"
import { setSessionHandoff } from "@/pages/session/handoff"
import { useSessionLayout } from "@/pages/session/session-layout"
import { WORK_COLUMN_WIDTH_MIN } from "@/pages/session/session-panel-width"
import { floorPanelColumnWidth, WORK_COLUMN_WIDTH_MIN } from "@/pages/session/session-panel-width"
import { SessionFileBrowserTab, type SessionFileBrowserState } from "@/pages/session/v2/session-file-browser-tab"

type PulseInspectorStage = "optimization" | "calibration" | "compilation"
Expand Down Expand Up @@ -325,7 +325,10 @@ export function SessionSidePanel(props: {
if (!open()) return "0px"
// the tabs column owns its width (never flex-fills the window) and can be
// dragged much narrower — Kate 2026-07-27
if (reviewOpen()) return `${layout.panelColumn.width()}px`
// Floor at WORK_COLUMN_WIDTH_MIN so the <aside> always fills its work column
// container (which uses clampWorkColumnWidth); without this a stored width
// below the floor leaves a transparent gap on the right side.
if (reviewOpen()) return `${floorPanelColumnWidth(layout.panelColumn.width())}px`
return `${fileTreeWidth()}px`
})
const treeWidth = createMemo(() => (fileOpen() ? `${fileTreeWidth()}px` : "0px"))
Expand Down
Loading