fix(chat,projects): clamp detail-column views so they don't grow the window

Two sibling fixes to the one landed in 4baa3d4 (Sessions tab
height clamp). User reported that both the Chat section and the
per-project Sessions tab expanded the window height past the
screen once their content grew intrinsically.

Root cause is the same for both: the outer VStack at the top of
each view had no `.frame(maxHeight: .infinity)`. When
NavigationSplitView's detail slot renders one of these, SwiftUI
asks the child for its ideal height. Without a clamp, a tall
enough child (RichChatView's message list; a long attributed-
sessions list; a dashboard with a text widget containing a long
README block) bubbles its intrinsic size all the way up and
macOS grows the window to fit.

ChatView: add `.frame(maxWidth: .infinity, maxHeight: .infinity)`
to the outer VStack in `body`. Pre-existing issue that predated
v2.3 — it just happened to be masked by the chat area having
enough give until now. Surfaced as the user exercised the
section more during v2.3 testing.

ProjectsView: add the same modifier to the "dashboard is loaded"
VStack branch in `dashboardArea`. The ContentUnavailableView
branches (no dashboard / no projects / no selection) don't need
it — ContentUnavailableView self-clamps.

Both the widgetsTab (ScrollView) and the siteTab (explicit
maxHeight) were already fine. The sessions tab picked up its
fix in 4baa3d4. These two commits together cover every surface
that lives in the detail column.

80/80 Swift tests still pass. Visual-only fix; no test change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-04-24 00:00:19 +02:00
parent 4baa3d4d28
commit 9aad9051c4
2 changed files with 17 additions and 0 deletions
@@ -15,6 +15,13 @@ struct ChatView: View {
errorBanner
chatArea
}
// Clamp the outer VStack to the detail column's offered
// space. Without this, the chat area's intrinsic height (a
// RichChatView whose message list grows with content) can
// bubble up through NavigationSplitView's detail slot and
// push the whole window past the screen. Same pattern as
// the Sessions tab fix in the v2.3 branch.
.frame(maxWidth: .infinity, maxHeight: .infinity)
.navigationTitle("Chat")
.task {
await viewModel.loadRecentSessions()
@@ -367,6 +367,16 @@ struct ProjectsView: View {
}
}
}
// Clamp the container VStack to the detail column's
// offered space. Without it, any tab whose content is
// taller than the window (long Sessions list, tall
// README block in a dashboard's text widget, etc.) can
// bubble its intrinsic height up through
// NavigationSplitView's detail slot and push the whole
// window past the screen. widgetsTab's own ScrollView
// and siteTab's explicit maxHeight both cooperate; the
// sessions tab needs this as well.
.frame(maxWidth: .infinity, maxHeight: .infinity)
} else if let error = viewModel.dashboardError {
ContentUnavailableView {
Label("No Dashboard", systemImage: "square.grid.2x2")