Skip to content

Plan picker paywall with a button group for Jetpack Compose

PlanPickerPaywall is design 4 of M3 Expressive Paywall. The most “Expressive” of the six. A connected button group switches plans; the spotlight card below morphs between MaterialShapes, changes color and rolls the price with AnimatedContent.

Plan picker paywall, light theme
Light
Plan picker paywall, dark theme
Dark
implementation("com.github.sanikantv:m3-expressive-paywall:v1.0.0")
  • You have two to four plans with short names.
  • You want the paywall itself to feel like a showcase of Material 3 Expressive.
PlanPickerPaywall(
plans = Sample.plans, // 2 to 4 plans with short titles fit the button group
features = Sample.features.take(3),
legal = Sample.legal,
onPurchase = buy,
onRestore = restore,
onClose = close,
initialPlanId = "pro_yearly",
)
Parameter Type Default Description
plans List<PaywallPlan> required Two to four plans. Titles appear in the buttons, so keep them short.
features List<PaywallFeature> required Benefits under the card.
legal PaywallLegal required Terms and Privacy URLs for the footer links.
onPurchase (PaywallPlan) -> Unit required Called with the selected plan when the button is tapped. Start your billing flow here.
onRestore () -> Unit required Called from the Restore link.
onClose () -> Unit required Called from the close button.
modifier Modifier Modifier Applied to the paywall’s root.
title String “Choose your plan” Headline.
subtitle String? “Switch anytime. Your progress stays with you.” Line under the headline.
initialPlanId String? null Plan to preselect.

Full signature: PlanPickerPaywall in the API reference.

The button group uses ButtonGroupDefaults.connectedLeading/Middle/TrailingButtonShapes(). To build the same control elsewhere, read Connected button group in Jetpack Compose. The card morph is explained in Shape morphing with MaterialShapes.

  • Each toggle button has Role.RadioButton semantics, because only one plan can be chosen.
  • Buttons are 56dp tall.
  • Long plan titles like “Annual subscription” get cut off in the buttons. Use “Yearly”.
  • Five or more plans. Use the classic design instead.

Built by Sanikant. Set in Google Sans Flex (SIL Open Font License). Not affiliated with Google.