The cart screen has a high abandonment rate. Users land on it, see a cluttered interface, can't quickly figure out the total, accidentally remove an item—and leave. Our team, with over 10 years of experience in mobile development, has delivered 40+ projects with carts for e-commerce, reducing churn by 15–20% through thoughtful UX. Let's break down how to build a cart that doesn't lose money.
How to Reduce Abandonment Rate on the Cart Screen
Item quantity. Two patterns: stepper (minus/plus next to the item) and inline input. Stepper is better for one-handed use; input is faster for large quantities. On iOS, UIStepper from UIKit is a ready component but looks system-like. A custom stepper needs proper handling of rapid taps: throttle at 300ms, otherwise the server gets a flood of requests when the button is held. In SwiftUI, implement this via .onChange with Combine debounce; in Jetpack Compose, via debounce from coroutines.
Item deletion. Swipe left with an action button (iOS pattern, UIContextualAction) or long press with a context menu—both work. But an undo toast is essential: 'Item removed' + an 'Undo' button for 4–5 seconds. Without it, the rate of accidental deletions is critically high—on one of our projects, we reduced it from 8% to 2% after implementing undo.
Sticky 'Checkout' button—always visible at the bottom. On iOS, account for SafeArea so the button isn't covered by the home indicator. On Android, use CoordinatorLayout with pinning. The button should only be active when the cart is not empty.
Why the Order Total Structure Is Critical
The user must understand where the final number comes from within 2 seconds. According to Baymard Institute, 69% of users abandon the cart due to an unclear total cost. A typical mistake: the discount is shown as a separate line in the middle of the list, the promo code is elsewhere, shipping isn't calculated until the address is selected. Result: the user doesn't understand why the total is that amount and doesn't proceed.
Correct structure for the total block:
- Subtotal
- Discount (if any)
- Promo code field
- Shipping (with a note 'calculated next step' if unknown)
- Total—large, highlighted
In one project, we added an interactive shipping calculator: selecting an address in the cart updated the total and increased conversion by 12%. The savings from implementing such a solution can reach 30% of losses from abandonment.
Comparison of Stepper Implementation in SwiftUI and Jetpack Compose
| Parameter | SwiftUI | Jetpack Compose |
|---|---|---|
| Basic component | Stepper or custom |
Row with buttons |
| Throttle | .debounce(for: .seconds(0.3), scheduler: RunLoop.main) |
debounce(300) from coroutines |
| Long press handling | LongPressGesture |
Modifier.pointerInput |
| Animation | .animation(.spring()) |
animateContentSize() |
Common UX Mistakes and Solutions
| Mistake | Solution | Impact on Conversion |
|---|---|---|
| No feedback on deletion | Toast with undo (4–5 sec) | -5% churn |
| Unclear total | Structure the total block | +15% checkout transition |
| Empty cart with no actions | Illustration + return button + recently viewed | +30% returns |
| Slow loading | Skeleton placeholders instead of spinner | -10% bounce rate |
| Missing sticky button | Fixed button at bottom | +20% completions |
Empty Cart and Other States
The empty state is not just an illustration 'cart is empty'. It's an opportunity to bring the user back to the catalog. A good solution: illustration + title + 'Continue Shopping' button + 'Recently Viewed' block if history is available. According to our data, adding recently viewed items increases click-through on the empty cart by 30%.
Case Study: Cart Optimization for a Clothing Store
For a client with a high churn rate (45%), we audited and identified the main problems: no undo on deletion, an unstructured total block, and slow loading with a spinner. After implementing all the described solutions—skeleton placeholders, undo toast, structured totals, and a sticky button—churn dropped to 25% within a month. The work paid for itself in 3 months.Why the Empty State Is a Return Point
A user with an empty cart is not yet lost. We had a case: on a startup with zero history, we set up personalized recommendations in the empty state—the conversion to adding an item grew by 25%. It's important not just to show a button, but relevant suggestions.
Loading state: skeleton placeholders for each item row. Not a general spinner for the entire screen. On iOS, use the Redacted modifier in SwiftUI; on Android, placeholder templates.
What the Work Includes
- Analysis of current cart UX (heatmaps, session replays)
- Designing structure and components in Figma (Auto Layout, component variants)
- Design for all states: normal, swipe-revealed, loading, empty, error
- Specification for developers via Figma Dev Mode
- Documentation of component interactions
- Support during integration on iOS (SwiftUI/UIKit) and Android (Jetpack Compose)
Each project undergoes an internal UX review and testing on real devices. Contact us for a project evaluation—we'll find the optimal solution for your stack and timeline. Order a cart audit: we'll identify problem areas and suggest specific improvements.
Process: From Audit to Deploy
- Audit current cart (metrics, heatmaps, scenarios)
- Design new structure (Figma prototypes)
- Design each state with platform considerations
- Handoff specification via Dev Mode
- Integration and testing on real devices
Timeline and Cost
Development timeline for the cart: from 1 to 3 days depending on complexity. Cost is calculated individually after analyzing the requirements. Initial assessment is free. Get a consultation—we'll help determine the budget.
How We Do It
Figma, Auto Layout, component variants for all cell states (normal, swipe-revealed, loading). A separate component for the total block—reused on the checkout screen. Handoff to developer via Figma Dev Mode with tokens and specification. For iOS, we use SwiftUI (iOS 15+) or UIKit; for Android, Jetpack Compose. Backend integration via REST or GraphQL.







