RProductCarousel
The RProductCarousel component displays a horizontal scrolling carousel of products with automatic configuration from the active campaign. It supports multiple layouts, auto-scroll, and can load all products from the channel or specific product IDs.
Features
- Three layout options:
full,compact,horizontal - Auto-configured: Automatically loads configuration from active campaign
- Auto-scroll support: Configurable interval from backend
- Smart product loading: Loads all products if no IDs provided
- Multiple carousels: Support for multiple instances via
componentId - Skeleton loader: Matches selected layout while loading
- Pagination indicators: Visual dots for navigation
- Product detail: Clickable cards open product detail overlay
- Real-time updates: Automatically updates when backend config changes
Basic Usage
Automatic Configuration
import SwiftUI
import ReachuUI
struct MyView: View {
var body: some View {
ScrollView {
VStack {
// Automatically uses configuration from backend
RProductCarousel()
}
}
}
}
With Specific Component ID
If your backend has multiple product_carousel components, you can specify which one to use:
// Use first matching component (default)
RProductCarousel()
// Use specific component by ID
RProductCarousel(componentId: "product-carousel-1")
RProductCarousel(componentId: "b8402c1e-5673-49e9-b53e-e0f176f05b44")
Layout Override
You can override the layout from backend for testing or comparison:
// Force specific layout (ignores backend config)
RProductCarousel(layout: "full") // Large vertical cards
RProductCarousel(layout: "compact") // Small vertical cards (2 visible)
RProductCarousel(layout: "horizontal") // Horizontal cards
// Combine componentId and layout override
RProductCarousel(
componentId: "product-carousel-1",
layout: "full"
)
With Add to Cart Button
// Show "Add to Cart" button in full layout cards
RProductCarousel(
layout: "full",
showAddToCartButton: true
)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
componentId | String? | nil | Optional component ID to identify a specific carousel. If nil, uses the first matching component from campaign. |
layout | String? | nil | Optional layout override. Options: "full", "compact", "horizontal". If nil, uses layout from backend config. |
showAddToCartButton | Bool | false | Whether to show "Add to Cart" button in full layout cards. |
Layout Options
Full Layout ("full")
- Card size: Full width minus padding
- Aspect ratio: 1.3:1 (height is 1.3x width)
- Cards visible: 1 at a time
- Best for: Featured products, hero displays
RProductCarousel(layout: "full")
Compact Layout ("compact")
- Card size: ~47% of screen width each
- Cards visible: 2 at once
- Height: Fixed 300px
- Best for: Product browsing, multiple products visible
RProductCarousel(layout: "compact")
Horizontal Layout ("horizontal")
- Card size: 90% width, 110px height
- Layout: Image left, description right
- Image size: 90x90px
- Best for: Compact product lists, quick browsing
RProductCarousel(layout: "horizontal")
Backend Configuration
The component reads configuration from the active campaign via GET /api/campaigns/{campaignId}/components.
Configuration Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
productIds | [String] | No | [] | Array of product IDs. Empty array or missing field loads ALL products from channel. |
autoPlay | Bool | No | false | Enable/disable auto-scroll |
interval | Int | No | 3000 | Auto-scroll interval in milliseconds |
layout | String? | No | "full" | Layout type: "full", "compact", or "horizontal" |
Example Configurations
Load All Products (No IDs)
{
"componentId": "product-carousel-all",
"type": "product_carousel",
"status": "active",
"config": {
"autoPlay": true,
"interval": 4000,
"layout": "full"
}
}
**Note:**When productIds is empty or not provided, the component automatically loads all products from the channel.
Specific Products with Auto-scroll
{
"componentId": "product-carousel-featured",
"type": "product_carousel",
"status": "active",
"config": {
"productIds": ["408841", "408842", "408843"],
"autoPlay": true,
"interval": 5000,
"layout": "compact"
}
}
Minimal Configuration
{
"componentId": "product-carousel-simple",
"type": "product_carousel",
"status": "active",
"config": {
"autoPlay": false,
"interval": 3000
}
}
**Note:**Missing productIds defaults to empty array (loads all products). Missing layout defaults to "full".
Multiple Carousels
You can display multiple carousels with different configurations:
struct HomeView: View {
var body: some View {
ScrollView {
VStack(spacing: 24) {
// First carousel (uses first matching component)
VStack(alignment: .leading) {
Text("Featured Products")
.font(.headline)
RProductCarousel()
}
// Second carousel (specific component ID)
VStack(alignment: .leading) {
Text("Recommended Products")
.font(.headline)
RProductCarousel(
componentId: "product-carousel-recommended"
)
}
// Third carousel (different layout)
VStack(alignment: .leading) {
Text("Trending Now")
.font(.headline)
RProductCarousel(
componentId: "product-carousel-trending",
layout: "compact"
)
}
}
}
}
}
Complete Example
import SwiftUI
import ReachuUI
import ReachuDesignSystem
struct ProductCarouselExampleView: View {
var body: some View {
NavigationView {
ScrollView {
VStack(spacing: 24) {
// 1. Auto-configured carousel
VStack(alignment: .leading, spacing: 8) {
Text("Featured Products")
.font(.headline)
RProductCarousel()
}
// 2. Specific component ID
VStack(alignment: .leading, spacing: 8) {
Text("Recommended Products")
.font(.headline)
RProductCarousel(
componentId: "b8402c1e-5673-49e9-b53e-e0f176f05b44"
)
}
// 3. Layout override
VStack(alignment: .leading, spacing: 8) {
Text("Compact View")
.font(.headline)
RProductCarousel(layout: "compact")
}
// 4. Horizontal layout
VStack(alignment: .leading, spacing: 8) {
Text("Horizontal View")
.font(.headline)
RProductCarousel(layout: "horizontal")
}
// 5. With Add to Cart button
VStack(alignment: .leading, spacing: 8) {
Text("With Add to Cart")
.font(.headline)
RProductCarousel(
layout: "full",
showAddToCartButton: true
)
}
}
.padding()
}
.navigationTitle("Product Carousel")
}
}
}
Behavior
- Component Detection: The component searches for an active
product_carouselcomponent in the campaign - Configuration Loading: If configuration is found, it uses it; otherwise shows skeleton loader
- Product Loading:
- If
productIdsis empty or missing → loads all products from channel - If
productIdshas values → loads only those specific products
- Real-time Updates: When backend updates config via WebSocket, component automatically reloads
- Layout Priority: Layout override from code takes precedence over backend config
WebSocket Updates
The component automatically updates when the backend sends component_config_updated events:
{
"type": "component_config_updated",
"componentId": "product-carousel-1",
"component": {
"id": "product-carousel-1",
"type": "product_carousel",
"config": {
"productIds": ["408841", "408842"],
"autoPlay": true,
"interval": 4000,
"layout": "full"
}
}
}
The component will automatically reload products and update the display when this event is received.
Troubleshooting
Carousel Not Showing
- Check campaign is active: Component only shows when campaign is active
- Check component status: Component must have
"status": "active" - Check component type: Must be
"product_carousel" - Check componentId: If using
componentId, ensure it matches exactly
Products Not Loading
- Check productIds: Empty array or missing field loads all products
- Check market availability: Ensure market is configured correctly
- Check network: Verify API connectivity
Layout Not Applying
- Check backend config: Verify
layoutvalue in backend config - Check override: Layout override from code takes precedence
- Check componentId: Ensure correct component is being used
Related Components
RProductBanner- Featured product bannerRProductStore- Grid/list product viewRProductSpotlight- Featured product spotlightRProductCard- Individual product card component