Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3290 +/- ##
==========================================
- Coverage 79.20% 79.19% -0.02%
==========================================
Files 352 353 +1
Lines 14099 14105 +6
Branches 1939 1941 +2
==========================================
+ Hits 11167 11170 +3
- Misses 2136 2137 +1
- Partials 796 798 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
...ui/src/main/kotlin/com/revenuecat/purchases/ui/revenuecatui/components/style/StyleFactory.kt
Show resolved
Hide resolved
...ui/src/main/kotlin/com/revenuecat/purchases/ui/revenuecatui/helpers/OfferingToStateMapper.kt
Show resolved
Hide resolved
tonidero
left a comment
There was a problem hiding this comment.
I think mostly cursor's comments + one of my own but depends on what we want the header to be able to do for this feature.
...ases/src/main/kotlin/com/revenuecat/purchases/paywalls/components/common/ComponentsConfig.kt
Show resolved
Hide resolved
...ui/src/main/kotlin/com/revenuecat/purchases/ui/revenuecatui/helpers/OfferingToStateMapper.kt
Show resolved
Hide resolved
| modifier = Modifier | ||
| .fillMaxWidth(), | ||
| ) | ||
| } |
There was a problem hiding this comment.
So we won't support transparent background header that allows the main content to scroll behind the header with this correct? Not sure if that's something we would want to do... If we do, I think we basically would need to draw the main content below the header, to the top, and then add a top padding to the content the size of the header.
FWIW, I know we don't do this for footers... But feels to me that this pattern might be more requested for headers?
There was a problem hiding this comment.
It took me a bit but I managed to get it working. The main content is drawn from the top inside a Box, with the header overlaid on top via Alignment.TopCenter. We measure the header height with onSizeChanged and conditionally add padding(top = headerHeightDp) to the scroll modifier, but only when there’s no hero image because I learnt that we handle that differently 😄 .
When there IS a hero image (we have a mainStackHasHeroImage), we skip the padding so the image renders behind the header. This way transparent headers with content scrolling behind are supported with and without hero images.
- Add HeaderComponentStyle handling to applyTopWindowInsetsIfNotYetApplied so the header's inner stack receives top insets (status bar / camera cutouts) - Add HeaderComponentStyle handling to applyHorizontalWindowInsetsIfNecessary so landscape horizontal insets propagate through the header, mirroring the existing StickyFooterComponentStyle handling - Add applyTopWindowInsets parameter to StyleFactory.create() (default true) so callers can opt out when another component owns the top edge - Pass applyTopWindowInsets = config.header == null for the main scrollable stack in OfferingToStateMapper, preventing double top-padding when a header is rendered above the stack Fixes two bugs reported in review: - Header missing window insets handling (cursor[bot], High severity) - Main stack gets top insets with header present (cursor[bot]/tonidero, Medium severity)
...ui/src/main/kotlin/com/revenuecat/purchases/ui/revenuecatui/components/style/StyleFactory.kt
Show resolved
Hide resolved
📸 Snapshot Test582 unchanged
🛸 Powered by Emerge Tools |
9865c44 to
b15fceb
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b15fceb. Configure here.

HeaderComponentdata model mirroring the existingStickyFooterComponentpattern, a wrapper around aStackComponentpinned above the scrollable body content.HeaderComponentStyleandHeaderComponentViewon the UI side, with full style factory and rendering supportOfferingToStateMapper→PaywallValidationResult→PaywallState→LoadedPaywallComponents)components_config.base, rendered above the scrollable stack when present, below it the sticky footer (layout: header | scrollable body | footer)Note
Medium Risk
Adds a new paywall component type and threads it through JSON deserialization, validation/state mapping, and Compose rendering, which can affect paywall layout and inset handling. Risk is moderate due to new UI composition/scroll padding logic and expanded component traversal, but changes are additive and covered by new/updated tests.
Overview
Adds a new
HeaderComponent(aStackComponentwrapper) to the paywalls data model, including JSON deserialization support (type: "header") and config wiring via an optionalheaderfield inPaywallComponentsConfig.On the UI side, introduces
HeaderComponentStyle/HeaderComponentView, updatesStyleFactoryto build header styles (including window-insets handling and hero-image tracking), and threads the header throughOfferingToStateMapper→PaywallValidationResult→PaywallState.Updates
LoadedPaywallComponentsto render the header pinned above the scrollable main content (adding top padding equal to the measured header height when appropriate) while keeping the sticky footer behavior, and extends component traversal/unsupported-condition detection plus test coverage to include headers.Reviewed by Cursor Bugbot for commit e57d603. Bugbot is set up for automated code reviews on this repo. Configure here.