The stacked mount reads as one document in view mode — title, body and the thread share a single scroll

Preview, stacked (over/under): title, the rendered body and the comment
thread now stack in one continuous document with one scroll, instead of
the fixed ≈3:2 split with each pane keeping its own. Edit mode keeps the
split unchanged (an editor needs a stable scroll of its own), and the
beside mount is untouched.

CardBodySurface gains a `scrolls` flag: false switches off the hosted
NSScrollView's scroller and elasticity and reports the NSTextView's own
height for the proposed width via `sizeThatFits`, the layout-manager
height-fit trick CommentBodyView already uses one level up. CardCommentsPane
gains an `embeddedProxy`: supplied, it renders the same header, find bar,
rows and composer without wrapping them in a second ScrollView, driving
scrollTo off the outer document's proxy instead of its own. CardWindowView
composes the two behind a new pure predicate, CommentsMount.showsContinuousDocument(mode:),
tested in CardCommentsLayoutTests.

The continuous↔split swap within stacked mount is a genuine remount of the
body pane (two independent scrolls can't become one shared scroll by
reconfiguration) — the same accepted cost the raw-source outlet already
takes elsewhere in this window. No new animation on that swap, matching
this file's existing precedent (the raw-source swap and the beside↔stacked
mount switch are both instant cuts today). Decisions recorded on the card's
thread, flagged for owner review where they're user-visible.

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-09 12:30:41 -04:00
parent 7a4d27f62d
commit 6bf3308915
5 changed files with 256 additions and 87 deletions
+11
View File
@@ -58,6 +58,17 @@ struct CommentsMountTests {
#expect(CommentsMount.beside.widensWindow)
#expect(!CommentsMount.stacked.widensWindow)
}
@Test("The continuous document arrangement is Preview-only, and stacked-only")
func continuousDocumentIsStackedPreviewOnly() {
// Title, body and the thread share one scroll only when the mount is stacked *and* the body
// is showing Preview Edit needs its own stable scroll, and beside never had a split to
// fold away in the first place.
#expect(CommentsMount.stacked.showsContinuousDocument(mode: .preview))
#expect(!CommentsMount.stacked.showsContinuousDocument(mode: .edit))
#expect(!CommentsMount.beside.showsContinuousDocument(mode: .preview))
#expect(!CommentsMount.beside.showsContinuousDocument(mode: .edit))
}
}
// MARK: - The window's minimum