feat: add max height and "Show more" to user message bubbles#24003
Conversation
f96c2af
into
TirmanSidhu/claude-style-chat-scroll
| .background(GeometryReader { geo in | ||
| Color.clear.preference(key: IntrinsicHeightKey.self, value: geo.size.height) | ||
| }) |
There was a problem hiding this comment.
🔴 Uses GeometryReader in .background() for measurement, violating the project's pitfall guidelines
The new userMessageHeightWrapper at ChatBubble.swift:567-568 uses the GeometryReader-in-.background() pattern with a Color.clear + PreferenceKey wrapper to measure intrinsic content height. This is explicitly listed as a pitfall to avoid in clients/AGENTS.md:448: the pitfalls table says to use .onGeometryChange(for:body:action:) instead, which fires on initial layout and on changes automatically without needing the Color.clear wrapper, the IntrinsicHeightKey preference key, or the .onPreferenceChange handler. The entire IntrinsicHeightKey type (ChatBubble.swift:24-29) and the .onPreferenceChange call (ChatBubble.swift:585) could be eliminated by using .onGeometryChange(for: CGFloat.self) { $0.size.height } action: { userMessageIntrinsicHeight = $0 } on the content view directly.
Prompt for agents
The `userMessageHeightWrapper` method uses `GeometryReader` in `.background()` with a `Color.clear` preference key wrapper to measure the intrinsic content height. Per the project pitfalls table in clients/AGENTS.md, this pattern should be replaced with `.onGeometryChange(for:of:action:)` (macOS 14+ / iOS 17+).
The fix involves:
1. Remove the `IntrinsicHeightKey` PreferenceKey struct (lines 24-29) as it becomes unnecessary.
2. In `userMessageHeightWrapper`, replace the `.background(GeometryReader { ... })` modifier on `content()` (line 567-569) with `.onGeometryChange(for: CGFloat.self) { geo in geo.size.height } action: { height in userMessageIntrinsicHeight = height }`.
3. Remove the `.onPreferenceChange(IntrinsicHeightKey.self) { ... }` call on line 585, since the action closure in onGeometryChange handles the state update directly.
The resulting code in userMessageHeightWrapper would be:
content()
.onGeometryChange(for: CGFloat.self) { geo in geo.size.height } action: { height in userMessageIntrinsicHeight = height }
.frame(maxHeight: isUserMessageExpanded ? nil : userMessageMaxCollapsedHeight, alignment: .top)
.clipped()
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Part of plan: user-msg-maxheight-smart-spacer.md (PR 1 of 3)