# Carousel A flexible carousel component for displaying sequences of content with navigation and pagination options. ## Import ```tsx import { Carousel } from '@coinbase/cds-web/carousel/Carousel' ``` ## Examples ### Basic Example Carousels are a great way to showcase a list of items in a compact and engaging way. By default, Carousels have navigation and pagination enabled. You can also add a title to the Carousel by setting `title` prop. You simply wrap each child in a `CarouselItem` component, and can optionally set the `width` prop to control the width of the item. You can also set the `styles` prop to control the styles of the carousel, such as the gap between items. :::tip Images Images inside of the carousel have `pointer-events` disabled by default. ::: ```jsx live function MyCarousel() { function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } return ( {Object.values(assets).map((asset, index) => ( ))} ); } ``` ### Item Sizing Items by default take their natural width while in the carousel, such as from our example above. However, you can set the `width` prop of `CarouselItem` to control the width of the item. #### Dynamic Sizing Items can be given a width proportional to the carousel width. :::tip Tip If you have a gap between items, you should account for that in the width. For example, if you have a gap of 8px, and you want to show 2 items per page, you should give each item a width of `calc(50% - 4px)`. ::: ```jsx live function DynamicSizingCarousel() { const itemsPerPage = [ { id: 'one', label: 'One' }, { id: 'two', label: 'Two' }, { id: 'three', label: 'Three' }, ]; const [selectedItemsPerPage, setSelectedItemsPerPage] = useState(itemsPerPage[0]); const itemWidths = { one: '100%', two: 'calc((100% - var(--space-1)) / 2)', three: 'calc((100% - (2 * var(--space-1))) / 3)', }; function NoopFn() { console.log('pressed'); } function ActionButton({ isVisible, children }) { return ( ); } return ( Items per page {({ isVisible }) => ( Get started} description="Want to add funds to your card every week or month?" media={ } minWidth="0" title={ Recurring Buy } width="100%" /> )} {({ isVisible }) => ( Start earning} dangerouslySetBackground="rgb(var(--purple70))" description={ Earn staking rewards on ETH by holding it on Coinbase } media={ } minWidth="0" title={ Up to 3.29% APR on ETHs } width="100%" /> )} {({ isVisible }) => ( Start chatting} dangerouslySetBackground="rgb(var(--teal70))" description={ Chat with other devs in our Discord community } media={ } minWidth="0" title={ Join the community } width="100%" /> )} {({ isVisible }) => ( Get 60 days free} dangerouslySetBackground="rgb(var(--blue80))" description={ Use code NOV60 when you sign up for Coinbase One } media={ } minWidth="0" title={ Coinbase One offer } width="100%" /> )} {({ isVisible }) => ( Get started} dangerouslySetBackground="rgb(var(--gray100))" description={ Spend USDC to get rewards with our Visa® debit card } media={ } minWidth="0" title={ Coinbase Card } width="100%" /> )} ); } ``` #### Responsive Sizing You can also use responsive props to change the number of items visible based on the carousel width. The carousel below will show per page 1 item on mobile, 2 items on tablet, and 3 items on desktop. ```jsx live function ResponsiveSizingCarousel() { const itemWidth = { phone: '100%', tablet: 'calc((100% - var(--space-1)) / 2)', desktop: 'calc((100% - (2 * var(--space-1))) / 3)', }; function NoopFn() { console.log('pressed'); } function ActionButton({ isVisible, children }) { return ( {children} ); } return ( {({ isVisible }) => ( Start earning} width="100%" minWidth="0" /> )} {({ isVisible }) => ( Enable 2FA} width="100%" minWidth="0" /> )} {({ isVisible }) => ( Update} width="100%" minWidth="0" /> )} ); } ``` #### Varied Sizing Not all carousel items need to be the same size. You can provide CarouselItems of varying widths as well. ```jsx live function VariedSizingCarousel() { function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } function NoopFn() { console.log('pressed'); } function ActionButton({ isVisible, children }) { return ( {children} ); } const itemWidth = { phone: '100%', tablet: 'calc((100% - var(--space-1)) / 2)', desktop: 'calc((100% - var(--space-1)) / 2)', }; return ( {({ isVisible }) => ( Start earning} width="100%" minWidth="0" /> )} {({ isVisible }) => ( Enable 2FA} width="100%" minWidth="0" /> )} {({ isVisible }) => ( Update profile} width="100%" minWidth="0" /> )} ); } ``` ### Drag You can set the `drag` prop to `snap` (default), `free`, or `none`. When set to `snap`, upon release the carousel will snap to either the nearest item or page (depending on `snapMode`). ```jsx live function DragCarousel() { const dragOptions = [ { id: 'snap', label: 'Snap' }, { id: 'free', label: 'Free' }, { id: 'none', label: 'None' }, ]; const [drag, setDrag] = useState(dragOptions[0]); function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } return ( Drag {Object.values(assets).map((asset, index) => ( ))} ); } ``` ### Snap Mode You can set the `snapMode` to `page` (default) or `item`. When set to `page`, the carousel will automatically group items into pages. When set to `item`, the carousel will snap to the nearest item. ```jsx live function SnapModeCarousel() { const snapModeOptions = [ { id: 'page', label: 'Page' }, { id: 'item', label: 'Item' }, ]; const [snapMode, setSnapMode] = useState(snapModeOptions[0]); function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } return ( Snap mode {Object.values(assets).map((asset, index) => ( ))} ); } ``` ### Overflow By default, the carousel's inner overflow is visible. This means that you can apply padding to the inner carousel element (such as `styles={{ carousel: { paddingInline: 'var(--space-3)' } }}`) and it will not be clipped. You can pair this with modifying the spacing of the inner carousel to match the padding of your page (along with a wrapping div to negate any default spacing). This creates a seamless experience. :::tip Tip If you want to have the next item be shown at the edge of the screen, make sure your carousel padding is larger than your gap. ::: ```jsx live function OverflowCarousel() { function SquareAssetCard({ isVisible, imageUrl, name }) { return ( ↗6.37% } header={} onClick={isVisible ? () => console.log('clicked') : undefined} subtitle={name} title="$0.87" /> ); } return ( {Object.values(assets).map((asset, index) => ( {({ isVisible }) => ( )} ))} ); } ``` ### Accessibility The carousel is accessible by default. You need to use `accessibilityLabel` or `accessibilityLabelledBy` props to provide a label for the carousel items. If you have elements that are focusable, you can use `isVisible` render prop to disable focus when the item is not visible. ```jsx {({ isVisible }) => ( Get started } description="Want to add funds to your card every week or month?" media={ } minWidth="0" title={ Recurring Buy } width="100%" /> )} ``` ### Customization #### Custom Components You can customize the navigation and pagination components of the carousel using the `NavigationComponent` and `PaginationComponent` props. You can also modify the title by providing a ReactNode for the `title` prop. ```jsx live function CustomComponentsCarousel() { function SeeAllComponent({ style }) { return ( See all ); } function PaginationComponent({ totalPages, activePageIndex, onClickPage, style }) { const canGoPrevious = activePageIndex > 0; const canGoNext = activePageIndex < totalPages - 1; const dotStyles = { width: 'var(--space-2)', height: 'var(--space-2)', borderRadius: 'var(--borderRadius-1000)', } as const; function onPrevious() { onClickPage(activePageIndex - 1); } function onNext() { onClickPage(activePageIndex + 1); } return ( {Array.from({ length: totalPages }, (_, index) => ( onClickPage(index)} style={dotStyles} /> ))} ); } function NoopFn() { console.log('pressed'); } function ActionButton({ isVisible, children }) { return ( ); } const itemWidth = { phone: '100%', tablet: 'round(down, calc((100% - var(--space-1)) / 2), 1px)', desktop: 'round(down, calc((100% - var(--space-1)) / 2), 1px)', }; return ( Learn more } > {({ isVisible }) => ( Get started} description="Want to add funds to your card every week or month?" media={ } minWidth="0" title="Recurring Buy" width="100%" /> )} {({ isVisible }) => ( Start earning} dangerouslySetBackground="rgb(var(--purple70))" description={ Earn staking rewards on ETH by holding it on Coinbase } media={ } minWidth="0" title={ Up to 3.29% APR on ETHs } width="100%" /> )} {({ isVisible }) => ( Start chatting} dangerouslySetBackground="rgb(var(--teal70))" description={ Chat with other devs in our Discord community } media={ } minWidth="0" title={ Join the community } width="100%" /> )} {({ isVisible }) => ( Get 60 days free} dangerouslySetBackground="rgb(var(--blue80))" description={ Use code NOV60 when you sign up for Coinbase One } media={ } minWidth="0" title={ Coinbase One offer } width="100%" /> )} {({ isVisible }) => ( Get started} dangerouslySetBackground="rgb(var(--gray100))" description={ Spend USDC to get rewards with our Visa® debit card } media={ } minWidth="0" title={ Coinbase Card } width="100%" /> )} ); } ``` #### Custom Styles You can use the `classNames` and `styles` props to customize different parts of the carousel. ```jsx live function CustomStylesCarousel() { return ( { return ( ); }} > console.log('Action pressed')} width="100%" minWidth="0" /> console.log('Enable 2FA pressed')} width="100%" minWidth="0" /> console.log('Update profile pressed')} width="100%" minWidth="0" /> ); } ``` #### Dynamic Content You can dynamically add and remove items from the carousel. ```jsx live function DynamicContentCarousel() { const [items, setItems] = useState(Object.values(assets).slice(0, 3)); function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } function addAsset() { const randomAsset = Object.values(assets)[Math.floor(Math.random() * Object.values(assets).length)]; setItems([...items, { ...randomAsset, symbol: `${randomAsset.symbol}-${items.length}` }]); } return ( {items.map((asset, index) => ( ))} ); } ``` You can also animate items as they enter or leave the viewport. ```jsx live function AnimatedCarousel() { function SquareAssetCard({ imageUrl, name }) { const ref = useRef(null); // useInView is a framer motion hook that detects when an element is in the viewport const isInView = useInView(ref, { amount: 0.5, once: false, }); return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } return ( {Object.values(assets).map((asset, index) => ( ))} ); } ``` You can even change the size or content of items. In the example below, click an asset to highlight it. ```jsx live function AnimatedSelectionCarousel() { const dimensions = { width: 140, height: 60 }; const path = useSparklinePath({ ...dimensions, data: prices }); const SquareAssetCard = memo(({ isVisible, imageUrl, name, color }) => { const squareSize = 156; const largeSize = 327; const [isHighlighted, setIsHighlighted] = useState(false); const [size, setSize] = useState('s'); const handleClick = useCallback(() => { setIsHighlighted((highlighted) => !highlighted); }, [setIsHighlighted]); const onAnimationStart = useCallback(() => { if (isHighlighted) { setSize('l'); } }, [isHighlighted, setSize]); const onAnimationComplete = useCallback(() => { if (!isHighlighted) { setSize('s'); } }, [isHighlighted, setSize]); return ( ↗6.37% } header={} subtitle={name} title="$0.87" style={{ maxWidth: largeSize, width: '100%' }} size={size} > ); }); return ( {Object.values(assets).map((asset, index) => ( {({ isVisible }) => ( )} ))} ); } ``` #### Hide Navigation and Pagination You can hide the navigation and pagination components of the carousel if desired (using `hideNavigation` and `hidePagination` props). Note that this can prevent proper accessibility for the carousel. If hiding pagination, it's recommended instead to pass in `DefaultCarouselNavigation` with `hideUnlessFocused` prop. Alternatively, you can ensure that the carousel is navigable by keyboard through other means. ```jsx live function HideNavigationAndPaginationCarousel() { function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } return ( } drag="free" snapMode="item" styles={{ root: { paddingInline: 'var(--space-3)' }, carousel: { gap: 'var(--space-1)' }, }} > {Object.values(assets).map((asset, index) => ( ))} ); } ``` #### Animated Pagination You can create smooth pagination animations by customizing the pagination dots. This example shows how to create expanding dots that smoothly transition between active and inactive states. ```jsx live function AnimatedPaginationCarousel() { const AnimatedPagination = memo((props) => { const { totalPages, activePageIndex, onClickPage, style } = props; const dotStyles = { height: 'var(--space-1)', borderRadius: 'var(--borderRadius-1000)', transition: 'all 0.3s ease', cursor: 'pointer', }; return ( {Array.from({ length: totalPages }, (_, index) => { const isActive = index === activePageIndex; return ( onClickPage?.(index)} style={{ ...dotStyles, width: isActive ? 'var(--space-3)' : 'var(--space-1)', }} /> ); })} ); }); function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } return ( {Object.values(assets).map((asset, index) => ( ))} ); } ``` ### Imperative API You can control the carousel programmatically using a ref. The carousel exposes methods to navigate to specific pages and access the current page index. ```jsx live function ImperativeApiCarousel() { const carouselRef = useRef(null); const [currentPageInfo, setCurrentPageInfo] = useState('Page 1'); function handleGoToPage(pageIndex: number) { if (carouselRef.current) { const clampedPageIndex = Math.max(0, Math.min(carouselRef.current.totalPages - 1, pageIndex)); carouselRef.current.goToPage(clampedPageIndex); setCurrentPageInfo(`Page ${clampedPageIndex + 1}`); } } function handleGoToFirstPage() { handleGoToPage(0); } function handleGoToLastPage() { if (carouselRef.current) { handleGoToPage(carouselRef.current.totalPages - 1); } } function handleGoToPrevPage() { if (carouselRef.current) { handleGoToPage(carouselRef.current.activePageIndex - 1); } } function handleGoToNextPage() { if (carouselRef.current) { handleGoToPage(carouselRef.current.activePageIndex + 1); } } function SquareAssetCard({ imageUrl, name }) { return ( ↗6.37% } header={} subtitle={name} title="$0.87" /> ); } return ( {currentPageInfo} {Object.values(assets).map((asset, index) => ( ))} ); } ``` ### Callbacks You can use the `onChangePage`, `onDragStart`, and `onDragEnd` callbacks to listen for user interaction in the carousel. ```tsx console.log('Page changed', activePageIndex)} onDragStart={() => console.log('Drag started')} onDragEnd={() => console.log('Drag ended')} > ... ``` ## Props | Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | `NavigationComponent` | `CarouselNavigationComponent` | No | `DefaultCarouselNavigation` | Custom component to render navigation arrows. | | `PaginationComponent` | `CarouselPaginationComponent` | No | `DefaultCarouselPagination` | Custom component to render pagination indicators. | | `alignContent` | `ResponsiveProp
` | No | `-` | - | | `alignItems` | `ResponsiveProp
` | No | `-` | - | | `alignSelf` | `ResponsiveProp
` | No | `-` | - | | `as` | `div` | No | `-` | - | | `aspectRatio` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - | | `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - | | `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - | | `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - | | `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - | | `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - | | `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - | | `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - | | `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - | | `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - | | `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - | | `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - | | `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. | | `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. | | `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. | | `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. | | `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. | | `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. | | `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. | | `bottom` | `ResponsiveProp>` | No | `-` | - | | `classNames` | `{ root?: string; title?: string \| undefined; navigation?: string \| undefined; pagination?: string \| undefined; carousel?: string \| undefined; carouselContainer?: string \| undefined; } \| undefined` | No | `-` | Custom class names for the component. | | `color` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - | | `columnGap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `dangerouslySetBackground` | `string` | No | `-` | - | | `display` | `ResponsiveProp` | No | `-` | - | | `drag` | `none \| free \| snap` | No | `'snap'` | Defines the drag interaction behavior for the carousel. none disables dragging completely. free enables free-form dragging with natural deceleration when released. snap enables dragging with automatic snapping to targets when released, defined by snapMode. | | `elevation` | `0 \| 1 \| 2` | No | `-` | - | | `flexBasis` | `ResponsiveProp>` | No | `-` | - | | `flexDirection` | `ResponsiveProp` | No | `-` | - | | `flexGrow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset` | No | `-` | - | | `flexShrink` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset` | No | `-` | - | | `flexWrap` | `ResponsiveProp` | No | `-` | - | | `font` | `ResponsiveProp` | No | `-` | - | | `fontFamily` | `ResponsiveProp` | No | `-` | - | | `fontSize` | `ResponsiveProp` | No | `-` | - | | `fontWeight` | `ResponsiveProp` | No | `-` | - | | `gap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `grid` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - | | `gridArea` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `gridAutoColumns` | `ResponsiveProp>` | No | `-` | - | | `gridAutoFlow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| row \| column \| dense` | No | `-` | - | | `gridAutoRows` | `ResponsiveProp>` | No | `-` | - | | `gridColumn` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `gridColumnEnd` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `gridColumnStart` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `gridRow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `gridRowEnd` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `gridRowStart` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `gridTemplate` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - | | `gridTemplateAreas` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - | | `gridTemplateColumns` | `ResponsiveProp>` | No | `-` | - | | `gridTemplateRows` | `ResponsiveProp>` | No | `-` | - | | `height` | `ResponsiveProp>` | No | `-` | - | | `hideNavigation` | `boolean` | No | `-` | Hides the navigation arrows (previous/next buttons). | | `hidePagination` | `boolean` | No | `-` | Hides the pagination indicators (dots/bars showing current page). | | `justifyContent` | `ResponsiveProp` | No | `-` | - | | `key` | `Key \| null` | No | `-` | - | | `left` | `ResponsiveProp>` | No | `-` | - | | `lineHeight` | `ResponsiveProp` | No | `-` | - | | `margin` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - | | `marginBottom` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - | | `marginEnd` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - | | `marginStart` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - | | `marginTop` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - | | `marginX` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - | | `marginY` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - | | `maxHeight` | `ResponsiveProp>` | No | `-` | - | | `maxWidth` | `ResponsiveProp>` | No | `-` | - | | `minHeight` | `ResponsiveProp>` | No | `-` | - | | `minWidth` | `ResponsiveProp>` | No | `-` | - | | `nextPageAccessibilityLabel` | `string` | No | `-` | Accessibility label for the next page button. | | `onChange` | `FormEventHandler` | No | `-` | - | | `onChangePage` | `((activePageIndex: number) => void)` | No | `-` | Callback fired when the carousel page changes. | | `opacity` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset` | No | `-` | - | | `overflow` | `ResponsiveProp` | No | `-` | - | | `padding` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `paddingBottom` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `paddingEnd` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `paddingStart` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `paddingTop` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `paddingX` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `paddingY` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `paginationAccessibilityLabel` | `string \| ((pageIndex: number) => string)` | No | `-` | Accessibility label for the go to page button. | | `pin` | `top \| bottom \| left \| right \| all` | No | `-` | Direction in which to absolutely pin the box. | | `position` | `ResponsiveProp` | No | `-` | - | | `previousPageAccessibilityLabel` | `string` | No | `-` | Accessibility label for the previous page button. | | `ref` | `((instance: CarouselImperativeHandle \| null) => void) \| RefObject \| null` | No | `-` | - | | `right` | `ResponsiveProp>` | No | `-` | - | | `rowGap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `snapMode` | `page \| item` | No | `'page'` | Specifies the pagination and navigation strategy for the carousel. item treats each item as a separate page for navigation, pagination, and snapping. page groups items into pages based on visible area for navigation, pagination, and snapping. This affects page calculation, navigation button behavior, and snap targets when dragging. | | `style` | `CSSProperties` | No | `-` | Custom styles for the root element. | | `styles` | `{ root?: CSSProperties; title?: CSSProperties \| undefined; navigation?: CSSProperties \| undefined; pagination?: CSSProperties \| undefined; carousel?: CSSProperties \| undefined; carouselContainer?: CSSProperties \| undefined; } \| undefined` | No | `-` | Custom styles for the component. | | `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID | | `textAlign` | `ResponsiveProp
` | No | `-` | - | | `textDecoration` | `ResponsiveProp` | No | `-` | - | | `textTransform` | `ResponsiveProp` | No | `-` | - | | `title` | `null \| string \| number \| false \| true \| ReactElement> \| Iterable \| ReactPortal` | No | `-` | Title to display above the carousel. When a string is provided, it will be rendered with default title styling. When a React element is provided, it completely replaces the default title component and styling. | | `top` | `ResponsiveProp>` | No | `-` | - | | `transform` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - | | `userSelect` | `ResponsiveProp` | No | `-` | - | | `visibility` | `ResponsiveProp` | No | `-` | - | | `width` | `ResponsiveProp>` | No | `-` | - | | `zIndex` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |