Skip to main content

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

ParameterTypeDefaultDescription
componentIdString?nilOptional component ID to identify a specific carousel. If nil, uses the first matching component from campaign.
layoutString?nilOptional layout override. Options: "full", "compact", "horizontal". If nil, uses layout from backend config.
showAddToCartButtonBoolfalseWhether 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

PropertyTypeRequiredDefaultDescription
productIds[String]No[]Array of product IDs. Empty array or missing field loads ALL products from channel.
autoPlayBoolNofalseEnable/disable auto-scroll
intervalIntNo3000Auto-scroll interval in milliseconds
layoutString?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

  1. Component Detection: The component searches for an active product_carousel component in the campaign
  2. Configuration Loading: If configuration is found, it uses it; otherwise shows skeleton loader
  3. Product Loading:
  • If productIds is empty or missing → loads all products from channel
  • If productIds has values → loads only those specific products
  1. Real-time Updates: When backend updates config via WebSocket, component automatically reloads
  2. 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

  • 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 layout value in backend config
  • Check override: Layout override from code takes precedence
  • Check componentId: Ensure correct component is being used