Skip to main content

Overview

Carousel is a production-ready carousel component included in the sunpeak Starter Kit. It provides smooth horizontal scrolling with navigation arrows, edge gradients, and persistent state tracking. Built on embla-carousel-react with wheel gesture support.

Import

import { Carousel } from './components/carousel';
import { Card } from './components/card';

Basic Usage

<Carousel showArrows={true} gap={16}>
  <Card header="Card 1">First card</Card>
  <Card header="Card 2">Second card</Card>
  <Card header="Card 3">Third card</Card>
</Carousel>

Props

children

  • Type: React.ReactNode
  • Optional: Yes
  • Description: The carousel items to display. Typically Card components, but can be any React nodes.

gap

  • Type: number
  • Optional: Yes
  • Default: 16
  • Description: Gap between carousel items in pixels.

showArrows

  • Type: boolean
  • Optional: Yes
  • Default: true
  • Description: Whether to show navigation arrows (Previous/Next buttons). Arrows only appear when there are more items to scroll.

showEdgeGradients

  • Type: boolean
  • Optional: Yes
  • Default: true
  • Description: Whether to show gradient overlays at the left/right edges to indicate more content. Gradients appear when scrolling is possible in that direction.

cardWidth

  • Type: number | { inline?: number; fullscreen?: number }
  • Optional: Yes
  • Default: 220
  • Description: Width of each carousel item in pixels. Can be:
    • A single number for consistent width
    • An object with inline and/or fullscreen properties to set different widths based on display mode

className

  • Type: string
  • Optional: Yes
  • Description: Additional CSS classes to apply to the carousel container.

State Management

The carousel uses useWidgetState to persist the current scroll position across sessions:
interface CarouselState {
  currentIndex?: number;
}
This means users will see the same scroll position when they return to your widget.

Common Patterns

<Carousel gap={16} cardWidth={240}>
  {products.map(product => (
    <Card
      key={product.id}
      image={product.image}
      imageAlt={product.name}
      header={product.name}
      metadata={`$${product.price}`}
      button1={{
        children: "Add to Cart",
        isPrimary: true,
        onClick: () => addToCart(product.id)
      }}
    >
      {product.description}
    </Card>
  ))}
</Carousel>
<Carousel gap={12} cardWidth={280} showArrows={true}>
  {photos.map(photo => (
    <Card
      key={photo.id}
      image={photo.url}
      imageAlt={photo.caption}
      header={photo.title}
      metadata={photo.location}
    />
  ))}
</Carousel>
<Carousel gap={20}>
  {recommendations.map(item => (
    <Card
      key={item.id}
      image={item.thumbnail}
      imageAlt={item.title}
      header={item.title}
      metadata={`⭐ ${item.rating}${item.category}`}
      button1={{
        children: "View Details",
        isPrimary: true,
        onClick: () => navigate(item.id)
      }}
    >
      {item.summary}
    </Card>
  ))}
</Carousel>