eleven / messenger Public

mac: translucent material band behind the composer row (iMessage-style) (#377)

In dark mode the feed scrolled fully-legible text behind the composer strip.
Now the input row (and its transient busy caption) rides ONE .bar material
band, so what passes beneath shows as blur — the iMessage treatment. Only the
row: the typeahead/banners/staged chips above stay transparent floaters, so
the band can never grow and curtain the chat (the failure that got the
original full-inset slab removed). iOS needs nothing — its composer already
wears floating-glass capsules.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Paul Campbell 27e88ae61e2ba54cc34b1ad6435fc2b512b55903 parent 153a864
1 file changed, +23 −15
  • ios/LChatMac/NativeFeedView.swift +23 −15
diff --git a/ios/LChatMac/NativeFeedView.swift b/ios/LChatMac/NativeFeedView.swift
index 20999d5..6a3e945 100644
--- a/ios/LChatMac/NativeFeedView.swift
+++ b/ios/LChatMac/NativeFeedView.swift
@@ -310,20 +310,11 @@ struct NativeFeedView: View {
}
}
.safeAreaInset(edge: .bottom) {
- VStack(spacing: 0) {
- composer
- // Transient feedback only (downloads, upload errors) — no
- // permanent status line.
- if let busyText {
- Text(busyText)
- .font(.caption2)
- .foregroundStyle(.secondary)
- .frame(maxWidth: .infinity)
- .padding(4)
- }
- }
- // No material slab: staged previews/banners float over the feed —
- // the .bar background grew with them and curtained the chat below.
+ // The material band lives on the input row INSIDE `composer`, never
+ // on this whole inset: staged previews/banners float transparent
+ // above it, so the band can't grow and curtain the chat (the
+ // failure that got the original full-inset .bar slab removed).
+ composer
}
// Track the feed's window frame so the swipe monitor only claims
// scroll events that happen over it.
@@ -583,7 +574,24 @@ struct NativeFeedView: View {
if editingID != nil {
composerBanner("Editing message", detail: nil) { cancelEdit() }
}
- composerRow
+ VStack(spacing: 0) {
+ composerRow
+ // Transient feedback only (downloads, upload errors) — no
+ // permanent status line.
+ if let busyText {
+ Text(busyText)
+ .font(.caption2)
+ .foregroundStyle(.secondary)
+ .frame(maxWidth: .infinity)
+ .padding(4)
+ }
+ }
+ .frame(maxWidth: .infinity)
+ // iMessage-style: the input row rides ONE translucent band, so the
+ // feed shows through it as material blur instead of fully-legible
+ // text (worst in dark mode). Only the row — the typeahead/banners
+ // above stay transparent floaters.
+ .background(.bar)
}
.onChange(of: draft) { _, text in
// Caret-at-end is the common case while typing; caret tracking for