{
  "title": "Carousel",
  "description": "Paged horizontal (or vertical) image/card slider with CSS scroll-snap on web and FlatList paging on native.",
  "url": "/docs/components/carousel",
  "since": "0.9.0",
  "tags": [
    "navigation",
    "slider"
  ],
  "platform": "both",
  "source": "---\ntitle: Carousel\ndescription: Paged horizontal (or vertical) image/card slider with CSS scroll-snap on web and FlatList paging on native.\nsince: 0.9.0\ntags: [navigation, slider]\nplatform: both\ncategory: navigation\n---\n\nimport { BundleSize } from '@/components/bundle-size';\nimport { Callout } from 'fumadocs-ui/components/callout';\nimport { Preview } from '@/components/preview';\nimport { PropsTable } from '@/components/props-table';\n\n<BundleSize component=\"Carousel\" />\n\n## At a glance\n\n- Compound API: `Carousel`, `Carousel.Content`, `Carousel.Item`, `Carousel.Previous`, `Carousel.Next`, `Carousel.Dots`.\n- Web: CSS `scroll-snap-type: x mandatory` — no extra dependency.\n- Native: RN `FlatList` with `pagingEnabled` — no carousel peer dep.\n- Controlled or uncontrolled via `index` / `defaultIndex`.\n- `loop` prop wraps navigation from last slide back to first and vice versa.\n\n## Preview\n\n<Preview name=\"carousel-basic\" />\n\n## Usage\n\n```tsx\nimport { Carousel } from '@nori-ui/core';\n\nexport function MyCarousel() {\n    return (\n        <Carousel>\n            <Carousel.Content>\n                <Carousel.Item>\n                    <img src=\"/slide1.jpg\" alt=\"Slide 1\" />\n                </Carousel.Item>\n                <Carousel.Item>\n                    <img src=\"/slide2.jpg\" alt=\"Slide 2\" />\n                </Carousel.Item>\n                <Carousel.Item>\n                    <img src=\"/slide3.jpg\" alt=\"Slide 3\" />\n                </Carousel.Item>\n            </Carousel.Content>\n            <Carousel.Previous />\n            <Carousel.Next />\n            <Carousel.Dots />\n        </Carousel>\n    );\n}\n```\n\n## Controlled\n\n```tsx\nimport { useState } from 'react';\nimport { Carousel } from '@nori-ui/core';\n\nexport function ControlledCarousel() {\n    const [index, setIndex] = useState(0);\n    return (\n        <Carousel index={index} onIndexChange={setIndex}>\n            <Carousel.Content>\n                <Carousel.Item><SlideA /></Carousel.Item>\n                <Carousel.Item><SlideB /></Carousel.Item>\n            </Carousel.Content>\n            <Carousel.Dots />\n        </Carousel>\n    );\n}\n```\n\n## Looping\n\nSet `loop` to wrap from the last slide back to the first when pressing Next, and vice versa:\n\n```tsx\n<Carousel loop>\n  <Carousel.Content>\n    <Carousel.Item>...</Carousel.Item>\n    <Carousel.Item>...</Carousel.Item>\n  </Carousel.Content>\n  <Carousel.Previous />\n  <Carousel.Next />\n</Carousel>\n```\n\n## Platform notes\n\n<Callout type=\"info\">\n**Web:** Each `Carousel.Item` has `scroll-snap-align: start` and `min-width: 100%`. The scrollbar is hidden via `scrollbar-width: none`. Previous/Next buttons call `scrollIntoView` with `behavior: smooth`.\n</Callout>\n\n<Callout type=\"info\">\n**Native:** `Carousel.Content` renders an RN `FlatList` with `pagingEnabled` and `horizontal`. Each item gets `width: windowWidth`. The item list passed as `children` to `Carousel.Content` is unwrapped by the FlatList renderer — `Carousel.Item` on native is just a thin `View` wrapper.\n</Callout>\n\n## Props\n\n### `Carousel`\n\n<PropsTable component=\"Carousel\" />\n\n### `Carousel.Content`\n\nScrollable or FlatList container that holds the `Carousel.Item` children.\nPasses the `orientation` prop down to determine scroll axis (`horizontal` by\ndefault, `vertical` for a vertical stack). On web it renders a scroll-snap\ncontainer; on native it wraps an RN `FlatList` with `pagingEnabled`.\n\n### `Carousel.Item`\n\nSingle slide wrapper. Accepts `children` and an optional `className`. Each\nitem fills the full width (or height, in vertical mode) of the viewport.\n\n### `Carousel.Previous` / `Carousel.Next`\n\nNavigation button that steps the index backward (`Previous`) or forward\n(`Next`). Accepts `children` for custom icon content and an `aria-label` for\nscreen-reader text. Automatically disabled at the boundary unless `loop` is set\non the root.\n\n### `Carousel.Dots`\n\nIndicator track that renders one dot per slide. Accepts `className` for custom\nstyles. The active dot is highlighted; each dot has an accessible\n`aria-label=\"Slide N\"` attribute. Clicking a dot jumps directly to that slide.\n"
}
