Carousel 10.18.1
This is an effective way of displaying multiple images or content in a single space.
Not only does it conserve screen real estate, but it also guides visitors to concentrate on crucial website content, significantly enhancing the overall visual appeal.
To support Arabic languages this component requires setting up the isRtl
prop directly.
Anatomy
<Carousel> <Carousel.LeftArrow>...</Carousel.LeftArrow> <Carousel.Reel> <Carousel.Item>...</Carousel.Item> <Carousel.Reel> <Carousel.Indicators/> </Carousel.RightArrow>...</Carousel.RightArrow> </Carousel>
Default
"use client";
import { Carousel } from "@heathmont/moon-core-tw";
import {
ControlsChevronLeftSmall,
ControlsChevronRightSmall,
} from "@heathmont/moon-icons-tw";
const Default = () => {
const items = Array.from({ length: 25 }, (index) => index);
return (
<div className="flex flex-col w-full items-center">
<Carousel
scrollTo={5}
data-testid="carousel"
className="w-full sm:max-w-auto"
>
<Carousel.LeftArrow data-testid="left-arrow">
<ControlsChevronLeftSmall />
</Carousel.LeftArrow>
<Carousel.Reel>
{items.map((_, index) => (
<Carousel.Item
key={index}
className="w-full max-w-80 h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
<Carousel.RightArrow data-testid="right-arrow">
<ControlsChevronRightSmall />
</Carousel.RightArrow>
</Carousel>
</div>
);
};
export default Default;
Customized Arrows
You can use any custom trigger for the previous/next button.
"use client";
import { Button, Carousel } from "@heathmont/moon-core-tw";
type RenderProps = {
scrollLeftToStep?: () => void;
scrollRightToStep?: () => void;
canScrollLeft?: boolean;
canScrollRight?: boolean;
};
const Example = () => {
const items = Array.from({ length: 25 }, (index) => index);
return (
<div className="flex flex-col w-full items-center">
<Carousel scrollTo={5} className="w-full sm:max-w-auto">
{({
scrollLeftToStep,
scrollRightToStep,
canScrollLeft,
canScrollRight,
}: RenderProps) => (
<>
<Button
onClick={scrollLeftToStep}
disabled={!canScrollLeft}
className="my-4"
data-testid="scroll-left"
>
Scroll to left
</Button>
<Carousel.Reel>
{items.map((_, index) => (
<Carousel.Item
key={index}
className="w-full max-w-80 h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
<Button
onClick={scrollRightToStep}
disabled={!canScrollRight}
className="my-4"
data-testid="scroll-right"
>
Scroll to Right
</Button>
</>
)}
</Carousel>
</div>
);
};
export default Example;
Showing Indicators
You have the option to display dots as indicators.
"use client";
import { Carousel } from "@heathmont/moon-core-tw";
import {
ControlsChevronLeftSmall,
ControlsChevronRightSmall,
} from "@heathmont/moon-icons-tw";
const Example = () => {
const items = Array.from({ length: 5 }, (index) => index);
return (
<div className="flex flex-col w-full items-center">
<Carousel step={1} selectedIndex={1} className="w-full max-w-80">
<Carousel.LeftArrow data-testid="scroll-left">
<ControlsChevronLeftSmall />
</Carousel.LeftArrow>
<Carousel.Reel>
{items.map((_, index) => (
<Carousel.Item
key={index}
className="w-full max-w-80 h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
<Carousel.RightArrow data-testid="scroll-right">
<ControlsChevronRightSmall />
</Carousel.RightArrow>
<Carousel.Indicators />
</Carousel>
</div>
);
};
export default Example;
Different gap
You can define the gap between slides using the className
property.
"use client";
import { Carousel } from "@heathmont/moon-core-tw";
import {
ControlsChevronLeftSmall,
ControlsChevronRightSmall,
} from "@heathmont/moon-icons-tw";
const Spaces = () => {
const items = Array.from({ length: 10 }, (index) => index);
return (
<div className="flex flex-col items-center gap-4 w-full">
<Carousel className="w-full sm:max-w-auto">
<Carousel.LeftArrow data-testid="scroll-left">
<ControlsChevronLeftSmall />
</Carousel.LeftArrow>
<Carousel.Reel className="gap-20">
{items.map((_, index) => (
<Carousel.Item
key={index}
className="w-full max-w-80 h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
<Carousel.RightArrow data-testid="scroll-right">
<ControlsChevronRightSmall />
</Carousel.RightArrow>
</Carousel>
</div>
);
};
export default Spaces;
Visible Indices
To access to indices visible in the carousel viewport, you can utilize the render prop, accessing firstVisibleIndex
and lastVisibleIndex
.
"use client";
import { Carousel } from "@heathmont/moon-core-tw";
import {
ControlsChevronLeftSmall,
ControlsChevronRightSmall,
} from "@heathmont/moon-icons-tw";
type RenderProps = {
firstVisibleIndex?: number;
lastVisibleIndex?: number;
};
const VisibleIndices = () => {
const items = Array.from({ length: 25 }, (index) => index);
return (
<div className="flex flex-col items-center gap-4 w-full">
<Carousel className="w-full sm:max-w-auto">
{({ firstVisibleIndex, lastVisibleIndex }: RenderProps) => (
<>
<Carousel.LeftArrow data-testid="scroll-left">
<ControlsChevronLeftSmall />
</Carousel.LeftArrow>
<Carousel.Reel>
{items.map((_, index) => (
<Carousel.Item
key={index}
className="w-full max-w-80 h-48 border border-beerus flex-col" /* flex-col added, Carousel.Item have as base flex */
data-testid={`carousel-${index}`}
>
<p>Current index: {index}</p>
<p data-testid={`visible-indices-${index}`}>
Visible indices:
{`${firstVisibleIndex}-${lastVisibleIndex}`}
</p>
</Carousel.Item>
))}
</Carousel.Reel>
<Carousel.RightArrow data-testid="scroll-right">
<ControlsChevronRightSmall />
</Carousel.RightArrow>
</>
)}
</Carousel>
</div>
);
};
export default VisibleIndices;
Selected Index
The selectedIndex
prop enables the carousel to display a particular index.
"use client";
import { Carousel, Chip } from "@heathmont/moon-core-tw";
import { useState } from "react";
const ITEMS = Array.from({ length: 5 }, (index) => index);
const SelectIndex = () => {
const [selected, setSelected] = useState(0);
return (
<div className="flex flex-col items-center gap-4 w-full">
<div className="flex gap-1">
{ITEMS.map((_, index) => (
<Chip
key={index}
isActive={selected === index}
onClick={() => setSelected(index)}
className="px-4"
data-testid={`carousel-button-${index}`}
>
{index}
</Chip>
))}
</div>
<Carousel
step={1}
selectedIndex={selected}
className="w-full max-w-80"
data-testid="selectedIndex-carousel"
>
<Carousel.Reel>
{ITEMS.map((_, index) => (
<Carousel.Item
key={index}
className="w-full h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
</Carousel>
</div>
);
};
export default SelectIndex;
Auto Slide
If the carousel is intended to advance automatically, you can achieve this by setting the autoSlideDelay
prop with the specified time in milliseconds.
"use client";
import { Carousel } from "@heathmont/moon-core-tw";
const AutoSlide = () => {
const items = Array.from({ length: 25 }, (index) => index);
return (
<div className="flex flex-col w-full items-center">
<Carousel
autoSlideDelay={3000}
step={1}
data-testid="autoSlide-carousel"
className="w-full sm:max-w-auto"
>
<Carousel.Reel>
{items.map((_, index) => (
<Carousel.Item
key={index}
className="w-full max-w-80 h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
</Carousel>
</div>
);
};
export default AutoSlide;
RTL support
"use client";
import { Carousel, Chip } from "@heathmont/moon-core-tw";
import { useState } from "react";
const RTLSupport = () => {
const [selected, setSelected] = useState(0);
const items = Array.from({ length: 5 }, (index) => index);
return (
<div
className="flex flex-col items-center gap-4 w-full"
dir="rtl"
data-testid="carousel"
>
<div className="flex gap-1">
{items.map((_, index) => (
<Chip
key={index}
isActive={selected === index}
onClick={() => setSelected(index)}
className="px-4"
data-testid={`carousel-button-${index}`}
>
{index}
</Chip>
))}
</div>
<Carousel step={1} selectedIndex={selected} className="w-[320px]" isRtl>
<Carousel.Reel>
{items.map((_, index) => (
<Carousel.Item
key={index}
className="w-80 h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
</Carousel>
</div>
);
};
export default RTLSupport;
Swipe or Drag disabled
Add isSwipeDragDisabled
to disable swipe/drag over the carousel content.
"use client";
import { Carousel, Chip } from "@heathmont/moon-core-tw";
import { useState } from "react";
const ITEMS = Array.from({ length: 5 }, (index) => index);
const SwipeDragDisabled = () => {
const [selected, setSelected] = useState(0);
return (
<div className="items-center gap-4 w-full flex flex-col">
<div className="flex gap-1">
{ITEMS.map((_, index) => (
<Chip
key={index}
isActive={selected === index}
onClick={() => setSelected(index)}
className="px-4"
data-testid={`carousel-button-${index}`}
>
{index}
</Chip>
))}
</div>
<Carousel
step={1}
selectedIndex={selected}
className="w-full max-w-80"
data-testid="selectedIndex-carousel"
isSwipeDragDisabled
>
<Carousel.Reel>
{ITEMS.map((_, index) => (
<Carousel.Item
key={index}
className="w-full h-48 border border-beerus"
data-testid={`carousel-${index}`}
>
{index}
</Carousel.Item>
))}
</Carousel.Reel>
</Carousel>
</div>
);
};
export default SwipeDragDisabled;
Carousel
These are props specific to the Carousel component:
Name | Type | Default |
---|---|---|
scrollTo | number | - |
step | number | 5 |
selectedIndex | number | - |
scrollLeftToStep | "() => void" | - |
scrollRightToStep | "() => void" | - |
canScrollLeft | boolean | - |
canScrollRight | boolean | - |
firstVisibleIndex | number | - |
lastVisibleIndex | number | - |
autoSlideDelay | number | - |
isRtl | boolean | - |
isSwipeDragDisabled | boolean | false |