Describe the bug
When tapping interactive elements (buttons, package selectors, tab controls) in Paywalls V2, the ripple effect has two problems:
- Ignores rounded corners -- the ripple renders as a rectangle instead of following the component's shape (pill, rounded rectangle, etc.).
- Extends beyond visible bounds -- the ripple area includes the component's margin, making it visually larger than the actual button or selector.
Both issues stem from the same root cause: Modifier.clickable() is applied on the outer modifier, before StackComponentView applies its margin and shape internally. In Jetpack Compose, the ripple is bounded by the nearest clip ancestor. Without .clip(shape) positioned after the margin and before .clickable(), the ripple fills the full rectangular bounds including margins.
Environment
- Platform: Android (Jetpack Compose)
- SDK version: 10.0.2 (purchases + purchases-ui)
- OS version: Android 14+
- Affects all devices using Paywalls V2 with rounded components
Steps to reproduce
- Create a Paywall V2 with buttons or package selectors that have rounded corners (e.g.
Shape.Pill).
- Display the paywall using the
Paywall composable.
- Tap any button or package selector.
- Expected: Ripple follows the rounded shape of the component and stays within its visible bounds.
- Actual: Ripple fills a rectangular area that extends into the component's margin, ignoring both corner radius and visible bounds.
Reproducing in paywall-tester
The sample paywall "bless" (#8) uses a plain StackComponent for its CTA button, which has no click handler and therefore no ripple. To reproduce the issue, replace the CTA StackComponent with a ButtonComponent (e.g., action = ButtonComponent.Action.RestorePurchases) wrapping the same stack. The attached screenshot was captured after this change.

Describe the bug
When tapping interactive elements (buttons, package selectors, tab controls) in Paywalls V2, the ripple effect has two problems:
Both issues stem from the same root cause:
Modifier.clickable()is applied on the outer modifier, beforeStackComponentViewapplies its margin and shape internally. In Jetpack Compose, the ripple is bounded by the nearest clip ancestor. Without.clip(shape)positioned after the margin and before.clickable(), the ripple fills the full rectangular bounds including margins.Environment
Steps to reproduce
Shape.Pill).Paywallcomposable.Reproducing in paywall-tester
The sample paywall "bless" (#8) uses a plain
StackComponentfor its CTA button, which has no click handler and therefore no ripple. To reproduce the issue, replace the CTAStackComponentwith aButtonComponent(e.g.,action = ButtonComponent.Action.RestorePurchases) wrapping the same stack. The attached screenshot was captured after this change.