Fluxo UIFluxo UIv0.4.93

Carousel

An image and content carousel with swipe gestures, autoplay, thumbnail navigation, and keyboard support.

Basic Usage

Image Carousel

A basic image carousel with dot navigation and arrow buttons.

import { Carousel } from 'fluxo-ui';
import type { CarouselSlide } from 'fluxo-ui';

const slides: CarouselSlide[] = [
  { id: 's1', type: 'image', src: '/photo1.jpg', alt: 'Mountain landscape' },
  { id: 's2', type: 'image', src: '/photo2.jpg', alt: 'Ocean sunset' },
  { id: 's3', type: 'image', src: '/photo3.jpg', alt: 'City skyline' },
];

<Carousel slides={slides} />

Thumbnail Navigation

Use navigation="thumbnails" to display a clickable thumbnail strip below (or beside) the carousel.

Thumbnail Navigation

Navigate slides using clickable thumbnail strip below the main viewport.

import { Carousel } from 'fluxo-ui';

<Carousel
  slides={slides}
  navigation="thumbnails"
  thumbnailPosition="bottom"
/>

Editable Thumbnails

Pass thumbnailActions for per-thumbnail overlay buttons and trailingThumbnail for an extra tile after the strip. Both are fully generic — supply any icon and handler for delete, edit, add, or any custom action.

Editable Thumbnails

Generic per-thumbnail action buttons plus a trailing add tile. Any icon and handler is configurable.

Last action: No action yet — hover a thumbnail or click the + tile.
import { Carousel } from 'fluxo-ui';
import { EditIcon, PlusIcon, TrashIcon } from 'fluxo-ui/icons';

<Carousel
  slides={slides}
  navigation="thumbnails"
  showThumbnailInfo
  thumbnailActions={[
    {
      icon: <EditIcon />,
      label: 'Rename',
      onClick: (slide, index) => rename(index),
    },
    {
      icon: <TrashIcon />,
      label: 'Delete',
      variant: 'danger',
      onClick: (slide, index) => remove(index),
    },
  ]}
  trailingThumbnail={{
    icon: <PlusIcon />,
    label: 'Add image',
    onClick: () => addSlide(),
  }}
/>

Add Images

Pass onAddImages to make the carousel an attachment surface. Files can be dragged onto the viewport (a drop overlay appears) or chosen via the trailing add tile's file picker. Forward clipboard paste from your form to the same callback for paste-anywhere support. Filter accepted files withaddImagesAccept.

Add Images (drop · paste · pick)

Set onAddImages to turn the carousel into an attachment surface: drag-and-drop onto the viewport, an add tile that opens the file picker, and (via a consumer paste listener) clipboard paste — all feeding the same callback.

Last action: Drag an image here, paste from clipboard, or click the add tile.
import { Carousel } from 'fluxo-ui';
import { TrashIcon } from 'fluxo-ui/icons';

const addFromFiles = (files: File[]) => {
  Promise.all(
    files.map(
      (file) =>
        new Promise<CarouselSlide>((resolve) => {
          const url = URL.createObjectURL(file);
          resolve({ id: crypto.randomUUID(), type: 'image', src: url, name: file.name });
        }),
    ),
  ).then((next) => setSlides((prev) => [...prev, ...next]));
};

// Drag-drop and the trailing file-picker tile are handled by the carousel.
// Forward clipboard paste to the same callback for paste-anywhere support.
useEffect(() => {
  const onPaste = (e: ClipboardEvent) => {
    const files = Array.from(e.clipboardData?.files ?? []).filter((f) => f.type.startsWith('image/'));
    if (files.length) addFromFiles(files);
  };
  window.addEventListener('paste', onPaste);
  return () => window.removeEventListener('paste', onPaste);
}, []);

<Carousel
  slides={slides}
  navigation="thumbnails"
  aspectRatio="16/10"
  onAddImages={addFromFiles}
  thumbnailActions={[{ icon: <TrashIcon />, label: 'Delete', variant: 'danger', onClick: (_s, i) => remove(i) }]}
/>

Autoplay

Enable autoplay with loop for continuous slide rotation. Autoplay pauses on hover.

Autoplay with Loop

Slides advance automatically every 3 seconds and loop back to the first slide. Pauses on hover.

import { Carousel } from 'fluxo-ui';

<Carousel
  slides={slides}
  autoplay
  autoplayInterval={3000}
  loop
/>

Import

import { Carousel } from 'fluxo-ui';
import type { CarouselProps, CarouselSlide, CarouselThumbnailAction, CarouselTrailingThumbnail } from 'fluxo-ui';

Carousel Props

slidesreq
CarouselSlide[]

Array of slide data.

activeIndex
number

Controlled active slide index.

onSlideChange
(index: number) => void

Called when the active slide changes.

navigation
'dots' | 'arrows' | 'thumbnails' | 'none'"'dots'"

Navigation style.

thumbnailPosition
'top' | 'bottom' | 'left' | 'right'"'bottom'"

Position of thumbnail strip.

autoplay
boolean"false"

Enable automatic slide advancement.

autoplayInterval
number"5000"

Autoplay interval in milliseconds.

loop
boolean"false"

Loop back to first slide after the last.

showArrows
boolean"true"

Show previous/next arrow buttons.

showDots
boolean

Show dot indicators (overrides navigation).

lazyLoad
boolean"false"

Lazy-load images as they become active.

swipeable
boolean"true"

Enable swipe/drag gesture navigation.

aspectRatio
string

CSS aspect ratio for slides (e.g. "16/9").

className
string

Additional CSS class for the container.

slideClassName
string

Additional CSS class for each slide.

ariaLabel
string"'Image carousel'"

Accessible name for the carousel region.

showAutoplayToggle
boolean"true"

Show a play/pause button when autoplay is enabled (WCAG 2.2.2).

thumbnailActions
CarouselThumbnailAction[]

Per-thumbnail overlay action buttons (e.g. delete, edit). Each action has { icon, label, onClick(slide, index), variant?, isVisible? }. Generic — any icon and handler.

trailingThumbnail
CarouselTrailingThumbnail

An extra tile rendered after the last thumbnail (e.g. an add button). Shape: { icon, label, onClick }.

onAddImages
(files: File[]) => void

Enables image attachment. When set, the carousel accepts drag-and-drop of image files onto the viewport (with a drop overlay) and renders a trailing 'add' tile that opens a file picker (unless a custom trailingThumbnail is provided). Receives the filtered File[]. Combine with a consumer-side clipboard paste handler that forwards pasted files to the same callback.

addImagesAccept
string"'image/*'"

Comma-separated accept filter (MIME types like 'image/png' or extensions like '.png') applied to dropped and picked files before onAddImages fires.

addImagesDropLabel
string"'Drop image to add'"

Label shown in the drop overlay and used as the trailing add tile's accessible label when onAddImages is set.

CarouselSlide Interface

idreq
string

Unique identifier for the slide.

typereq
'image' | 'video' | 'custom'

Slide content type.

src
string

Image URL (for image type).

alt
string

Alt text for the image.

thumbnail
string

Thumbnail URL for thumbnail navigation.

content
ReactNode

Custom content (for custom type).

CarouselThumbnailAction Interface

iconreq
ReactNode

Icon rendered inside the action button.

labelreq
string

Accessible label / tooltip for the action.

onClickreq
(slide: CarouselSlide, index: number) => void

Invoked with the slide and its index when the action is clicked.

variant
'default' | 'danger'"'default'"

Visual style of the action button.

isVisible
(slide: CarouselSlide, index: number) => boolean

Optional predicate to conditionally show the action per slide.

CarouselTrailingThumbnail Interface

iconreq
ReactNode

Icon rendered inside the trailing tile (e.g. a plus icon).

labelreq
string

Accessible label / tooltip for the trailing tile.

onClickreq
() => void

Invoked when the trailing tile is clicked.

Features

Swipe Gestures

Touch and pointer swipe support for mobile and desktop navigation.

Autoplay

Auto-advance slides at a configurable interval, pausing on hover.

Thumbnails

Thumbnail strip with configurable position for visual slide selection.

Keyboard Navigation

Arrow keys navigate between slides with focus management.

Lazy Loading

Only load slide content when it becomes active to reduce initial bandwidth.

Accessibility

ARIA roledescription, tab roles for dots, and labeled arrow buttons.