RProductSlider
A powerful horizontal scrolling component for displaying collections of products in your iOS applications. The RProductSlider
automatically adapts to different use cases with multiple layout options, built-in headers, and "See All" functionality.
Overview
The RProductSlider
is designed for creating engaging product discovery experiences. It supports multiple layouts optimized for different use cases, from featured product showcases to compact recommendation lists.
Basic Usage
import SwiftUI
import ReachuUI
import ReachuCore
struct ProductHomeView: View {
@StateObject private var viewModel = ProductViewModel()
var body: some View {
ScrollView {
VStack(spacing: 24) {
// Featured products
RProductSlider(
title: "Featured Products",
products: viewModel.featuredProducts,
layout: .featured,
showSeeAll: true,
maxItems: 5,
onProductTap: { product in
viewModel.showProductDetail(product)
},
onAddToCart: { product in
viewModel.addToCart(product)
},
onSeeAllTap: {
viewModel.showFeaturedProducts()
}
)
// Category products
RProductSlider(
title: "Electronics",
products: viewModel.electronicsProducts,
layout: .cards,
showSeeAll: true,
onProductTap: { product in
viewModel.showProductDetail(product)
},
onAddToCart: { product in
viewModel.addToCart(product)
}
)
}
}
}
}
Layout Variants
The RProductSlider
supports six distinct layout variants, each optimized for different use cases:
Featured Layout (.featured)
Perfect for highlighting premium products and promotions.
RProductSlider(
title: "Featured Products",
products: featuredProducts,
layout: .featured,
showSeeAll: true,
maxItems: 5
)
Features:
- ✅ Large Cards: Hero-style product cards (280pt width)
- ✅ Full Information: Shows brand, title, description, and price
- ✅ Prominent CTA: Large "Add to Cart" buttons
- ✅ Perfect for: Homepage banners, special promotions, new arrivals
Cards Layout (.cards)
Ideal for browsing product collections and categories.
RProductSlider(
title: "Electronics",
products: electronicsProducts,
layout: .cards,
showSeeAll: true,
maxItems: 6
)
Features:
- ✅ Medium Cards: Grid-style product cards (180pt width)
- ✅ Balanced Information: Brand, title, and price with Add to Cart
- ✅ Efficient Browsing: Optimal for category exploration
- ✅ Perfect for: Category listings, search results, related products
Showcase Layout (.showcase) ✨
Premium layout for luxury products and special collections.
RProductSlider(
title: "Premium Collection",
products: premiumProducts,
layout: .showcase,
showSeeAll: true,
maxItems: 3
)
Features:
- ✅ Extra Large Cards: Premium hero cards (360pt width)
- ✅ Maximum Impact: Full descriptions, premium styling
- ✅ Luxury Experience: Optimal spacing and visual hierarchy
- ✅ Perfect for: Premium collections, luxury items, special editions
Wide Layout (.wide)
Comprehensive layout for detailed product browsing.
RProductSlider(
title: "Detailed Browse",
products: detailedProducts,
layout: .wide,
showSeeAll: true,
maxItems: 4
)
Features:
- ✅ Wide Cards: List-style cards with comprehensive info (320pt width)
- ✅ Detailed Information: Full product specifications and descriptions
- ✅ Comparison Friendly: Wide format perfect for feature comparison
- ✅ Perfect for: Detailed browsing, comparison views, specifications
Compact Layout (.compact)
Designed for recommendations and space-constrained areas.
RProductSlider(
title: "You Might Like",
products: recommendedProducts,
layout: .compact,
showSeeAll: true,
maxItems: 8
)
Features:
- ✅ Small Cards: Minimal product cards (120pt width)
- ✅ Essential Information: Title and price only
- ✅ Tap-only Interaction: No Add to Cart button (space optimization)
- ✅ Perfect for: Recommendations, quick picks, footer suggestions
Micro Layout (.micro) 🔍
Ultra-compact layout for dense product listings.
RProductSlider(
title: "Related Items",
products: relatedProducts,
layout: .micro,
showSeeAll: false,
maxItems: 12
)
Features:
- ✅ Ultra-Small Cards: Minimal footprint cards (80pt width)
- ✅ Dense Layout: Maximum products in minimal space
- ✅ Simplified Interaction: Tap-only, no add-to-cart buttons
- ✅ Perfect for: Footer recommendations, related items, accessories
Convenience Initializers
The RProductSlider
includes pre-configured convenience initializers for common use cases:
Featured Products
// Automatically configured for featured products
let featuredSlider = RProductSlider.featured(
title: "Featured Products",
products: featuredProducts,
maxItems: 5,
onProductTap: { product in
showProductDetail(product)
},
onAddToCart: { product in
addToCart(product)
},
onSeeAllTap: {
showAllFeatured()
}
)
Default Settings:
- Layout:
.featured
- Show See All:
true
- Max Items:
5
- Show Description:
true
Category Products
// Automatically configured for category browsing
let categorySlider = RProductSlider.category(
title: "Electronics",
products: electronicsProducts,
maxItems: 6,
onProductTap: { product in
showProductDetail(product)
},
onAddToCart: { product in
addToCart(product)
},
onSeeAllTap: {
showCategory("electronics")
}
)
Default Settings:
- Layout:
.cards
- Show See All:
true
- Max Items:
6
- Show Brand:
true
Recommendations
// Automatically configured for recommendations
let recommendationsSlider = RProductSlider.recommendations(
title: "You Might Like",
products: recommendedProducts,
maxItems: 8,
onProductTap: { product in
showProductDetail(product)
},
onSeeAllTap: {
showRecommendations()
}
)
Default Settings:
- Layout:
.compact
- Show See All:
true
- Max Items:
8
- No Add to Cart button (tap-only interaction)
Premium Showcase
// Automatically configured for premium products
let showcaseSlider = RProductSlider.showcase(
title: "Premium Collection",
products: luxuryProducts,
maxItems: 3,
onProductTap: { product in
showProductDetail(product)
},
onAddToCart: { product in
addToCart(product)
},
onSeeAllTap: {
showPremiumCollection()
}
)
Default Settings:
- Layout:
.showcase
- Show See All:
true
- Max Items:
3
- Show Description:
true
- Premium styling and spacing
Detailed Browse
// Automatically configured for detailed browsing
let detailedSlider = RProductSlider.detailed(
title: "Compare Products",
products: comparisonProducts,
maxItems: 4,
onProductTap: { product in
showProductDetail(product)
},
onAddToCart: { product in
addToCart(product)
},
onSeeAllTap: {
showDetailedBrowse()
}
)
Default Settings:
- Layout:
.wide
- Show See All:
true
- Max Items:
4
- Show Description:
true
- Comprehensive product information
Micro Recommendations
// Automatically configured for dense listings
let microSlider = RProductSlider.micro(
title: "Related",
products: relatedProducts,
maxItems: 12,
onProductTap: { product in
showProductDetail(product)
},
onSeeAllTap: {
showRelated()
}
)
Default Settings:
- Layout:
.micro
- Show See All:
false
- Max Items:
12
- No Add to Cart button
- Ultra-compact spacing
Advanced Configuration
Custom Headers
RProductSlider(
title: "Best Sellers", // Optional header title
products: bestSellingProducts,
layout: .cards,
showSeeAll: true, // Show/hide "See All" button
maxItems: 10, // Limit number of displayed items
onSeeAllTap: {
// Handle "See All" action
showAllBestSellers()
}
)
Without Header
RProductSlider(
title: nil, // No header
products: products,
layout: .cards,
showSeeAll: false, // No "See All" needed
onProductTap: { product in
showProductDetail(product)
}
)
Item Limiting
// Show maximum 5 items
RProductSlider(
title: "Limited Selection",
products: allProducts, // Large array
maxItems: 5, // Only show first 5
layout: .featured
)
// Show all items (no limit)
RProductSlider(
title: "Complete Collection",
products: products,
maxItems: nil, // Show all products
layout: .cards
)
Real-World Examples
Homepage Product Sections
struct HomepageView: View {
@StateObject private var viewModel = HomepageViewModel()
var body: some View {
ScrollView {
VStack(spacing: 32) {
// Hero featured products
RProductSlider.featured(
title: "Featured This Week",
products: viewModel.featuredProducts,
onProductTap: viewModel.showProduct,
onAddToCart: viewModel.addToCart,
onSeeAllTap: viewModel.showFeaturedCollection
)
// Category sections
ForEach(viewModel.categories) { category in
RProductSlider.category(
title: category.title,
products: viewModel.products(for: category),
maxItems: 6,
onProductTap: viewModel.showProduct,
onAddToCart: viewModel.addToCart,
onSeeAllTap: {
viewModel.showCategory(category)
}
)
}
// Recommendations at bottom
RProductSlider.recommendations(
title: "Recommended for You",
products: viewModel.recommendedProducts,
onProductTap: viewModel.showProduct,
onSeeAllTap: viewModel.showRecommendations
)
}
.padding(.vertical, 24)
}
}
}
Product Detail Recommendations
struct ProductDetailView: View {
let product: Product
@StateObject private var viewModel = ProductDetailViewModel()
var body: some View {
ScrollView {
VStack(spacing: 24) {
// Product details...
ProductDetailContent(product: product)
// Related products
RProductSlider.category(
title: "Related Products",
products: viewModel.relatedProducts,
maxItems: 5,
onProductTap: { relatedProduct in
// Navigate to related product
viewModel.showProduct(relatedProduct)
},
onAddToCart: viewModel.addToCart
)
// Recently viewed
RProductSlider.recommendations(
title: "Recently Viewed",
products: viewModel.recentlyViewed,
maxItems: 6,
onProductTap: viewModel.showProduct
)
}
}
.task {
await viewModel.loadRelatedProducts(for: product)
}
}
}
Category Browse Page
struct CategoryView: View {
let category: Category
@StateObject private var viewModel = CategoryViewModel()
var body: some View {
VStack(spacing: 0) {
// Subcategory filters...
CategoryFilters(category: category)
ScrollView {
VStack(spacing: 24) {
// Featured in category
RProductSlider.featured(
title: "Featured in \(category.title)",
products: viewModel.featuredProducts,
maxItems: 3,
onProductTap: viewModel.showProduct,
onAddToCart: viewModel.addToCart
)
// Subcategory sliders
ForEach(viewModel.subcategories) { subcategory in
RProductSlider.category(
title: subcategory.title,
products: viewModel.products(for: subcategory),
onProductTap: viewModel.showProduct,
onAddToCart: viewModel.addToCart,
onSeeAllTap: {
viewModel.showSubcategory(subcategory)
}
)
}
}
.padding(.vertical, 16)
}
}
.navigationTitle(category.title)
}
}
Layout Guidelines
When to Use Each Layout
Layout | Best For | Card Width | Use Cases |
---|---|---|---|
Showcase | Luxury products, premium collections | 360pt | Premium brands, luxury items, special editions |
Wide | Detailed browsing, comparisons | 320pt | Product specifications, detailed comparison, reviews |
Featured | Premium products, promotions | 280pt | Homepage banners, new arrivals, special offers |
Cards | General browsing | 180pt | Category listings, search results, related products |
Compact | Recommendations, space-constrained | 120pt | Recently viewed, suggestions, quick picks |
Micro | Dense listings, minimal space | 80pt | Footer recommendations, accessories, related items |
Visual Hierarchy
VStack(spacing: 32) {
// Hero: Showcase for premium (largest)
RProductSlider.showcase(
title: "Premium Collection",
products: premium
)
// Primary: Featured for promotions
RProductSlider.featured(
title: "Featured This Week",
products: featured
)
// Secondary: Wide for detailed browsing
RProductSlider.detailed(
title: "Compare & Choose",
products: comparison
)
// Standard: Category sections
RProductSlider.category(
title: "Electronics",
products: electronics
)
// Compact: Recommendations
RProductSlider.recommendations(
title: "You Might Like",
products: recommendations
)
// Minimal: Related items
RProductSlider.micro(
title: "Related Items",
products: related
)
}
Performance Considerations
Efficient Data Loading
class ProductSliderViewModel: ObservableObject {
@Published var featuredProducts: [Product] = []
@Published var categoryProducts: [String: [Product]] = [:]
func loadFeaturedProducts() async {
// Load only what's needed for the slider
self.featuredProducts = try await productService.getFeatured(limit: 5)
}
func loadCategoryProducts(_ categoryId: String) async {
// Lazy load category products when needed
if categoryProducts[categoryId] == nil {
categoryProducts[categoryId] = try await productService.getProducts(
categoryId: categoryId,
limit: 6
)
}
}
}
Memory Management
- ✅ Lazy Loading: Load slider content as needed
- ✅ Pagination: Use
maxItems
to limit initial load - ✅ Image Optimization: Product cards handle image loading efficiently
- ✅ State Management: Use appropriate state management patterns
Accessibility
The RProductSlider
includes comprehensive accessibility support:
// Automatic accessibility labels
.accessibilityLabel("Product slider: \(title)")
// Navigation accessibility
.accessibilityAddTraits(.startsMediaSession)
// Individual product accessibility
.accessibilityElement(children: .contain)
Accessibility Features:
- ✅ VoiceOver Support: Proper navigation and announcements
- ✅ Dynamic Type: Respects user font size preferences
- ✅ High Contrast: Adapts to accessibility display modes
- ✅ Keyboard Navigation: Full keyboard support for tvOS and external keyboards
- Use Featured layout sparingly for maximum impact
- Implement lazy loading for better performance
- Provide meaningful titles that describe the product collection
- Consider user context when choosing layouts and item limits