shadcn.io is not affiliated with official shadcn/ui
Shadcn Carousel for React and Tailwind
An interactive slideshow for cycling through items.
1
2
3
4
5
6
7
8
Installation
bunx --bun shadcn@latest add https://kit.dev/r/carousel.jsonpnpm dlx shadcn@latest add https://kit.dev/r/carousel.jsonnpx shadcn@latest add https://kit.dev/r/carousel.jsonyarn shadcn@latest add https://kit.dev/r/carousel.jsonThis component depends on Button. Install it first if you haven't already.
Install the following dependencies:
bun add @ark-ui/react lucide-reactpnpm add @ark-ui/react lucide-reactnpm install @ark-ui/react lucide-reactyarn add @ark-ui/react lucide-reactCopy and paste the following code into your project.
"use client";
import {
Carousel as ArkCarousel,
useCarousel as useArkCarousel,
useCarouselContext as useArkCarouselContext,
} from "@ark-ui/react/carousel";
import {
ChevronLeftIcon,
ChevronRightIcon,
PauseIcon,
PlayIcon,
} from "lucide-react";
import type React from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
export const useCarousel: typeof useArkCarousel = (props) =>
useArkCarousel({ spacing: "16px", ...props });
export const useCarouselContext = useArkCarouselContext;
export const CarouselContext = ArkCarousel.Context;
const carouselRootClassName = cn(
"relative",
"flex flex-col",
"data-[orientation=vertical]:w-max data-[orientation=vertical]:flex-row"
);
export const Carousel = (
props: React.ComponentProps<typeof ArkCarousel.Root>
) => {
const { spacing = "16px", className, ...rest } = props;
return (
<ArkCarousel.Root
className={cn(carouselRootClassName, className)}
data-slot="carousel"
spacing={spacing}
{...rest}
/>
);
};
export const CarouselRootProvider = (
props: React.ComponentProps<typeof ArkCarousel.RootProvider>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.RootProvider
className={cn(carouselRootClassName, className)}
data-slot="carousel"
{...rest}
/>
);
};
export const CarouselControl = (
props: React.ComponentProps<typeof ArkCarousel.Control>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.Control
className={cn(
"flex items-center justify-between gap-2",
"data-[orientation=vertical]:flex-col",
className
)}
data-slot="carousel-control"
{...rest}
/>
);
};
export const CarouselPrevious = (
props: React.ComponentProps<typeof ArkCarousel.PrevTrigger>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.PrevTrigger
className={cn(
"absolute",
"data-[orientation=horizontal]:-inset-s-12 data-[orientation=horizontal]:top-1/2 data-[orientation=horizontal]:-translate-y-1/2",
"data-[orientation=vertical]:-top-12 data-[orientation=vertical]:left-1/2 data-[orientation=vertical]:-translate-x-1/2 data-[orientation=vertical]:rotate-90",
className
)}
data-slot="carousel-previous"
{...rest}
asChild
>
<Button
aria-label="Previous slide"
clickEffect={false}
pill
size="icon-md"
variant="outline"
>
<ChevronLeftIcon aria-hidden="true" />
</Button>
</ArkCarousel.PrevTrigger>
);
};
export const CarouselNext = (
props: React.ComponentProps<typeof ArkCarousel.NextTrigger>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.NextTrigger
className={cn(
"absolute",
"data-[orientation=horizontal]:-inset-e-12 data-[orientation=horizontal]:top-1/2 data-[orientation=horizontal]:-translate-y-1/2",
"data-[orientation=vertical]:-bottom-12 data-[orientation=vertical]:left-1/2 data-[orientation=vertical]:-translate-x-1/2 data-[orientation=vertical]:rotate-90",
className
)}
{...rest}
asChild
data-slot="carousel-next"
>
<Button
aria-label="Next slide"
clickEffect={false}
pill
size="icon-md"
variant="outline"
>
<ChevronRightIcon aria-hidden="true" />
</Button>
</ArkCarousel.NextTrigger>
);
};
export const CarouselIndicatorGroup = (
props: React.ComponentProps<typeof ArkCarousel.IndicatorGroup>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.IndicatorGroup
className={cn(
"flex justify-center gap-2",
"data-[orientation=vertical]:flex-col",
className
)}
data-slot="carousel-indicator-group"
{...rest}
/>
);
};
export const CarouselIndicator = (
props: React.ComponentProps<typeof ArkCarousel.Indicator>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.Indicator
className={cn(
"size-2",
"shrink-0",
"bg-foreground",
"opacity-64 data-current:opacity-100",
"overflow-hidden",
"[&_img]:size-full [&_img]:rounded-lg [&_img]:object-cover",
"rounded-full",
className
)}
data-slot="carousel-indicator"
{...rest}
/>
);
};
export const CarouselContent = (
props: React.ComponentProps<typeof ArkCarousel.ItemGroup>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.ItemGroup
className={cn(
"min-w-0",
"-my-4 py-4",
"overflow-hidden rounded-lg",
className
)}
data-slot="carousel-group"
{...rest}
/>
);
};
export const CarouselItem = (
props: React.ComponentProps<typeof ArkCarousel.Item>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.Item
className={cn(
"min-w-0",
"[&_img]:size-full [&_img]:rounded-lg [&_img]:object-cover",
className
)}
data-slot="carousel-item"
{...rest}
/>
);
};
export const CarouselAutoplayTrigger = (
props: React.ComponentProps<typeof ArkCarousel.AutoplayTrigger>
) => {
const { className, children, ...rest } = props;
return (
<ArkCarousel.AutoplayTrigger
className={className}
data-slot="carousel-autoplay-trigger"
{...rest}
asChild
>
{children ?? (
<Button
aria-label="Toggle autoplay"
clickEffect={false}
pill
size="icon-md"
variant="outline"
>
<ArkCarousel.AutoplayIndicator
fallback={<PlayIcon aria-hidden="true" />}
>
<PauseIcon aria-hidden="true" />
</ArkCarousel.AutoplayIndicator>
</Button>
)}
</ArkCarousel.AutoplayTrigger>
);
};
export const CarouselAutoplayIndicator = (
props: React.ComponentProps<typeof ArkCarousel.AutoplayIndicator>
) => (
<ArkCarousel.AutoplayIndicator
data-slot="carousel-autoplay-indicator"
{...props}
/>
);
export const CarouselProgressText = (
props: React.ComponentProps<typeof ArkCarousel.ProgressText>
) => {
const { className, ...rest } = props;
return (
<ArkCarousel.ProgressText
className={cn("text-muted-foreground text-sm", className)}
data-slot="carousel-progress-text"
{...rest}
/>
);
};Update the import paths to match your project setup.
Anatomy
Carousel
├── CarouselItem
│ └── CarouselContent
├── CarouselControl
├── CarouselNext
├── CarouselPrevious
├── CarouselIndicator
│ └── CarouselIndicatorGroup
├── CarouselAutoplayTrigger
└── CarouselProgressTextUsage
import { Card, CardContent } from "@/components/ui/card";
import {
Carousel,
CarouselContent,
CarouselControl,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";const slides = [1, 2, 3, 4, 5, 6, 7, 8];
const CarouselDemo = () => (
<Carousel className="w-full max-w-48 sm:max-w-64" slideCount={slides.length}>
<CarouselControl>
<CarouselPrevious />
<CarouselNext />
</CarouselControl>
<CarouselContent>
{slides.map((slide, index) => (
<CarouselItem index={index} key={slide}>
<Card>
<CardContent className="flex aspect-square items-center justify-center">
<span className="font-semibold text-4xl">{slide}</span>
</CardContent>
</Card>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
);Accessibility
| Key | Description |
|---|---|
Enter | Activate the focused control. |
Space | Activate the focused control. |
ArrowDown | Move to the next item. |
ArrowUp | Move to the previous item. |
ArrowRight | Move to the next item. |
ArrowLeft | Move to the previous item. |
Home | Go to the start. |
End | Go to the end. |
Demos
Autoplay
Controlled
Dynamic
Loop
Mouse Drag
Orientation Horizontal
Orientation Vertical
Pause On Hover
Root Provider
Scroll To
Slides Per Page
Spacing
Thumbnail Indicator
Thumbnail Indicator Vertical
Variable Size
API Reference
Carousel
div
PropType
AttributeType
CSS variableType
CarouselContent
div
PropType
AttributeType
CarouselItem
div
PropType
AttributeType
CarouselControl
div
PropType
AttributeType
CarouselNext
button
PropType
AttributeType
CarouselPrevious
button
PropType
AttributeType
CarouselIndicatorGroup
div
PropType
AttributeType
CarouselIndicator
button
PropType
AttributeType
CarouselAutoplayTrigger
button
PropType
AttributeType
CarouselProgressText
span
PropType
AttributeType
CarouselAutoplayIndicator
span
PropType
AttributeType
CarouselRootProvider
div
PropType
AttributeType
CSS variableType
CarouselContext
PropType