Acronis UIKit
Legacy (shadcn-uikit)Components

Carousel

A slideshow component for cycling through content.

Usage

import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselPrevious,
  CarouselNext,
} from '@acronis-platform/shadcn-uikit';

Basic

A simple carousel with navigation arrows.

1
2
3
4
5
View source
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';

export function CarouselBasic() {
  return (
    <Carousel className="w-full max-w-xs mx-auto">
      <CarouselContent>
        {Array.from({ length: 5 }).map((_, index) => (
          <CarouselItem key={index}>
            <div className="p-1">
              <Card>
                <CardContent className="flex aspect-square items-center justify-center p-6">
                  <span className="text-4xl font-semibold">{index + 1}</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

With dots

Carousel with dot indicators for pagination.

1
2
3
4
5
View source
import * as React from 'react';
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  type CarouselApi,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';
import { Button } from '@acronis-platform/shadcn-uikit/react';
import {
  ChevronLeftIcon,
  ChevronRightIcon,
} from '@acronis-platform/shadcn-uikit';
export function CarouselWithDots() {
  const [api, setApi] = React.useState<CarouselApi>();
  const [current, setCurrent] = React.useState(0);
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    if (!api) {
      return;
    }

    setCount(api.scrollSnapList().length);
    setCurrent(api.selectedScrollSnap() + 1);

    api.on('select', () => {
      setCurrent(api.selectedScrollSnap() + 1);
    });
  }, [api]);

  return (
    <div className="w-full max-w-xs mx-auto">
      <Carousel setApi={setApi}>
        <CarouselContent>
          {Array.from({ length: 5 }).map((_, index) => (
            <CarouselItem key={index}>
              <div className="p-1">
                <Card>
                  <CardContent className="flex aspect-square items-center justify-center p-6">
                    <span className="text-4xl font-semibold">{index + 1}</span>
                  </CardContent>
                </Card>
              </div>
            </CarouselItem>
          ))}
        </CarouselContent>
      </Carousel>
      <div className="flex items-center justify-center gap-4 mt-4">
        <Button
          variant="ghost"
          size="sm"
          onClick={() => api?.scrollPrev()}
          disabled={!api?.canScrollPrev()}
          className="text-[hsl(var(--carousel-nav-text))] disabled:text-[hsl(var(--carousel-nav-text-disabled)/0.3)]"
        >
          <ChevronLeftIcon className="h-4 w-4 mr-1" />
          Prev
        </Button>
        <div className="flex gap-2">
          {Array.from({ length: count }).map((_, index) => (
            <button
              key={index}
              onClick={() => api?.scrollTo(index)}
              className={`h-2 rounded-full transition-all ${
                index + 1 === current
                  ? 'w-2 bg-[hsl(var(--carousel-dot-active))]'
                  : 'w-2 bg-[hsl(var(--carousel-dot)/0.3)]'
              }`}
              aria-label={`Go to slide ${index + 1}`}
            />
          ))}
        </div>
        <Button
          variant="ghost"
          size="sm"
          onClick={() => api?.scrollNext()}
          disabled={!api?.canScrollNext()}
          className="text-[hsl(var(--carousel-nav-text))] disabled:text-[hsl(var(--carousel-nav-text-disabled)/0.3)]"
        >
          Next
          <ChevronRightIcon className="h-4 w-4 ml-1" />
        </Button>
      </div>
    </div>
  );
}

Multiple items

Show multiple items per slide.

1
2
3
4
5
6
7
8
9
10
View source
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';

export function CarouselMultiple() {
  return (
    <Carousel
      opts={{
        align: 'start',
      }}
      className="w-full max-w-2xl mx-auto"
    >
      <CarouselContent>
        {Array.from({ length: 10 }).map((_, index) => (
          <CarouselItem key={index} className="md:basis-1/2 lg:basis-1/3">
            <div className="p-1">
              <Card>
                <CardContent className="flex aspect-square items-center justify-center p-6">
                  <span className="text-3xl font-semibold">{index + 1}</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

A photo gallery carousel.

🖼️

Image 1

🖼️

Image 2

🖼️

Image 3

🖼️

Image 4

🖼️

Image 5

View source
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';

export function CarouselImageGallery() {
  return (
    <Carousel className="w-full max-w-lg mx-auto">
      <CarouselContent>
        {Array.from({ length: 5 }).map((_, index) => (
          <CarouselItem key={index}>
            <div className="p-1">
              <Card>
                <CardContent className="flex aspect-video items-center justify-center p-6 bg-gradient-to-br from-blue-100 to-blue-200">
                  <div className="text-center">
                    <div className="text-6xl mb-2">🖼️</div>
                    <p className="text-sm text-gray-600">Image {index + 1}</p>
                  </div>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

Testimonials

A testimonial slider carousel.

"This product has completely transformed how we work!"

John Doe

CEO, Company A

"Outstanding support and amazing features."

Jane Smith

CTO, Company B

"Best investment we made this year."

Bob Johnson

Manager, Company C

View source
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';

export function CarouselTestimonials() {
  return (
    <Carousel className="w-full max-w-xl mx-auto">
      <CarouselContent>
        {[
          {
            quote: 'This product has completely transformed how we work!',
            author: 'John Doe',
            role: 'CEO, Company A',
          },
          {
            quote: 'Outstanding support and amazing features.',
            author: 'Jane Smith',
            role: 'CTO, Company B',
          },
          {
            quote: 'Best investment we made this year.',
            author: 'Bob Johnson',
            role: 'Manager, Company C',
          },
        ].map((testimonial, index) => (
          <CarouselItem key={index}>
            <div className="p-1">
              <Card>
                <CardContent className="flex flex-col items-center justify-center p-8 text-center min-h-[200px]">
                  <p className="text-lg italic mb-4">
                    &quot;{testimonial.quote}&quot;
                  </p>
                  <div>
                    <p className="font-semibold">{testimonial.author}</p>
                    <p className="text-sm text-gray-600">{testimonial.role}</p>
                  </div>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

Products

A product showcase carousel.

💻

Product 1

$99

📱

Product 2

$149

Product 3

$199

🎧

Product 4

$299

View source
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';
import { Button } from '@acronis-platform/shadcn-uikit/react';

export function CarouselProducts() {
  return (
    <Carousel className="w-full max-w-md mx-auto">
      <CarouselContent>
        {[
          { name: 'Product 1', price: '$99', emoji: '💻' },
          { name: 'Product 2', price: '$149', emoji: '📱' },
          { name: 'Product 3', price: '$199', emoji: '⌚' },
          { name: 'Product 4', price: '$299', emoji: '🎧' },
        ].map((product, index) => (
          <CarouselItem key={index}>
            <div className="p-1">
              <Card>
                <CardContent className="flex flex-col items-center justify-center p-8">
                  <div className="text-6xl mb-4">{product.emoji}</div>
                  <h4 className="text-xl font-semibold mb-2">{product.name}</h4>
                  <p className="text-2xl font-bold text-primary mb-4">
                    {product.price}
                  </p>
                  <Button className="w-full">Add to Cart</Button>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

Vertical

A vertically scrolling carousel.

1
2
3
4
5
View source
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';

export function CarouselVertical() {
  return (
    <Carousel
      opts={{
        align: 'start',
      }}
      orientation="vertical"
      className="w-full max-w-xs mx-auto"
    >
      <CarouselContent className="h-[400px]">
        {Array.from({ length: 5 }).map((_, index) => (
          <CarouselItem key={index} className="pt-1 md:basis-1/2">
            <div className="p-1">
              <Card>
                <CardContent className="flex items-center justify-center p-6">
                  <span className="text-3xl font-semibold">{index + 1}</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

Autoplay

Carousel with automatic slide progression.

1
2
3
4
5
View source
import * as React from 'react';
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
  type CarouselApi,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';

export function CarouselAutoplay() {
  const [api, setApi] = React.useState<CarouselApi>();

  React.useEffect(() => {
    if (!api) {
      return;
    }

    const interval = setInterval(() => {
      if (api.canScrollNext()) {
        api.scrollNext();
      } else {
        api.scrollTo(0);
      }
    }, 3000);

    return () => clearInterval(interval);
  }, [api]);

  return (
    <Carousel setApi={setApi} className="w-full max-w-xs mx-auto">
      <CarouselContent>
        {Array.from({ length: 5 }).map((_, index) => (
          <CarouselItem key={index}>
            <div className="p-1">
              <Card>
                <CardContent className="flex aspect-square items-center justify-center p-6 bg-gradient-to-br from-purple-100 to-pink-100">
                  <span className="text-4xl font-semibold">{index + 1}</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

Figma style

A carousel styled to match Figma design specifications.

📄

Step 1

📄

Step 2

📄

Step 3

📄

Step 4

📄

Step 5

View source
import * as React from 'react';
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  type CarouselApi,
} from '@acronis-platform/shadcn-uikit/react';
import { Card, CardContent } from '@acronis-platform/shadcn-uikit/react';
import { Button } from '@acronis-platform/shadcn-uikit/react';
import {
  ChevronLeftIcon,
  ChevronRightIcon,
} from '@acronis-platform/shadcn-uikit';
export function CarouselFigmaStyle() {
  const [api, setApi] = React.useState<CarouselApi>();
  const [current, setCurrent] = React.useState(0);
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    if (!api) {
      return;
    }

    setCount(api.scrollSnapList().length);
    setCurrent(api.selectedScrollSnap());

    api.on('select', () => {
      setCurrent(api.selectedScrollSnap());
    });
  }, [api]);

  const isFirst = current === 0;
  const isLast = current === count - 1;

  return (
    <div className="w-full max-w-sm mx-auto space-y-4">
      <Carousel setApi={setApi}>
        <CarouselContent>
          {Array.from({ length: 5 }).map((_, index) => (
            <CarouselItem key={index}>
              <Card>
                <CardContent className="flex aspect-video items-center justify-center p-6">
                  <div className="text-center">
                    <div className="text-5xl mb-2">📄</div>
                    <p className="text-sm text-gray-600">Step {index + 1}</p>
                  </div>
                </CardContent>
              </Card>
            </CarouselItem>
          ))}
        </CarouselContent>
      </Carousel>

      <div className="flex items-center justify-between">
        <button
          onClick={() => api?.scrollPrev()}
          disabled={isFirst}
          className={`text-sm font-semibold py-1 transition-colors ${
            isFirst
              ? 'text-[hsl(var(--carousel-nav-text-disabled)/0.3)] cursor-not-allowed'
              : 'text-[hsl(var(--carousel-nav-text))] hover:opacity-80'
          }`}
        >
          <ChevronLeftIcon className="inline h-4 w-4" /> Prev
        </button>

        <div className="flex gap-2">
          {Array.from({ length: count }).map((_, index) => (
            <button
              key={index}
              onClick={() => api?.scrollTo(index)}
              className={`h-2 w-2 rounded-full transition-all ${
                index === current
                  ? 'bg-[hsl(var(--carousel-dot-active))]'
                  : 'bg-[hsl(var(--carousel-dot)/0.3)]'
              }`}
              aria-label={`Go to slide ${index + 1}`}
            />
          ))}
        </div>

        <button
          onClick={() => api?.scrollNext()}
          disabled={isLast}
          className={`text-sm font-semibold py-1 transition-colors ${
            isLast
              ? 'text-[hsl(var(--carousel-nav-text-disabled)/0.3)] cursor-not-allowed'
              : 'text-[hsl(var(--carousel-nav-text))] hover:opacity-80'
          }`}
        >
          Next <ChevronRightIcon className="inline h-4 w-4" />
        </button>
      </div>

      {isLast && (
        <div className="space-y-2">
          <Button className="w-full bg-[hsl(var(--carousel-button-bg))] text-[hsl(var(--carousel-button-text))] hover:opacity-90">
            Protect devices
          </Button>
          <Button
            variant="ghost"
            className="w-full text-[hsl(var(--carousel-nav-text))]"
          >
            Go back
          </Button>
        </div>
      )}
    </div>
  );
}

API Reference

Prop

Type

The Carousel component also accepts all standard HTML div attributes. Sub-components CarouselContent, CarouselItem, CarouselPrevious, and CarouselNext extend their native element props.

Edit on GitHub

On this page