ZaidanHomeDocsComponentsBlocksChartsTypesetCreate

Command Palette

Search for a command to run...

GitHub
New
Sections
  • Introduction
  • Components
  • Blocks
  • Installation
  • Customization
  • Dark Mode
  • Typeset
  • Zaidan Skills
  • FAQ
  • Roadmap
  • Changelog
Installation
  • Astro
  • Manual
  • Solid Start
  • TanStack Router
  • TanStack Start
  • Vite
Blocks
  • Data Grid
  • Event Calendar
  • Filters
  • Gantt
  • Image Crop
  • Kanban
  • Message Scroller
  • Questionnaire
  • Sortable
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Attachment
  • Avatar
  • Badge
  • Breadcrumb
  • Bubble
  • Button
  • Button Group
  • Calendar
  • Card
  • Carousel
  • Chart
  • Checkbox
  • Collapsible
  • Combobox
  • Command
  • Context Menu
  • Dialog
  • Drawer
  • Dropdown Menu
  • Empty
  • Field
  • Hover Card
  • Input
  • Input Group
  • Input OTP
  • Item
  • Kbd
  • Label
  • Marker
  • Menubar
  • Message
  • Native Select
  • Navigation Menu
  • Pagination
  • Popover
  • Progress
  • Radio Group
  • Resizable
  • Scroll Area
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Skeleton
  • Slider
  • Spinner
  • Switch
  • Table
  • Tabs
  • Textarea
  • Toast
  • Toggle
  • Toggle Group
  • Tooltip

Carousel

A carousel with motion and swipe built using Embla.

1
2
3
4
5
1
import { For } from "solid-js";
2
3
import { Card, CardContent } from "~/components/ui/card";
4
import {
5
Carousel,
6
CarouselContent,
7
CarouselItem,
8
CarouselNext,
9
CarouselPrevious,
10
} from "~/components/ui/carousel";
11
12
export default function CarouselDemo() {
13
return (
14
<Carousel aria-label="Carousel demo" class="w-full max-w-[12rem] sm:max-w-xs">
15
<CarouselContent>
16
<For each={Array.from({ length: 5 })}>
17
{(_, index) => (
18
<CarouselItem>
19
<div class="p-1">
20
<Card>
21
<CardContent class="flex aspect-square items-center justify-center p-6">
22
<span class="text-4xl font-semibold">{index() + 1}</span>
23
</CardContent>
24
</Card>
25
</div>
26
</CarouselItem>
27
)}
28
</For>
29
</CarouselContent>
30
<CarouselPrevious />
31
<CarouselNext />
32
</Carousel>
33
);
34
}

About

The Carousel component is built with Embla Carousel, which provides motion, swipe, and keyboard navigation.

Installation

pnpm dlx shadcn@latest add @zaidan/carousel
npx shadcn@latest add @zaidan/carousel
yarn dlx shadcn@latest add @zaidan/carousel
bunx --bun shadcn@latest add @zaidan/carousel

Usage

1
import {
2
Carousel,
3
CarouselContent,
4
CarouselItem,
5
CarouselNext,
6
CarouselPrevious,
7
} from "~/components/ui/carousel";
1
<Carousel>
2
<CarouselContent>
3
<CarouselItem>...</CarouselItem>
4
<CarouselItem>...</CarouselItem>
5
<CarouselItem>...</CarouselItem>
6
</CarouselContent>
7
<CarouselPrevious />
8
<CarouselNext />
9
</Carousel>

Composition

Use the following composition to build a Carousel:

Carousel
├── CarouselContent
│ ├── CarouselItem
│ └── CarouselItem
├── CarouselPrevious
└── CarouselNext

Sizes

To set the size of the items, use the basis utility class on <CarouselItem />.

1
2
3
4
5
1
import { For } from "solid-js";
2
3
import { Card, CardContent } from "~/components/ui/card";
4
import {
5
Carousel,
6
CarouselContent,
7
CarouselItem,
8
CarouselNext,
9
CarouselPrevious,
10
} from "~/components/ui/carousel";
11
12
export default function CarouselSize() {
13
return (
14
<Carousel
15
aria-label="Carousel size example"
16
opts={{ align: "start" }}
17
class="w-full max-w-[12rem] sm:max-w-xs md:max-w-sm"
18
>
19
<CarouselContent>
20
<For each={Array.from({ length: 5 })}>
21
{(_, index) => (
22
<CarouselItem class="basis-1/2 lg:basis-1/3">
23
<div class="p-1">
24
<Card>
25
<CardContent class="flex aspect-square items-center justify-center p-6">
26
<span class="text-3xl font-semibold">{index() + 1}</span>
27
</CardContent>
28
</Card>
29
</div>
30
</CarouselItem>
31
)}
32
</For>
33
</CarouselContent>
34
<CarouselPrevious />
35
<CarouselNext />
36
</Carousel>
37
);
38
}
1
// 33% of the carousel width.
2
<Carousel>
3
<CarouselContent>
4
<CarouselItem class="basis-1/3">...</CarouselItem>
5
<CarouselItem class="basis-1/3">...</CarouselItem>
6
<CarouselItem class="basis-1/3">...</CarouselItem>
7
</CarouselContent>
8
</Carousel>
1
// 50% on small screens and 33% on larger screens.
2
<Carousel>
3
<CarouselContent>
4
<CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
5
<CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
6
<CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
7
</CarouselContent>
8
</Carousel>

Spacing

To set item spacing, use a pl-[VALUE] utility on <CarouselItem /> and a negative -ml-[VALUE] on <CarouselContent />.

1
2
3
4
5
1
import { For } from "solid-js";
2
3
import { Card, CardContent } from "~/components/ui/card";
4
import {
5
Carousel,
6
CarouselContent,
7
CarouselItem,
8
CarouselNext,
9
CarouselPrevious,
10
} from "~/components/ui/carousel";
11
12
export default function CarouselSpacing() {
13
return (
14
<Carousel
15
aria-label="Carousel spacing example"
16
class="w-full max-w-[12rem] sm:max-w-xs md:max-w-sm"
17
>
18
<CarouselContent class="-ml-1">
19
<For each={Array.from({ length: 5 })}>
20
{(_, index) => (
21
<CarouselItem class="basis-1/2 pl-1 lg:basis-1/3">
22
<div class="p-1">
23
<Card>
24
<CardContent class="flex aspect-square items-center justify-center p-6">
25
<span class="text-2xl font-semibold">{index() + 1}</span>
26
</CardContent>
27
</Card>
28
</div>
29
</CarouselItem>
30
)}
31
</For>
32
</CarouselContent>
33
<CarouselPrevious />
34
<CarouselNext />
35
</Carousel>
36
);
37
}
1
<Carousel>
2
<CarouselContent class="-ml-4">
3
<CarouselItem class="pl-4">...</CarouselItem>
4
<CarouselItem class="pl-4">...</CarouselItem>
5
<CarouselItem class="pl-4">...</CarouselItem>
6
</CarouselContent>
7
</Carousel>
1
<Carousel>
2
<CarouselContent class="-ml-2 md:-ml-4">
3
<CarouselItem class="pl-2 md:pl-4">...</CarouselItem>
4
<CarouselItem class="pl-2 md:pl-4">...</CarouselItem>
5
<CarouselItem class="pl-2 md:pl-4">...</CarouselItem>
6
</CarouselContent>
7
</Carousel>

Orientation

Use the orientation prop to set the carousel orientation.

1
2
3
4
5
1
import { For } from "solid-js";
2
3
import { Card, CardContent } from "~/components/ui/card";
4
import {
5
Carousel,
6
CarouselContent,
7
CarouselItem,
8
CarouselNext,
9
CarouselPrevious,
10
} from "~/components/ui/carousel";
11
12
export default function CarouselOrientation() {
13
return (
14
<Carousel
15
aria-label="Vertical carousel example"
16
opts={{ align: "start" }}
17
orientation="vertical"
18
class="w-full max-w-xs"
19
>
20
<CarouselContent class="-mt-1 h-[270px]">
21
<For each={Array.from({ length: 5 })}>
22
{(_, index) => (
23
<CarouselItem class="basis-1/2 pt-1">
24
<div class="p-1">
25
<Card>
26
<CardContent class="flex items-center justify-center p-6">
27
<span class="text-3xl font-semibold">{index() + 1}</span>
28
</CardContent>
29
</Card>
30
</div>
31
</CarouselItem>
32
)}
33
</For>
34
</CarouselContent>
35
<CarouselPrevious />
36
<CarouselNext />
37
</Carousel>
38
);
39
}
1
<Carousel orientation="vertical | horizontal">
2
<CarouselContent>
3
<CarouselItem>...</CarouselItem>
4
<CarouselItem>...</CarouselItem>
5
<CarouselItem>...</CarouselItem>
6
</CarouselContent>
7
</Carousel>

Options

Pass options to the carousel using the opts prop. See the Embla Carousel options documentation for more information.

1
<Carousel
2
opts={{
3
align: "start",
4
loop: true,
5
}}
6
>
7
<CarouselContent>
8
<CarouselItem>...</CarouselItem>
9
<CarouselItem>...</CarouselItem>
10
<CarouselItem>...</CarouselItem>
11
</CarouselContent>
12
</Carousel>

API

Use a signal and the setApi prop to get an instance of the carousel API.

1
2
3
4
5
Slide 0 of 0
1
import { createEffect, createSignal, For, onCleanup } from "solid-js";
2
3
import { Card, CardContent } from "~/components/ui/card";
4
import {
5
Carousel,
6
type CarouselApi,
7
CarouselContent,
8
CarouselItem,
9
CarouselNext,
10
CarouselPrevious,
11
} from "~/components/ui/carousel";
12
13
export default function CarouselApiDemo() {
14
const [api, setApi] = createSignal<CarouselApi>();
15
const [current, setCurrent] = createSignal(0);
16
const [count, setCount] = createSignal(0);
17
18
createEffect(() => {
19
const carouselApi = api();
20
if (!carouselApi) return;
21
22
const onSelect = () => setCurrent(carouselApi.selectedScrollSnap() + 1);
23
24
setCount(carouselApi.scrollSnapList().length);
25
onSelect();
26
carouselApi.on("select", onSelect);
27
onCleanup(() => carouselApi.off("select", onSelect));
28
});
29
30
return (
31
<div class="mx-auto max-w-[10rem] sm:max-w-xs">
32
<Carousel aria-label="Carousel API example" setApi={setApi} class="w-full max-w-xs">
33
<CarouselContent>
34
<For each={Array.from({ length: 5 })}>
35
{(_, index) => (
36
<CarouselItem>
37
<Card class="m-px">
38
<CardContent class="flex aspect-square items-center justify-center p-6">
39
<span class="text-4xl font-semibold">{index() + 1}</span>
40
</CardContent>
41
</Card>
42
</CarouselItem>
43
)}
44
</For>
45
</CarouselContent>
46
<CarouselPrevious />
47
<CarouselNext />
48
</Carousel>
49
<div class="py-2 text-center text-sm text-muted-foreground">
50
Slide {current()} of {count()}
51
</div>
52
</div>
53
);
54
}
1
import { createEffect, createSignal, onCleanup } from "solid-js";
2
import { type CarouselApi } from "~/components/ui/carousel";
3
4
export function Example() {
5
const [api, setApi] = createSignal<CarouselApi>();
6
const [current, setCurrent] = createSignal(0);
7
const [count, setCount] = createSignal(0);
8
9
createEffect(() => {
10
const carouselApi = api();
11
if (!carouselApi) return;
12
13
const onSelect = () => {
14
setCurrent(carouselApi.selectedScrollSnap() + 1);
15
};
16
17
setCount(carouselApi.scrollSnapList().length);
18
onSelect();
19
carouselApi.on("select", onSelect);
20
onCleanup(() => carouselApi.off("select", onSelect));
21
});
22
23
return (
24
<Carousel setApi={setApi}>
25
<CarouselContent>
26
<CarouselItem>...</CarouselItem>
27
<CarouselItem>...</CarouselItem>
28
<CarouselItem>...</CarouselItem>
29
</CarouselContent>
30
</Carousel>
31
);
32
}

Events

Listen to events using the API instance from setApi.

1
import { createEffect, createSignal, onCleanup } from "solid-js";
2
import { type CarouselApi } from "~/components/ui/carousel";
3
4
export function Example() {
5
const [api, setApi] = createSignal<CarouselApi>();
6
7
createEffect(() => {
8
const carouselApi = api();
9
if (!carouselApi) return;
10
11
const onSelect = () => {
12
// Do something on select.
13
};
14
15
carouselApi.on("select", onSelect);
16
onCleanup(() => carouselApi.off("select", onSelect));
17
});
18
19
return (
20
<Carousel setApi={setApi}>
21
<CarouselContent>
22
<CarouselItem>...</CarouselItem>
23
<CarouselItem>...</CarouselItem>
24
<CarouselItem>...</CarouselItem>
25
</CarouselContent>
26
</Carousel>
27
);
28
}

See the Embla Carousel events documentation for more information.

Plugins

Use the plugins prop to add plugins to the carousel.

1
import Autoplay from "embla-carousel-autoplay";
2
3
export function Example() {
4
return (
5
<Carousel
6
plugins={[
7
Autoplay({
8
delay: 2000,
9
}),
10
]}
11
>
12
// ...
13
</Carousel>
14
);
15
}
1
2
3
4
5
1
import Autoplay from "embla-carousel-autoplay";
2
import { For } from "solid-js";
3
4
import { Card, CardContent } from "~/components/ui/card";
5
import {
6
Carousel,
7
CarouselContent,
8
CarouselItem,
9
CarouselNext,
10
CarouselPrevious,
11
} from "~/components/ui/carousel";
12
13
export default function CarouselPlugin() {
14
const plugin = Autoplay({ delay: 2000, stopOnInteraction: true });
15
16
return (
17
<Carousel
18
aria-label="Carousel autoplay example"
19
plugins={[plugin]}
20
class="w-full max-w-[10rem] sm:max-w-xs"
21
onMouseEnter={plugin.stop}
22
onMouseLeave={plugin.reset}
23
>
24
<CarouselContent>
25
<For each={Array.from({ length: 5 })}>
26
{(_, index) => (
27
<CarouselItem>
28
<div class="p-1">
29
<Card>
30
<CardContent class="flex aspect-square items-center justify-center p-6">
31
<span class="text-4xl font-semibold">{index() + 1}</span>
32
</CardContent>
33
</Card>
34
</div>
35
</CarouselItem>
36
)}
37
</For>
38
</CarouselContent>
39
<CarouselPrevious />
40
<CarouselNext />
41
</Carousel>
42
);
43
}

API Reference

See the Embla Carousel API reference for information on options, events, and plugins.

On This Page

  • About
  • Installation
  • Usage
  • Composition
  • Sizes
  • Spacing
  • Orientation
  • Options
  • API
  • Events
  • Plugins
  • API Reference
Built by Kevin Abatan. The source code is available on GitHub.