RFloatingCartIndicator
A persistent, elegant cart indicator that appears on all screens when the cart contains items. Provides quick access to checkout and real-time cart updates with smooth animations.
Overview
The RFloatingCartIndicator
is designed to provide users with constant awareness of their cart status and easy access to checkout from anywhere in your app. It automatically appears when items are added to the cart and disappears when the cart becomes empty.
Key Features
- ✅ Global Persistence - Appears on every screen when cart has items
- ✅ Real-time Updates - Shows current item count and total price
- ✅ Quick Checkout Access - One-tap to open checkout overlay
- ✅ Elegant Design - Gradient background with professional styling
- ✅ Smart Animations - Bounce effect when items are added
- ✅ Auto-hide - Disappears automatically when cart is empty
- ✅ Haptic Feedback - Tactile confirmation on iOS devices
- ✅ Cross-platform - Works on iOS, macOS, tvOS, and watchOS
Basic Usage
Simple Integration
Add the floating cart indicator to your main content view:
import SwiftUI
import ReachuUI
struct ContentView: View {
@EnvironmentObject var cartManager: CartManager
var body: some View {
NavigationView {
// Your main app content
ProductCatalogView()
}
.overlay {
RFloatingCartIndicator()
.environmentObject(cartManager)
}
.sheet(isPresented: $cartManager.isCheckoutPresented) {
RCheckoutOverlay()
.environmentObject(cartManager)
}
}
}
What You Get Automatically
When you add RFloatingCartIndicator
to your app:
- Cart appears when first item is added
- Count updates in real-time as items are added/removed
- Price updates automatically when quantities change
- Bounce animation plays when new items are added
- Tapping opens the checkout overlay immediately
- Cart disappears when all items are removed
Design & Layout
Visual Design
The floating cart indicator features:
- Gradient Background - Primary color gradient for brand consistency
- Rounded Corners - Capsule shape for modern appearance
- Shadow - Subtle drop shadow for depth
- Badge - White circular badge with item count
- Typography - Clear, readable text with proper hierarchy
Positioning
The indicator automatically positions itself:
- Bottom Center - Centered horizontally at the bottom of the screen
- Safe Area Aware - Respects device safe areas and navigation bars
- Consistent Margin - Maintains proper spacing from screen edges
- Above Content - Appears above your app content without interference
Size & Spacing
// Container
.padding(.horizontal, ReachuSpacing.lg) // 24pt horizontal padding
.padding(.vertical, ReachuSpacing.md) // 16pt vertical padding
.padding(.bottom, ReachuSpacing.xl) // 32pt bottom margin
// Internal spacing
HStack(spacing: ReachuSpacing.sm) // 12pt between elements
// Badge positioning
.offset(x: 12, y: -8) // Positioned on cart icon
Integration Examples
With Tab Bar Apps
struct TabBarApp: View {
@EnvironmentObject var cartManager: CartManager
var body: some View {
TabView {
ProductsView()
.tabItem {
Image(systemName: "bag.fill")
Text("Products")
}
CartView()
.tabItem {
Image(systemName: "cart.fill")
Text("Cart")
}
// Automatic cart badge on tab
.badge(cartManager.itemCount > 0 ? cartManager.itemCount : nil)
}
// Floating cart works with tab bars
.overlay {
RFloatingCartIndicator()
.environmentObject(cartManager)
}
.sheet(isPresented: $cartManager.isCheckoutPresented) {
RCheckoutOverlay()
.environmentObject(cartManager)
}
}
}
With Navigation Stack
struct NavigationApp: View {
@EnvironmentObject var cartManager: CartManager
var body: some View {
NavigationStack {
ProductListView()
.navigationTitle("Products")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
// Optional: Additional cart button in navigation
Button {
cartManager.showCheckout()
} label: {
Image(systemName: "cart")
.overlay(
cartManager.itemCount > 0 ?
Badge(count: cartManager.itemCount) : nil
)
}
}
}
}
// Floating cart complements navigation
.overlay {
RFloatingCartIndicator()
.environmentObject(cartManager)
}
}
}
Multiple Screen Integration
The floating cart automatically works across all your app screens:
// Product Catalog Screen
ProductCatalogView()
.overlay { RFloatingCartIndicator() } // ✅ Shows cart
// Product Detail Screen
ProductDetailView(product: product)
.overlay { RFloatingCartIndicator() } // ✅ Shows cart
// Search Results Screen
SearchResultsView(query: searchQuery)
.overlay { RFloatingCartIndicator() } // ✅ Shows cart
// User Profile Screen
UserProfileView()
.overlay { RFloatingCartIndicator() } // ✅ Shows cart
// Any other screen in your app
AnyView()
.overlay { RFloatingCartIndicator() } // ✅ Shows cart
Advanced Customization
Custom Checkout Actions
While the floating cart automatically opens the checkout overlay, you can customize the behavior:
struct CustomFloatingCartExample: View {
@EnvironmentObject var cartManager: CartManager
@State private var showCustomCheckout = false
var body: some View {
YourContentView()
.overlay {
// Use the standard floating cart
RFloatingCartIndicator()
.environmentObject(cartManager)
}
// Custom checkout flow
.sheet(isPresented: $cartManager.isCheckoutPresented) {
CustomCheckoutFlow()
.environmentObject(cartManager)
}
}
}
Conditional Display
You can conditionally show the floating cart based on app state:
struct ConditionalCartExample: View {
@EnvironmentObject var cartManager: CartManager
@State private var isCheckoutAllowed = true
var body: some View {
YourContentView()
.overlay {
// Only show floating cart when checkout is allowed
if isCheckoutAllowed {
RFloatingCartIndicator()
.environmentObject(cartManager)
}
}
}
}
Animation Details
Bounce Animation
When items are added to the cart, the floating cart plays a satisfying bounce animation:
// Badge bounce when items added
.scaleEffect(bounceAnimation ? 1.2 : 1.0)
.animation(.spring(response: 0.3, dampingFraction: 0.6), value: bounceAnimation)
// Appears/disappears smoothly
.animation(.spring(response: 0.6, dampingFraction: 0.8), value: cartManager.itemCount)
Press Animation
When users tap the floating cart:
// Scale down on press
.scaleEffect(isPressed ? 0.95 : 1.0)
.animation(.easeInOut(duration: 0.1), value: isPressed)
// Haptic feedback on iOS
#if os(iOS)
let impactFeedback = UIImpactFeedbackGenerator(style: .medium)
impactFeedback.impactOccurred()
#endif
Accessibility
The floating cart includes comprehensive accessibility support:
// Automatic accessibility label
.accessibilityLabel("Shopping cart with \(cartManager.itemCount) items, total \(cartManager.currency) \(cartManager.cartTotal)")
// Action hint
.accessibilityHint("Tap to open checkout")
// Cart count value
.accessibilityValue("\(cartManager.itemCount) items")
// Role identification
.accessibilityAddTraits(.isButton)
Performance Considerations
Efficient Updates
The floating cart is optimized for performance:
- ✅ Reactive Updates - Only redraws when cart state changes
- ✅ Minimal Layout - Simple HStack with efficient text rendering
- ✅ Conditional Rendering - Only appears when needed
- ✅ Animation Optimization - Uses hardware-accelerated animations
Memory Management
- ✅ Automatic Cleanup - Disposes resources when cart is empty
- ✅ Observer Pattern - Uses
@EnvironmentObject
for efficient updates - ✅ Animation Disposal - Properly cancels animations when view disappears
Best Practices
Integration Guidelines
- Use Globally - Add to your main app container for global access
- Combine with Checkout - Always pair with
RCheckoutOverlay
- Respect Safe Areas - The component automatically handles safe areas
- Test on Devices - Verify positioning on different screen sizes
Design Considerations
- Brand Consistency - Uses your app's primary colors automatically
- Accessibility First - Includes comprehensive accessibility support
- Cross-Platform - Works consistently across all Apple platforms
- Performance - Optimized for smooth animations and efficient rendering
User Experience
- Predictable Behavior - Appears/disappears based on cart state
- Clear Feedback - Shows exact count and total price
- Quick Access - One-tap to checkout from anywhere
- Non-Intrusive - Doesn't interfere with app navigation
Platform-Specific Notes
iOS
- Full haptic feedback support
- Respects Dynamic Type for text sizing
- Works with all screen sizes including iPhone and iPad
macOS
- Adapted for cursor interaction
- Proper hover states and click feedback
- Respects macOS design guidelines
tvOS
- Optimized for remote control navigation
- Focus management compatible
- Appropriate sizing for TV screens
watchOS
- Simplified design for small screens
- Essential information only
- Optimized for Series 4+ screens
The floating cart indicator works best when combined with the complete Reachu UX system. Use it alongside RToastNotification
for notifications and RCheckoutOverlay
for the complete checkout experience.
The floating cart automatically integrates with CartManager
state. Simply add it to your view hierarchy and it will work seamlessly with all other Reachu components.