Carousel
The Carousel component allows users to cycle through a series of content panels (typically images, cards, or text) in a horizontal or vertical layout. It is commonly used for featured content, product showcases, or testimonials.
Installation
npm install --save @godaddy/antaresProps
The Carousel component accepts the following props:
childrenReactNode | ReactNode[]—The slides of the carousel.
activeIndex?number | undefined—The index of the active slide. (Controlled mode)
defaultActiveIndex?number | undefined—The index of the default active slide. (Uncontrolled mode)
hideMaskEdges?boolean | undefined—Whether to hide the mask edges of the viewport.
hideDots?boolean | undefined—Whether to hide the dots.
hideNavigationControls?boolean | undefined—Whether to hide the navigation controls.
prevButtonProps?ButtonProps | undefined—Props to pass to the previous button.
nextButtonProps?ButtonProps | undefined—Props to pass to the next button.
emblaOptions?Partial<OptionsType> | undefined—All options available for the embla carousel.
emblaAccessibilityOptions?Partial<CreateOptionsType<OptionsType>> | undefined—All options available for the embla accessibility.
onPrev?OnActionCallbackType | undefined—The callback function to be called when the previous slide is pressed.
onNext?OnActionCallbackType | undefined—The callback function to be called when the next slide is pressed.
onChange?OnActionCallbackType | undefined—The callback function to be called when the active slide changes.
display?"flex" | "inline-flex" | undefined'flex'The display property for the flex container.
direction?"row" | "column" | "row-reverse" | "column-reverse" | undefined'row'The direction in which to layout children.
wrap?"wrap" | "nowrap" | "wrap-reverse" | undefined—Whether to wrap items onto multiple lines.
as?(React.ElementType & "div") | undefined'div'Polymorphic element type.
padding?Spacing | Spacing[] | undefined—Padding on all sides. Accepts single value or array.
inlinePadding?Spacing | Spacing[] | undefined—Padding on inline (horizontal) direction.
inlinePaddingStart?Spacing | undefined—Padding on inline start (left in LTR).
inlinePaddingEnd?Spacing | undefined—Padding on inline end (right in LTR).
blockPadding?Spacing | Spacing[] | undefined—Padding on block (vertical) direction.
blockPaddingStart?Spacing | undefined—Padding on block start (top).
blockPaddingEnd?Spacing | undefined—Padding on block end (bottom).
elevation?"base" | "card" | "raised" | "overlay" | undefined—Elevation levels for visual depth.
rounding?Rounding | undefined—Rounding values for border radius.
alignSelf?"center" | (string & {}) | "auto" | "normal" | "start" | "end" | "flex-start" | "flex-end" | "self-start" | "self-end" | "stretch" | undefined—In Flex/Grid layout. Cross-axis alignment within flex/grid container.
justifySelf?"center" | (string & {}) | "auto" | "normal" | "start" | "end" | "flex-start" | "flex-end" | "self-start" | "self-end" | "stretch" | "left" | "right" | undefined—In Flex/Grid layout. Main-axis alignment within flex/grid container.
order?string | number | undefined—In Flex/Grid layout. Layout order within flex/grid container.
flex?string | number | undefined—In Flex/Grid layout. Flex shorthand for grow, shrink, and basis.
flexGrow?string | number | undefined—In Flex/Grid layout. How much the item will grow relative to siblings.
flexShrink?string | number | undefined—In Flex/Grid layout. How much the item will shrink relative to siblings.
flexBasis?string | undefined—In Flex/Grid layout. Initial main size before growing/shrinking.
gridArea?string | undefined—In Flex/Grid layout. Named grid area for placement.
gridColumnStart?string | undefined—In Flex/Grid layout. Grid column start line.
gridColumnEnd?string | undefined—In Flex/Grid layout. Grid column end line.
gridRowStart?string | undefined—In Flex/Grid layout. Grid row start line.
gridRowEnd?string | undefined—In Flex/Grid layout. Grid row end line.
justifyContent?"center" | (string & {}) | "normal" | "start" | "end" | "stretch" | "space-around" | "space-between" | "space-evenly" | undefined—The distribution of space around children along the main axis in flex or inline axis in grid
alignContent?"center" | (string & {}) | "normal" | "start" | "end" | "stretch" | "space-around" | "space-between" | "space-evenly" | "baseline" | undefined—The distribution of space around children along the cross axis in flex or block axis in grid
justifyItems?"center" | (string & {}) | "normal" | "start" | "end" | "stretch" | "legacy" | undefined—Defines the default justify-self for all children in a grid container.
alignItems?"center" | (string & {}) | "normal" | "start" | "end" | "stretch" | "baseline" | undefined—Sets the align-self property for each child.
gap?Spacing | Spacing[] | undefined—The gap between children.
columnGap?Spacing | undefined—The gap between columns.
rowGap?Spacing | undefined—The gap between rows.
inputMode?"search" | "text" | "none" | "tel" | "url" | "email" | "numeric" | "decimal" | undefined—Hints at the type of data that might be entered by the user while editing the element or its contents
is?string | undefined—Specify that a standard HTML element should behave like a defined custom built-in element
Examples
Basic Usage
The default carousel is a carousel that is uncontrolled, it shows the first slide by default. You can also pass the defaultActiveIndex prop to the Carousel component to set the initial active slide index.
import { Carousel, Flex } from '@godaddy/antares';export function DefaultExample() { return ( <Carousel style={{ maxWidth: 400 }}> {Array.from({ length: 3 }).map((_, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ height: 300, background: 'lavender' }}> Slide {index + 1} </Flex> ))} </Carousel> );}Controlled
The controlled carousel is a carousel that is controlled by the activeIndex prop.
import { Carousel, Flex } from '@godaddy/antares';import { useState } from 'react';export function ControlledExample() { const [activeIndex, setActiveIndex] = useState(1); function handlePrev(index: number, _values: { atFirstSlide: boolean; atLastSlide: boolean }) { setActiveIndex(Math.max(0, index - 1)); } function handleNext(index: number, _values: { atFirstSlide: boolean; atLastSlide: boolean }) { setActiveIndex(Math.min(2, index + 1)); } function handleChange(index: number) { setActiveIndex(index); } return ( <Carousel style={{ maxWidth: 400 }} activeIndex={activeIndex} onPrev={handlePrev} onNext={handleNext} onChange={handleChange} > {Array.from({ length: 3 }).map((_, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ height: 300, background: 'lavender' }}> Slide {index + 1} </Flex> ))} </Carousel> );}External Controls (Uncontrolled)
You can control the carousel externally by passing the ref prop to the Carousel component and using the emblaApi to control the carousel imperatively.
import { Button, Icon, Carousel, Flex, type CarouselRef } from '@godaddy/antares';import { useRef } from 'react';const TOTAL_SLIDES = 3;export function ExternalControlsUncontrolledExample() { const carouselRef = useRef<CarouselRef>(null); function handlePrev() { carouselRef.current?.emblaApi?.goToPrev(); } function handleNext() { carouselRef.current?.emblaApi?.goToNext(); } return ( <Flex direction="column" gap="md" style={{ maxWidth: 400 }}> <Flex direction="row" gap="md" alignSelf="end"> <Button variant="secondary" aria-label="External prev slide" onClick={handlePrev}> <Icon icon="chevron-left" /> </Button> <Button variant="secondary" aria-label="External next slide" onClick={handleNext}> <Icon icon="chevron-right" /> </Button> </Flex> <Carousel hideNavigationControls ref={carouselRef} id="carousel"> {Array.from({ length: TOTAL_SLIDES }).map((_, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ height: 300, background: 'lavender' }}> Slide {index + 1} </Flex> ))} </Carousel> </Flex> );}External Controls (Controlled)
You can control the carousel externally by using the activeIndex prop to control the active slide index.
import { Button, Icon, Carousel, Flex } from '@godaddy/antares';import { useState } from 'react';const TOTAL_SLIDES = 3;export function ExternalControlsControlledExample() { const [activeIndex, setActiveIndex] = useState(1); function handlePrev() { setActiveIndex(Math.max(0, activeIndex - 1)); } function handleNext() { setActiveIndex(Math.min(TOTAL_SLIDES - 1, activeIndex + 1)); } return ( <Flex direction="column" gap="md" style={{ maxWidth: 400 }}> <Flex direction="row" gap="md" alignSelf="end"> <Button variant="secondary" aria-label="External prev slide" onClick={handlePrev} isDisabled={activeIndex === 0} > <Icon icon="chevron-left" /> </Button> <Button variant="secondary" aria-label="External next slide" onClick={handleNext} isDisabled={activeIndex === TOTAL_SLIDES - 1} > <Icon icon="chevron-right" /> </Button> </Flex> <Carousel hideDots hideNavigationControls activeIndex={activeIndex}> {Array.from({ length: TOTAL_SLIDES }).map((_, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ height: 300, background: 'lavender' }}> Slide {index + 1} </Flex> ))} </Carousel> </Flex> );}Hide Controls
The hide controls carousel is a carousel that hides the navigation controls.
import { Carousel, Flex } from '@godaddy/antares';export function HideControlsExample() { return ( <Carousel style={{ maxWidth: 400 }} hideNavigationControls hideDots> {Array.from({ length: 3 }).map((_, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ height: 300, background: 'lavender' }}> Slide {index + 1} </Flex> ))} </Carousel> );}Variable Widths
It supports multiple slides with different widths.
import { Carousel, Flex } from '@godaddy/antares';const SLIDE_WIDTHS = [200, 100, 300, 100, 200];export function VariableWidthsExample() { return ( <Carousel style={{ maxWidth: 400 }}> {SLIDE_WIDTHS.map((width, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ width, height: 300, background: 'lavender' }} > Slide {index + 1} </Flex> ))} </Carousel> );}Events
You can listen to events like onChange, onPrev, or onNext.
import { Box, Carousel, Flex } from '@godaddy/antares';import { useState } from 'react';export function EventsExample() { const [message, setMessage] = useState('Listening for change events...'); const [messagePrev, setMessagePrev] = useState('Listening for prev events...'); const [messageNext, setMessageNext] = useState('Listening for next events...'); function handleChange(index: number, values: { atFirstSlide: boolean; atLastSlide: boolean }) { setMessage(`onChange: ${index}, firstSlide: ${values.atFirstSlide}, lastSlide: ${values.atLastSlide}`); } function handlePrev(index: number, values: { atFirstSlide: boolean; atLastSlide: boolean }) { setMessagePrev(`onPrev: ${index}, firstSlide: ${values.atFirstSlide}, lastSlide: ${values.atLastSlide}`); } function handleNext(index: number, values: { atFirstSlide: boolean; atLastSlide: boolean }) { setMessageNext(`onNext: ${index}, firstSlide: ${values.atFirstSlide}, lastSlide: ${values.atLastSlide}`); } return ( <Flex direction="column" gap="md"> <Box>{message}</Box> <Box>{messagePrev}</Box> <Box>{messageNext}</Box> <Carousel style={{ maxWidth: 400 }} defaultActiveIndex={2} onChange={handleChange} onPrev={handlePrev} onNext={handleNext} > {Array.from({ length: 3 }).map((_, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ height: 300, background: 'lavender' }}> Slide {index + 1} </Flex> ))} </Carousel> </Flex> );}RTL Direction
The carousel follows the current layout direction (LTR or RTL). By default, that direction is detected automatically from the browser or system settings.
import { Carousel, Flex } from '@godaddy/antares';import { RTLProvider } from '../../../utils/rtl-locale-provider.tsx';export function RTLDirectionExample() { return ( <RTLProvider> <Carousel style={{ maxWidth: 400 }}> {Array.from({ length: 3 }).map((_, index) => ( <Flex key={index} alignItems="center" justifyContent="center" style={{ height: 300, background: 'lavender' }}> Slide {index + 1} </Flex> ))} </Carousel> </RTLProvider> );}