Carousel

Find the source code here.

Overview

Carousel is a good way to show multiple contents in one place by alterning between them via a navigation-like.

Best example is gallery photos from ecommerce product detail.

JSXPine's Carousel provide properties which will enabled you to deal with many customization cases. Here below are some examples of what you can achieved with this component:

With Indicators

By setting indicator props to true, dot points will appeared at the bottom of the carousel.

It displays the number of items the carousel contains.

These are indicator props value: true, top, bottom (default value when true), left, right.

Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10
Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10

Copied !

import { Carousel } from "$components/carousel.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: import("$components/image.component").ImageType[] }>}
 */
export function IndicatorsCarouselExample(props) {
	const { slides } = props;
	return (
		<div class="flex flex-col gap-y-6">
			<Carousel slides={slides} indicator />
			<Carousel slides={slides} indicator="top" />
		</div>
	);
}

Custom Slides

Default slot is for slides. Here is an example with our own image design.

Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10

Copied !

import { Carousel } from "$components/carousel.component";
import { Image } from "$components/image.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: import("$components/image.component").ImageType[] }>}
 */
export function CustomSlidesImageCarouselExample(props) {
	const { slides } = props;
	return (
		<Carousel loop>
			{slides.map((image) => (
				<Image src={image.src} alt={image.alt} />
			))}
		</Carousel>
	);
}

However, images are not the only slides you can put in carousel. Be aware that it's up to you to properly define your css class to have expected layout.

This is an example with just some section tag and dummy content inside as slides.

This is Slide 1

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Doloremque voluptatem aliquid nam, quaerat eligendi quasi iste sed, placeat consequuntur enim ad quis tenetur praesentium impedit! Suscipit cumque natus ipsam earum.

This is Slide 2

Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis, perspiciatis.

This is Slide 3

Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum aliquid vel eligendi minus nesciunt rerum illo beatae eos dolor. Esse voluptatem excepturi eligendi ab rem, nam possimus sed sequi quaerat corrupti consequuntur molestias sint rerum repudiandae explicabo est necessitatibus non autem vitae hic illo officiis obcaecati asperiores maxime. Facere, eum?

This is Slide 4

Lorem ipsum dolor sit amet consectetur adipisicing elit. Natus dolor dicta cumque nemo. Architecto quam odit obcaecati laboriosam sapiente inventore, dolorem iusto? Numquam velit sed minima culpa magni sapiente. Distinctio quas voluptatem sed dignissimos cumque heading sequi ratione consequatur at, dicta iste repellat non! Quam quod totam aperiam magni repellat dolorum dolore mollitia illo, fugit qui possimus voluptatibus! Maiores eveniet consectetur voluptates nostrum magni doloribus in, ea autem itaque nam maxime minus necessitatibus illum ad?

This is Slide 5

Lorem ipsum dolor sit, amet consectetur adipisicing elit. Veritatis magni, aperiam repellendus nisi itaque facere! Consequatur beatae voluptas reiciendis minus quidem inventore ea heading harum dicta obcaecati aut nam sunt ipsum odit dolore doloribus iure nemo quasi, officia asperiores. Vero?

Copied !

import { Carousel } from "$components/carousel.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: {color: string, text: string }[] }>}
 */
export function CustomSlidesCarouselExample(props) {
	const { slides } = props;
	return (
		<Carousel hideNavigations indicator>
			{slides.map((item, index) => (
				<div
					class={`min-w-full h-full flex flex-col gap-y-2 items-center p-2 md:p-6 ${item.color}`}
				>
					<h3>This is Slide {index + 1}</h3>
					<p class="text-sm flex items-start" safe>{item.text}</p>
				</div>
			))}
		</Carousel>
	);
}

Custom Navigations

Carousel allows you to customize navigations with slot which is named navigations.

You will be able to use all alpine features bound to default navigations such as previous(), next() functions and disability.

With this customization, you'll have to deal with icons based on direction yourself. Below are some examples.

Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10
Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10

Copied !

import { PrimaryButton, InfoButton } from "$components/button.component";
import { Carousel } from "$components/carousel.component";
import { Icon } from "$components/icon.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: import("$components/image.component").ImageType[] }>}
 */
export function CustomNavigationsCarouselExample(props) {
	const { slides } = props;
	return (
		<div class="flex flex-col gap-y-4">
			<Carousel
				slides={slides}
				navigations={
					<div>
						<PrimaryButton
							x-bind:disabled="!loop && areFirstSlidesToShow()"
							x-on:click="previous()"
							borderRadius="pill"
							class="absolute top-1/2 -translate-y-1/2 left-4"
						>
							<Icon
								name="arrow-left-line"
								size={6}
								fill="none"
								stroke="currentColor"
							/>
						</PrimaryButton>
						<PrimaryButton
							x-bind:disabled="!loop && areLastSlidesToShow()"
							x-on:click="next()"
							borderRadius="pill"
							class="absolute top-1/2 -translate-y-1/2 right-4"
						>
							<Icon
								name="arrow-right-line"
								size={6}
								fill="none"
								stroke="currentColor"
							/>
						</PrimaryButton>
					</div>
				}
				loop
			/>

			<Carousel
				slides={slides}
				direction="vertical"
				navigations={
					<div>
						<InfoButton
							x-bind:disabled="!loop && areFirstSlidesToShow"
							x-on:click="previous()"
							borderRadius="pill"
							class="absolute left-1/2 -translate-x-1/2 top-4"
						>
							<span>Previous</span>
						</InfoButton>
						<InfoButton
							x-bind:disabled="!loop && areLastSlidesToShow"
							x-on:click="next()"
							borderRadius="pill"
							class="absolute left-1/2 -translate-x-1/2 bottom-4"
						>
							<span>Next</span>
						</InfoButton>
					</div>
				}
			/>
		</div>
	);
}

Custom Indicators

Indicators can also be customize. Just set an html tag with slot name as indicators.

As reminder, you'll have to deal with indicators position based on direction yourself. Below an example with indicators as numbers.

Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10

Copied !

import { Carousel, CarouselIndicators } from "$components/carousel.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: import("$components/image.component").ImageType[] }>}
 */
export function DefaultCarouselExample(props) {
	const { slides } = props;
	return (
		<Carousel
			slides={slides}
			indicators={
				<CarouselIndicators>
					{slides.map((image, index) => (
						<li>
							<button
								x-on:click={`setActiveIndex(Number(${index}))`}
								x-bind:disabled={`isActive(Number(${index}))`}
								class="cursor-pointer p-2 bg-white text-slate-700 disabled:bg-slate-900 disabled:text-white disabled:cursor-not-allowed"
							>
								<span>{index + 1}</span>
							</button>
						</li>
					))}
				</CarouselIndicators>
			}
			loop
			indicator
		/>
	);
}

Multiple Slides

A great feature of carousel is to show multiple slides.

Just set a number to slidesToShow props as shown in examples below.

PS: For custom slides, it's up to you to manage slide sizes.

Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10

Copied !

import { Carousel } from "$components/carousel.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: import("$components/image.component").ImageType[] }>}
 */
export function MultipleSlidesWith2CarouselExample(props) {
	const { slides } = props;
	return <Carousel slides={slides} slidesToShow={2} />;
}
Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10

Copied !

import { InfoButton } from "$components/button.component";
import { Carousel } from "$components/carousel.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: import("$components/image.component").ImageType[] }>}
 */
export function MultipleSlidesWith3CarouselExample(props) {
	const { slides } = props;
	return (
		<Carousel
			slides={slides}
			slidesToShow={3}
			direction="vertical"
			indicator="left"
			navigations={
				<div>
					<InfoButton
						x-bind:disabled="!loop && areFirstSlidesToShow"
						x-on:click="previous()"
						borderRadius="pill"
						class="absolute left-1/2 -translate-x-1/2 top-4"
					>
						<span>Previous</span>
					</InfoButton>
					<InfoButton
						x-bind:disabled="!loop && areLastSlidesToShow"
						x-on:click="next()"
						borderRadius="pill"
						class="absolute left-1/2 -translate-x-1/2 bottom-4"
					>
						<span>Next</span>
					</InfoButton>
				</div>
			}
			loop
		/>
	);
}
Photo of MountainsPhoto of Mountains 02Photo of Mountains 03Photo of Mountains 04Photo of Mountains 05Photo of Mountains 06Photo of Mountains 07Photo of Mountains 08Photo of Mountains 09Photo of Mountains 10

Copied !

import { Carousel } from "$components/carousel.component";
import { Image } from "$components/image.component";

/**
 * @type {import("$common/props").JSXComponent<{ slides: import("$components/image.component").ImageType[] }>}
 */
export function MultipleCustomSlidesWith2CarouselExample(props) {
	const { slides } = props;
	return (
		<Carousel slidesToShow={3} loop>
			{slides.map((image) => (
				<Image class="w-1/3 h-full" src={image.src} alt={image.alt} />
			))}
		</Carousel>
	);
}