import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from '@hanzo/ui'
Three slides with the previous and next arrows.
One command scaffolds the app and its config.
Every push builds on the runners.
A merge to main publishes the site.
export function Default() {return (<YStack width="100%" minW={0} px={40}><Carousel width="100%" maxW={360}><CarouselContent>{steps.map(([title, body]) => (<CarouselItem key={title}><YStack p="$5" gap="$2" rounded="$4" borderWidth={1} borderColor="$borderColor" ><Text fontWeight="600">{title}</Text><Paragraph color="$color11">{body}</Paragraph></YStack></CarouselItem>))}</CarouselContent><CarouselPrevious /><CarouselNext /></Carousel></YStack>)}
Wraps at the ends and advances every four seconds until the pointer is over it.
One command scaffolds the app and its config.
Every push builds on the runners.
A merge to main publishes the site.
export function LoopAutoplay() {return (<YStack width="100%" minW={0} px={40}><Carousel width="100%" maxW={360} options={{ loop: true, autoplay: 4000 }} ><CarouselContent>{steps.map(([title, body]) => (<CarouselItem key={title}><YStack p="$5" gap="$2" rounded="$4" bg="$color3"><Text fontWeight="600">{title}</Text><Paragraph color="$color11">{body}</Paragraph></YStack></CarouselItem>))}</CarouselContent></Carousel></YStack>)}
The caller keeps the api and reads which slide settled.
Slide 1 of 3
Back to the firstexport function WithApi() {const [api, setApi] = useState<CarouselApi | null>(null)const [index, setIndex] = useState(0)return (<YStack gap="$3"><YStack width="100%" minW={0} px={40}><Carousel width={360} setApi={setApi} onCarouselSelect={(a) => setIndex(a.selectedScrollSnap())} ><CarouselContent>{steps.map(([title]) => (<CarouselItem key={title}><YStack p="$5" rounded="$4" bg="$color3"><Text fontWeight="600">{title}</Text></YStack></CarouselItem>))}</CarouselContent></Carousel></YStack><Paragraph color="$color11">Slide {index + 1} of {steps.length}</Paragraph><Text fontSize={13} color="$color12" cursor="pointer" onPress={() => api?.scrollTo(0)} >Back to the first</Text></YStack>)}
export type CarouselOptions = {/** Past the last slide, go to the first — and the reverse. */loop?: boolean/** The slide it opens on. Default 0. */startIndex?: number/** Where a slide settles in the viewport. Default `center`. */align?: 'start' | 'center' | 'end'/*** Advance every N milliseconds.** Stops while the pointer is over the carousel or focus is inside it, and* never starts at all under `prefers-reduced-motion` — a carousel that moves* on its own is the canonical vestibular trigger, and it also steals the* slide out from under someone still reading it.*/autoplay?: number}
export type CarouselApi = {/*** Centre slide `index`. Out of range clamps, or wraps when `loop`.** `jump` arrives there without animating, which is what opening ON a slide* wants — animating from the first one reads as the carousel moving by* itself the moment it appears.*/scrollTo: (index: number, jump?: boolean) => voidscrollPrev: () => voidscrollNext: () => void/** The slide nearest the centre, or -1 when there are none. */selectedScrollSnap: () => numbercanScrollPrev: () => booleancanScrollNext: () => booleanslideCount: () => number/*** Where each slide comes to rest, in scroll pixels.** Its length is the number of slides, which is what a dot strip beneath a* carousel counts — and counting the API rather than the source array is what* keeps the dots right when the slides are conditional.*/scrollSnapList: () => number[]/** Subscribe. `select` fires when the settled slide changes. */on: (event: 'select', listener: () => void) => voidoff: (event: 'select', listener: () => void) => void}
export type CarouselProps = Omit<React.ComponentProps<typeof Box>, 'onSelect'> & {options?: CarouselOptions/** Handed the api once, on mount. */setApi?: (api: CarouselApi) => void/** Fires when the settled slide CHANGES — not on mount. */onCarouselSelect?: (api: CarouselApi) => void}