From ed3e680b91af1b9659212d77aa4b703612e5e821 Mon Sep 17 00:00:00 2001 From: Shane Rosenthal Date: Tue, 4 Aug 2026 08:22:52 -0400 Subject: [PATCH] Fix dead list-item taps and unthemed List background on iOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two independent iOS renderer gaps: 1. List-item rows attached onTapGesture via applyClickHandlers but never set a content shape, so taps only registered on opaque pixels — the padding and the Spacer gap between the text block and trailing content (most of the row) were tap-dead. @tap on a list-item effectively required hitting the text exactly. Add .contentShape(Rectangle()) before the click handlers so the whole row bounds is hittable. (Compose already covers full bounds via .clickable — Android was unaffected.) 2. SwiftUI's List paints the system (grouped) background and ignored the node's own background style, so a themed screen (bg-theme-background) rendered on stock systemGroupedBackground instead of the app palette. When the node declares a background, hide the system scroll background and paint the node's resolved color (light or dark variant) — matching how every other container element behaves. Lists without a declared background are unaffected. Co-Authored-By: Claude Fable 5 --- resources/ios/NativeUIListItemRenderer.swift | 5 +++++ resources/ios/NativeUIListRenderer.swift | 23 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/resources/ios/NativeUIListItemRenderer.swift b/resources/ios/NativeUIListItemRenderer.swift index 8ff3a55..b9f7ec2 100644 --- a/resources/ios/NativeUIListItemRenderer.swift +++ b/resources/ios/NativeUIListItemRenderer.swift @@ -115,6 +115,11 @@ struct NativeUIListItemRenderer: View { .padding(.vertical, 12) .background(containerColor != 0 ? Color(argb: containerColor) : Color.clear) .opacity(disabled ? 0.5 : 1.0) + // Without an explicit content shape, onTapGesture only registers on + // opaque pixels — the padding and the Spacer gap between text and + // trailing content (most of the row) are tap-dead. Make the whole + // row bounds hittable before attaching @tap / @longPress handlers. + .contentShape(Rectangle()) .applyClickHandlers(node: node) } diff --git a/resources/ios/NativeUIListRenderer.swift b/resources/ios/NativeUIListRenderer.swift index 9e7c13b..fc1fa66 100644 --- a/resources/ios/NativeUIListRenderer.swift +++ b/resources/ios/NativeUIListRenderer.swift @@ -85,6 +85,7 @@ struct NativeUIListRenderer: View { } } .modifier(GroupedOrPlainListStyle(grouped: grouped)) + .modifier(ListBackgroundModifier(node: node)) .scrollDismissesKeyboard(.interactively) .refreshable { if onRefreshCb != 0 { @@ -207,3 +208,25 @@ private struct GroupedOrPlainListStyle: ViewModifier { } } } + +/// SwiftUI's List paints the system (grouped) background and ignores the +/// node's own background style, so a themed screen (`bg-theme-background`) +/// renders on the stock gray instead of the app's palette. When the node +/// declares a background, hide the system scroll background and paint the +/// node's color — matching how every other container element behaves. +private struct ListBackgroundModifier: ViewModifier { + let node: NativeUINode + @Environment(\.colorScheme) private var colorScheme + + func body(content: Content) -> some View { + let darkBg = colorScheme == .dark ? node.props.getColor("dark_bg_color", default: 0) : 0 + let argb = darkBg != 0 ? darkBg : (node.style?.bgColor ?? 0) + if argb != 0 { + content + .scrollContentBackground(.hidden) + .background(Color(argb: argb)) + } else { + content + } + } +}