A paywall with plan cards, trial lines and every loading, purchasing and error state.
A paywall with a hero slot, plan cards with a moving selection ring, derived per-month and trial lines, loading skeletons and purchasing, error and restored states.
$199 once, every piece included. See how installing works · Sign in
SwiftUI source you own, built on Apple frameworks only.
Purchase (screen)
How it behaves, what it handles, and the decisions behind it.
StoreKit-agnostic: map your products to PaywallPlan (price, currency, period, trial days) and the screen derives the per-month equivalence ("$3.33/mo") and the trial line ("7-day free trial, then $39.99 per year"). The selection ring travels between cards with matchedGeometryEffect, the CTA reads "Start free trial" when the selected plan has one, and PaywallStatus drives purchasing, error and restored states. isLoading shows breathing skeleton cards. Pair with glass-paywall-screen for full StoreKit 2 wiring.
termsURL / privacyURL parameters and hidden when nil. Nothing links to swiftpieces.com.hero is a ViewBuilder slot above the headline; omit it for the plain layout..selection on plan change, .error and .success on status. Cards use glassEffect on iOS 26 with a Material fallback and an opaque surface under Reduce Transparency.GlassPaywallBlockExample at the end of GlassPaywallBlock.swift is the screen shown in the preview; copy it as a starting point.SPTheme from @Environment(\.spTheme) and requires the design-system item. Set .environment(\.spTheme, YourTheme()) once at the root.accent drives the CTA tint, the selection ring, the badge and the selected card's glass tint; accentOn colors text on them. danger colors the inline error and fill the skeleton bars.display for the headline, headline and title3 on plan cards, and caption (12pt floor) for the badge and per-month line. Cards use radius.lg; the ring shares the card shape, so it stays concentric under any theme.spSurface: surface for plans, surfaceElevated for the selected one. The selection ring spring and skeleton timing are fixed and not read from motion.Pieces that work well next to this one.