diff --git a/docs/components/carousel.md b/docs/components/carousel.md
index d8a2c2f5..24041d1f 100644
--- a/docs/components/carousel.md
+++ b/docs/components/carousel.md
@@ -97,6 +97,166 @@ Carousels consist of optional navigation arrows to go backwards and forwards, as
```
+```jsx react
+import { useReducer } from 'react';
+import {
+ SlCarousel,
+ SlCarouselItem,
+ SlSwitch,
+ SlInput,
+ SlSelect,
+ SlMenuItem
+} from '@shoelace-style/shoelace/dist/react';
+
+const css = `
+ sl-carousel {
+ --aspect-ratio: 3 / 2;
+ }
+
+ .carousel-options {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: end;
+ gap: 1rem;
+ }
+`;
+
+const App = () => {
+ const [state, updateState] = useReducer(
+ (state, event) => {
+ console.log(event);
+ },
+ {
+ loop: true,
+ pagination: true,
+ navigation: true,
+ autoplay: true,
+ mouseDragging: true,
+ slidesPerPage: 1,
+ slidesPerMove: 1,
+ orientation: 'horizontal'
+ }
+ );
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loop
+
+
+ Show navigation
+
+
+ Show pagination
+
+
+ Autoplay (3s)
+
+
+ Mouse dragging
+
+
+
+
+
+
+ Horizontal
+ Vertical
+
+
+
+
+ >
+ );
+};
+```
+
+
+
## Examples
### Multiple slides per view
@@ -116,6 +276,21 @@ This can be done by using the `slides-per-move` attribute.
```
+```jsx react
+import { SlCarousel, SlCarouselItem } from '@shoelace-style/shoelace/dist/react';
+
+const App = () => (
+
+ Slide 1
+ Slide 2
+ Slide 3
+ Slide 4
+ Slide 5
+ Slide 6
+
+);
+```
+
### Adding/removing slides
The content of the carousel can be changed by either appending or removing items, the carousel will update itself automatically.
@@ -174,6 +349,57 @@ The content of the carousel can be changed by either appending or removing items
```
+```jsx react
+import { useState } from 'react';
+import { SlCarousel, SlCarouselItem } from '@shoelace-style/shoelace/dist/react';
+
+const css = `
+ .dynamic-carousel {
+ --aspect-ratio: 3 / 2;
+ }
+
+ .dynamic-carousel sl-carousel-item {
+ flex: 0 0 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: white;
+ font-size: var(--sl-font-size-2x-large);
+ }
+`;
+
+const App = () => {
+ const [slides, setSlides] = useState(['#204ed8', '#be133d', '#6e28d9']);
+
+ const rnd = (min, max) => Math.round(Math.random() * (max - min)) + min;
+ const getRandomColor = () => `rgb(${rnd(50, 150)}, ${rnd(50, 150)}, ${rnd(50, 150)})`;
+
+ const addSlide = () => {
+ setSlides([...slides, getRandomColor()]);
+ };
+
+ const removeSlide = () => {
+ setSlides(slides.slice(0, -1));
+ };
+
+ return (
+ <>
+
+ {slides.map((color, i) => (
+ Slide {i}
+ ))}
+
+
+
+ Add slide
+ Remove slide
+
+
+ >
+ );
+};
+```
+
### Vertical scrolling
Setting the `orientation` attribute to `vertical`, will make the carousel laying out vertically, making it
@@ -233,6 +459,67 @@ it's important to specify a predefined height to the carousel through CSS.
```
+```jsx react
+import { SlCarousel, SlCarouselItem } from '@shoelace-style/shoelace/dist/react';
+
+const css = `
+ .vertical {
+ max-height: 400px;
+ }
+
+ .vertical::part(base) {
+ grid-template-areas: 'slides slides pagination';
+ }
+
+ .vertical::part(pagination) {
+ flex-direction: column;
+ }
+
+ .vertical::part(navigation) {
+ transform: rotate(90deg);
+ display: flex;
+ }
+`;
+
+const App = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+```
+
### Aspect ratio
Use the `--aspect-ratio` custom property to customize the size of viewport in order to make it match a particular aspect ratio.
@@ -290,6 +577,67 @@ Use the `--aspect-ratio` custom property to customize the size of viewport in or
```
+```jsx react
+import { useState } from 'react';
+import { SlCarousel, SlCarouselItem, SlDivider, SlSelect, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
+
+const App = () => {
+ const [aspectRatio, setAspectRatio] = useState('3/2');
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setAspectRatio(event.target.value)}
+ >
+ 1 / 1
+ 3 / 2
+ 16 / 9
+
+
+
+ >
+ );
+};
+```
+
### Scroll hint
Use `--scroll-padding` to add inline padding in horizontal carousels and block padding in vertical carousels.
@@ -345,6 +693,68 @@ be scrolled.
```
+```jsx react
+import { useState } from 'react';
+import { SlCarousel, SlCarouselItem, SlDivider, SlRange } from '@shoelace-style/shoelace/dist/react';
+
+const App = () => {
+ const [scrollPadding, setScrollPadding] = useState(10);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setScrollPadding(event.target.valueAsNumber)}
+ />
+
+ >
+ );
+};
+```
+
### Custom layout
The appereance of the carousel can be easly customized through its slots or `part` attributes.
@@ -431,6 +841,95 @@ The appereance of the carousel can be easly customized through its slots or `par
```
+```jsx react
+import { SlCarousel, SlCarouselItem } from '@shoelace-style/shoelace/dist/react';
+
+const css = `
+ .custom-layout::part(base) {
+ grid-template-areas:
+ 'slides slides slides'
+ 'slides slides slides';
+ }
+
+ .custom-layout::part(pagination) {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ padding: var(--sl-spacing-large);
+ background: linear-gradient(0deg, rgba(0, 0, 0, 0.8) 5%, rgba(0, 0, 0, 0.2) 75%, rgba(0, 0, 0, 0) 100%);
+ }
+
+ .custom-layout::part(pagination-item) {
+ height: 5px;
+ width: var(--sl-spacing-large);
+ border-radius: var(--sl-border-radius-pill);
+ background-color: #fff;
+ }
+
+ .custom-layout::part(pagination-item--active) {
+ background-color: var(--sl-color-primary-400);
+ width: var(--sl-spacing-x-large);
+ }
+
+ .custom-layout::part(navigation-button) {
+ margin: var(--sl-spacing-large);
+ border-radius: var(--sl-border-radius-circle);
+ font-weight: var(--sl-font-weight-bold);
+ color: var(--sl-color-neutral-1000);
+ background: var(--sl-color-neutral-0);
+ opacity: 0.6;
+ transition: var(--sl-transition-medium) opacity;
+ }
+
+ .custom-layout::part(navigation-button):focus,
+ .custom-layout::part(navigation-button):hover {
+ opacity: 1;
+ }
+`;
+
+const App = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+```
+
### Gallery example
The carousel has a set of API with which is possible to interact programmatically, for example it is possible to
@@ -483,36 +982,21 @@ Using the API is possible to extend the carousel, for exmaple by syncing the act
@@ -587,4 +1071,124 @@ Using the API is possible to extend the carousel, for exmaple by syncing the act
```
+```jsx react
+import { useRef } from 'react';
+import { SlCarousel, SlCarouselItem, SlDivider, SlRange } from '@shoelace-style/shoelace/dist/react';
+
+const css = `
+ .carousel-thumbnails {
+ --slide-aspect-ratio: 3 / 2;
+ }
+
+ .thumbnails {
+ display: flex;
+ justify-content: center;
+ }
+
+ .thumbnails__scroller {
+ display: flex;
+ gap: var(--sl-spacing-small);
+ overflow-x: auto;
+ scrollbar-width: none;
+ scroll-behavior: smooth;
+ scroll-padding: var(--sl-spacing-small);
+ }
+
+ .thumbnails__scroller::-webkit-scrollbar {
+ display: none;
+ }
+
+ .thumbnails__image {
+ width: 64px;
+ height: 64px;
+ object-fit: cover;
+
+ opacity: 0.3;
+ will-change: opacity;
+ transition: 250ms opacity;
+
+ cursor: pointer;
+ }
+
+ .thumbnails__image.active {
+ opacity: 1;
+ }
+`;
+
+const images = [
+ {
+ src: '/assets/examples/carousel/adam-kool-ndN00KmbJ1c-unsplash.jpg',
+ alt: 'The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash'
+ },
+ {
+ src: '/assets/examples/carousel/thomas-kelley-JoH60FhTp50-unsplash.jpg',
+ alt: 'A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash'
+ },
+ {
+ src: '/assets/examples/carousel/leonard-cotte-c1Jp-fo53U8-unsplash.jpg',
+ alt: 'The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash'
+ },
+ {
+ src: '/assets/examples/carousel/sapan-patel-i9Q9bc-WgfE-unsplash.jpg',
+ alt: 'A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash'
+ },
+ {
+ src: '/assets/examples/carousel/v2osk-1Z2niiBPg5A-unsplash.jpg',
+ alt: 'A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash'
+ }
+];
+
+const App = () => {
+ const carouselRef = useRef();
+ const thumbnailsRef = useRef();
+ const [currentSlide, setCurrentSlide] = useState(0);
+
+ useEffect(() => {
+ const thumbnails = Array.from(thumbnailsRef.current.querySelectorAll('.thumbnails__image'));
+
+ thumbnails[currentSlide]..scrollIntoView({
+ block: 'nearest'
+ });
+ }, [currentSlide]);
+
+ const handleThumbnailClick = (index) => {
+ carouselRef.current.goToSlide(index);
+ }
+
+ const handleSlideChange = (event) => {
+ const slideIndex = e.detail.index;
+ setCurrentSlide(slideIndex);
+ }
+
+ return (
+ <>
+
+ {images.map({ src, alt }) => (
+
+
+
+ )}
+
+
+
+
+ >
+ );
+};
+```
+
[component-metadata:sl-carousel]