@neynar/ui
Version:
React UI component library built on shadcn/ui and Tailwind CSS
211 lines (197 loc) • 5.41 kB
Markdown
# Carousel
**Type**: component
A responsive carousel/slider component for content presentation The Carousel component provides a touch-friendly, keyboard-accessible way to browse through multiple items. Built on Embla Carousel, it supports various configurations including autoplay, loop, drag scrolling, infinite scroll, momentum scrolling, and both horizontal and vertical orientations. Features include responsive breakpoints, plugin system, smooth animations, focus management, RTL support, and extensive customization options.
## JSX Usage
```jsx
import { Carousel } from '@neynar/ui';
<Carousel
opts={value}
plugins={value}
orientation={value}
setApi={() => {}}
className="value"
>
{/* Your content here */}
</Carousel>
```
## Component Props
### opts
- **Type**: `CarouselOptions`
- **Required**: No
- **Description**: No description available
### plugins
- **Type**: `CarouselPlugin`
- **Required**: No
- **Description**: No description available
### orientation
- **Type**: `"horizontal" | "vertical"`
- **Required**: No
- **Description**: No description available
### setApi
- **Type**: `(api: CarouselApi) => void`
- **Required**: No
- **Description**: No description available
### className
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### children
- **Type**: `React.ReactNode`
- **Required**: No
- **Description**: No description available
## Examples
### Example 1
```tsx
// Basic image carousel
<Carousel className="w-full max-w-xs">
<CarouselContent>
{images.map((src, index) => (
<CarouselItem key={index}>
<img src={src} alt={`Slide ${index + 1}`} className="w-full" />
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
```
### Example 2
```tsx
// Multi-item responsive carousel with custom spacing
<Carousel
opts={{
align: "start",
loop: true,
slidesToScroll: "auto",
breakpoints: {
"(min-width: 768px)": { slidesToScroll: 2 }
}
}}
className="w-full"
>
<CarouselContent className="-ml-2 md:-ml-4">
{products.map((product, index) => (
<CarouselItem key={index} className="pl-2 md:pl-4 md:basis-1/2 lg:basis-1/3">
<Card>
<CardContent className="p-4">
<h3>{product.name}</h3>
<p>{product.price}</p>
</CardContent>
</Card>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
```
### Example 3
```tsx
// Vertical carousel with autoplay plugin
import Autoplay from "embla-carousel-autoplay";
<Carousel
orientation="vertical"
opts={{ loop: true, align: "center" }}
plugins={[Autoplay({ delay: 3000, stopOnInteraction: true, stopOnMouseEnter: true })]}
className="h-[400px]"
>
<CarouselContent className="h-full">
{testimonials.map((testimonial, index) => (
<CarouselItem key={index} className="basis-1/2">
<div className="p-6">
<blockquote>{testimonial.quote}</blockquote>
<cite>{testimonial.author}</cite>
</div>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
```
### Example 4
```tsx
// Controlled carousel with custom indicators and API access
import { useState, useEffect } from "react";
function ControlledCarousel() {
const [api, setApi] = useState<CarouselApi>();
const [current, setCurrent] = useState(0);
const [count, setCount] = useState(0);
useEffect(() => {
if (!api) return;
setCount(api.scrollSnapList().length);
setCurrent(api.selectedScrollSnap() + 1);
api.on('select', () => {
setCurrent(api.selectedScrollSnap() + 1);
});
}, [api]);
return (
<div className="space-y-4">
<Carousel setApi={setApi} opts={{ loop: true }}>
<CarouselContent>
{slides.map((slide, index) => (
<CarouselItem key={index}>{slide.content}</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
// Custom indicators
<div className="flex justify-center gap-2">
{Array.from({ length: count }).map((_, i) => (
<button
key={i}
className={cn(
"w-2 h-2 rounded-full transition-colors",
current === i + 1 ? "bg-primary" : "bg-muted"
)}
onClick={() => api?.scrollTo(i)}
/>
))}
</div>
<div className="text-center text-sm text-muted-foreground">
Slide {current} of {count}
</div>
</div>
);
}
```
### Example 5
```tsx
// Momentum scrolling carousel with drag-free mode
<Carousel
opts={{
dragFree: true,
containScroll: false,
skipSnaps: true
}}
className="w-full"
>
<CarouselContent>
{items.map((item, index) => (
<CarouselItem key={index} className="basis-auto">
<div className="w-32 h-32 bg-muted rounded-lg" />
</CarouselItem>
))}
</CarouselContent>
</Carousel>
```
### Example 6
```tsx
// Breakpoint-responsive carousel that disables on larger screens
<Carousel
opts={{
active: true,
breakpoints: {
"(min-width: 768px)": { active: false }
}
}}
className="md:hidden"
>
<CarouselContent>
{mobileItems.map((item, index) => (
<CarouselItem key={index}>{item}</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
```