Package-level declarations

The public paywall composables and their data classes.

Types

Link copied to clipboard
data class BenefitPage(val title: String, val description: String, val icon: ImageVector)

One page of the onboarding carousel that ends in the plan selection.

Link copied to clipboard
data class ComparisonRow(val label: String, val free: Boolean, val pro: Boolean = true, val freeText: String? = null, val proText: String? = null)

One row of the Free vs Pro table. Text values replace the check or cross icon when set.

Link copied to clipboard
data class PaywallFeature(val title: String, val description: String? = null, val icon: ImageVector = PaywallIcons.Check)

A benefit row with an icon, used by the classic, plan picker and onboarding paywalls.

Link copied to clipboard

Small set of Material icons (Apache 2.0) so the library needs no icon dependency. Use them for PaywallFeature, TrialStep and BenefitPage, or pass your own vectors.

Link copied to clipboard
data class PaywallLegal(val termsUrl: String, val privacyUrl: String)

Links Google Play expects on every subscription screen. They open with the platform androidx.compose.ui.platform.UriHandler.

Link copied to clipboard
data class PaywallPlan(val id: String, val title: String, val price: String, val period: String, val trialText: String? = null, val badge: String? = null, val priceDetail: String? = null, val isSubscription: Boolean = true)

One purchasable option shown on a paywall.

Link copied to clipboard
data class TrialStep(val title: String, val description: String, val icon: ImageVector)

One step of the trial timeline.

Functions

Link copied to clipboard
fun ClassicPlansPaywall(plans: List<PaywallPlan>, features: List<PaywallFeature>, legal: PaywallLegal, onPurchase: (PaywallPlan) -> Unit, onRestore: () -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier, title: String = stringResource(R.string.pw_classic_title), subtitle: String? = stringResource(R.string.pw_classic_subtitle), initialPlanId: String? = null, heroIcon: ImageVector = PaywallIcons.Sparkle)

Design 1, classic plans: an animated hero, a feature list and stacked plan cards (for example monthly, yearly and lifetime). The badged plan is preselected.

Link copied to clipboard
fun ComparisonPaywall(plans: List<PaywallPlan>, rows: List<ComparisonRow>, legal: PaywallLegal, onPurchase: (PaywallPlan) -> Unit, onRestore: () -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier, title: String = stringResource(R.string.pw_comparison_title), subtitle: String? = stringResource(R.string.pw_comparison_subtitle), freeLabel: String = stringResource(R.string.pw_comparison_free), proLabel: String = stringResource(R.string.pw_comparison_pro), initialPlanId: String? = null)

Design 2, Free vs Pro table: a comparison grid with a highlighted Pro column, then side-by-side plan tiles. Works best with two or three plans.

Link copied to clipboard
fun defaultTrialSteps(plan: PaywallPlan, trialDays: Int = 7, reminderDay: Int = trialDays - 2): List<TrialStep>

Default "Today, reminder, billing" steps for a trial of trialDays days on plan. Pass your own list to TrialTimelinePaywall to change the copy or icons.

Link copied to clipboard
fun LimitedOfferSheet(plan: PaywallPlan, originalPrice: String, discountLabel: String, offerEndsAtMillis: Long, legal: PaywallLegal, onPurchase: (PaywallPlan) -> Unit, onRestore: () -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier, title: String = stringResource(R.string.pw_offer_title), subtitle: String = stringResource(R.string.pw_offer_subtitle), offerDurationMillis: Long = 15 * 60_000L, sheetState: SheetState = rememberBottomSheetState(SheetValue.Hidden, setOf(SheetValue.Hidden, SheetValue.Expanded)))

Design 5, limited-time offer: a modal bottom sheet with a big discount, the struck-through original price, a live countdown and a wavy progress bar that drains as time runs out. Show it on top of any screen; it dismisses through onClose.

Link copied to clipboard
fun OnboardingPaywall(pages: List<BenefitPage>, plans: List<PaywallPlan>, legal: PaywallLegal, onPurchase: (PaywallPlan) -> Unit, onRestore: () -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier, plansTitle: String = stringResource(R.string.pw_onboarding_plans_title), plansSubtitle: String? = stringResource(R.string.pw_onboarding_plans_subtitle), initialPlanId: String? = null, pagerState: PagerState = rememberPagerState { pages.size + 1 })

Design 6, onboarding-end paywall: a short carousel of benefit pages that ends in the plan selection. Use it as the last step of onboarding. The legal footer appears on the plan page, where purchase becomes possible.

Link copied to clipboard
fun PlanPickerPaywall(plans: List<PaywallPlan>, features: List<PaywallFeature>, legal: PaywallLegal, onPurchase: (PaywallPlan) -> Unit, onRestore: () -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier, title: String = stringResource(R.string.pw_picker_title), subtitle: String? = stringResource(R.string.pw_picker_subtitle), initialPlanId: String? = null)

Design 4, expressive plan picker: a connected button group switches plans, and the spotlight card below morphs its shape and rolls the price for each choice. Designed for two to four plans with short titles.

Link copied to clipboard
fun TrialTimelinePaywall(plans: List<PaywallPlan>, legal: PaywallLegal, onPurchase: (PaywallPlan) -> Unit, onRestore: () -> Unit, onClose: () -> Unit, modifier: Modifier = Modifier, title: String = stringResource(R.string.pw_trial_title), subtitle: String? = stringResource(R.string.pw_trial_subtitle), steps: List<TrialStep> = defaultTrialSteps(plans.firstOrNull { it.trialText != null } ?: plans.first()), initialPlanId: String? = null)

Design 3, trial timeline: explains exactly when the user is reminded and charged, which builds trust for free trials. The timeline describes the first plan that has a trial and fades when a plan without a trial is selected.