kopia lustrzana https://github.com/shoelace-style/shoelace
wip; improve carousel docs
rodzic
a526e8a956
commit
c69db4919b
|
@ -2,10 +2,8 @@
|
||||||
|
|
||||||
[component-header:sl-carousel]
|
[component-header:sl-carousel]
|
||||||
|
|
||||||
Carousels consist of optional navigation arrows to go backwards and forwards, as well as optional pagination indicators.
|
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
<sl-carousel loop pagination navigation autoplay mouse-dragging>
|
<sl-carousel pagination navigation mouse-dragging loop>
|
||||||
<sl-carousel-item>
|
<sl-carousel-item>
|
||||||
<img
|
<img
|
||||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
@ -37,242 +35,276 @@ Carousels consist of optional navigation arrows to go backwards and forwards, as
|
||||||
/>
|
/>
|
||||||
</sl-carousel-item>
|
</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
<sl-divider></sl-divider>
|
|
||||||
<div class="carousel-options">
|
|
||||||
<div class="carousel-options">
|
|
||||||
<sl-switch checked name="loop"> Loop </sl-switch>
|
|
||||||
<sl-switch checked name="navigation"> Show navigation </sl-switch>
|
|
||||||
<sl-switch checked name="pagination"> Show pagination </sl-switch>
|
|
||||||
<sl-switch checked name="autoplay"> Autoplay (3s) </sl-switch>
|
|
||||||
<sl-switch checked name="mouseDragging"> Mouse dragging </sl-switch>
|
|
||||||
</div>
|
|
||||||
<div class="carousel-options">
|
|
||||||
<sl-input type="number" label="Slides per page" name="slidesPerPage" value="1"></sl-input>
|
|
||||||
<sl-input type="number" label="Slides per move" name="slidesPerMove" value="1"></sl-input>
|
|
||||||
<sl-select label="Orientation" name="orientation" value="horizontal">
|
|
||||||
<sl-menu-item value="horizontal">Horizontal</sl-menu-item>
|
|
||||||
<sl-menu-item value="vertical">Vertical</sl-menu-item>
|
|
||||||
</sl-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
sl-carousel {
|
|
||||||
--aspect-ratio: 3 / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-options {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: end;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
(() => {
|
|
||||||
const options = document.querySelector('.carousel-options');
|
|
||||||
const carousel = document.querySelector('sl-carousel');
|
|
||||||
const loop = options.querySelector('sl-switch[name="loop"]');
|
|
||||||
const navigation = options.querySelector('sl-switch[name="navigation"]');
|
|
||||||
const pagination = options.querySelector('sl-switch[name="pagination"]');
|
|
||||||
const autoplay = options.querySelector('sl-switch[name="autoplay"]');
|
|
||||||
const mouseDragging = options.querySelector('sl-switch[name="mouseDragging"]');
|
|
||||||
const slidesPerMove = options.querySelector('sl-input[name="slidesPerMove"]');
|
|
||||||
const slidesPerPage = options.querySelector('sl-input[name="slidesPerPage"]');
|
|
||||||
const orientation = options.querySelector('sl-select[name="orientation"]');
|
|
||||||
|
|
||||||
loop.addEventListener('sl-change', () => (carousel.loop = loop.checked));
|
|
||||||
navigation.addEventListener('sl-change', () => (carousel.navigation = navigation.checked));
|
|
||||||
pagination.addEventListener('sl-change', () => (carousel.pagination = pagination.checked));
|
|
||||||
autoplay.addEventListener('sl-change', () => (carousel.autoplay = autoplay.checked));
|
|
||||||
slidesPerMove.addEventListener('sl-change', () => (carousel.slidesPerMove = slidesPerMove.valueAsNumber));
|
|
||||||
slidesPerPage.addEventListener('sl-change', () => (carousel.slidesPerPage = slidesPerPage.valueAsNumber));
|
|
||||||
orientation.addEventListener('sl-change', () => (carousel.orientation = orientation.value));
|
|
||||||
mouseDragging.addEventListener('sl-change', () => (carousel.mouseDragging = mouseDragging.checked));
|
|
||||||
|
|
||||||
document.addEventListener('sl-slide-change', e => {
|
|
||||||
console.log('Slide changed:', e.detail);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```jsx react
|
```jsx react
|
||||||
import { useReducer } from 'react';
|
import { SlCarousel, SlCarouselItem } from '@shoelace-style/shoelace/dist/react';
|
||||||
import {
|
|
||||||
SlCarousel,
|
|
||||||
SlCarouselItem,
|
|
||||||
SlSwitch,
|
|
||||||
SlInput,
|
|
||||||
SlSelect,
|
|
||||||
SlMenuItem
|
|
||||||
} from '@shoelace-style/shoelace/dist/react';
|
|
||||||
|
|
||||||
const css = `
|
const App = () => (
|
||||||
sl-carousel {
|
<>
|
||||||
--aspect-ratio: 3 / 2;
|
<SlCarousel pagination mouse-dragging>
|
||||||
}
|
<SlCarouselItem>
|
||||||
|
<img
|
||||||
.carousel-options {
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
display: flex;
|
src="/assets/examples/carousel/mountains.jpg"
|
||||||
flex-wrap: wrap;
|
/>
|
||||||
align-items: end;
|
</SlCarouselItem>
|
||||||
gap: 1rem;
|
<SlCarouselItem>
|
||||||
}
|
<img
|
||||||
`;
|
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||||
|
src="/assets/examples/carousel/waterfall.jpg"
|
||||||
const App = () => {
|
/>
|
||||||
const [state, updateState] = useReducer(
|
</SlCarouselItem>
|
||||||
(state, event) => {
|
<SlCarouselItem>
|
||||||
console.log(event);
|
<img
|
||||||
},
|
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||||
{
|
src="/assets/examples/carousel/sunset.jpg"
|
||||||
loop: true,
|
/>
|
||||||
pagination: true,
|
</SlCarouselItem>
|
||||||
navigation: true,
|
<SlCarouselItem>
|
||||||
autoplay: true,
|
<img
|
||||||
mouseDragging: true,
|
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||||
slidesPerPage: 1,
|
src="/assets/examples/carousel/field.jpg"
|
||||||
slidesPerMove: 1,
|
/>
|
||||||
orientation: 'horizontal'
|
</SlCarouselItem>
|
||||||
}
|
<SlCarouselItem>
|
||||||
);
|
<img
|
||||||
return (
|
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||||
<>
|
src="/assets/examples/carousel/valley.jpg"
|
||||||
<SlCarousel
|
/>
|
||||||
loop={state.loop}
|
</SlCarouselItem>
|
||||||
pagination={state.pagination}
|
</SlCarousel>
|
||||||
navigation={state.navigation}
|
</>
|
||||||
autoplay={state.autoplay}
|
);
|
||||||
mouseDragging={state.mouseDragging}
|
|
||||||
>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
|
||||||
src="/assets/examples/carousel/mountains.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
|
||||||
src="/assets/examples/carousel/waterfall.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
|
||||||
src="/assets/examples/carousel/sunset.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
|
||||||
src="/assets/examples/carousel/field.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
|
||||||
src="/assets/examples/carousel/valley.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
</SlCarousel>
|
|
||||||
<SlDivider></SlDivider>
|
|
||||||
<div className="carousel-options">
|
|
||||||
<div className="carousel-options">
|
|
||||||
<SlSwitch checked name="loop" value={state.loop} onSlChange={updateState}>
|
|
||||||
Loop
|
|
||||||
</SlSwitch>
|
|
||||||
<SlSwitch checked name="navigation" value={state.navigation} onSlChange={updateState}>
|
|
||||||
Show navigation
|
|
||||||
</SlSwitch>
|
|
||||||
<SlSwitch checked name="pagination" value={state.pagination} onSlChange={updateState}>
|
|
||||||
Show pagination
|
|
||||||
</SlSwitch>
|
|
||||||
<SlSwitch checked name="autoplay" value={state.autoplay} onSlChange={updateState}>
|
|
||||||
Autoplay (3s)
|
|
||||||
</SlSwitch>
|
|
||||||
<SlSwitch checked name="mouseDragging" value={state.mouseDragging} onSlChange={updateState}>
|
|
||||||
Mouse dragging
|
|
||||||
</SlSwitch>
|
|
||||||
</div>
|
|
||||||
<div className="carousel-options">
|
|
||||||
<SlInput
|
|
||||||
type="number"
|
|
||||||
label="Slides per page"
|
|
||||||
name="slidesPerPage"
|
|
||||||
value={state.slidesPerPage}
|
|
||||||
onSlChange={updateState}
|
|
||||||
/>
|
|
||||||
<SlInput
|
|
||||||
type="number"
|
|
||||||
label="Slides per move"
|
|
||||||
name="slidesPerMove"
|
|
||||||
value={state.slidesPerMove}
|
|
||||||
onSlChange={updateState}
|
|
||||||
/>
|
|
||||||
<SlSelect
|
|
||||||
label="Orientation"
|
|
||||||
name="orientation"
|
|
||||||
value="horizontal"
|
|
||||||
value={state.orientation}
|
|
||||||
onSlChange={updateState}
|
|
||||||
>
|
|
||||||
<SlMenuItem value="horizontal">Horizontal</SlMenuItem>
|
|
||||||
<SlMenuItem value="vertical">Vertical</SlMenuItem>
|
|
||||||
</SlSelect>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<style>{css}</style>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<script>
|
|
||||||
(() => {
|
|
||||||
const options = document.querySelector('.carousel-options');
|
|
||||||
const carousel = document.querySelector('sl-carousel');
|
|
||||||
const loop = options.querySelector('sl-switch[name="loop"]');
|
|
||||||
const navigation = options.querySelector('sl-switch[name="navigation"]');
|
|
||||||
const pagination = options.querySelector('sl-switch[name="pagination"]');
|
|
||||||
const autoplay = options.querySelector('sl-switch[name="autoplay"]');
|
|
||||||
const mouseDragging = options.querySelector('sl-switch[name="mouseDragging"]');
|
|
||||||
const slidesPerMove = options.querySelector('sl-input[name="slidesPerMove"]');
|
|
||||||
const slidesPerPage = options.querySelector('sl-input[name="slidesPerPage"]');
|
|
||||||
const orientation = options.querySelector('sl-select[name="orientation"]');
|
|
||||||
|
|
||||||
loop.addEventListener('sl-change', () => (carousel.loop = loop.checked));
|
|
||||||
navigation.addEventListener('sl-change', () => (carousel.navigation = navigation.checked));
|
|
||||||
pagination.addEventListener('sl-change', () => (carousel.pagination = pagination.checked));
|
|
||||||
autoplay.addEventListener('sl-change', () => (carousel.autoplay = autoplay.checked));
|
|
||||||
slidesPerMove.addEventListener('sl-change', () => (carousel.slidesPerMove = slidesPerMove.valueAsNumber));
|
|
||||||
slidesPerPage.addEventListener('sl-change', () => (carousel.slidesPerPage = slidesPerPage.valueAsNumber));
|
|
||||||
orientation.addEventListener('sl-change', () => (carousel.orientation = orientation.value));
|
|
||||||
mouseDragging.addEventListener('sl-change', () => (carousel.mouseDragging = mouseDragging.checked));
|
|
||||||
|
|
||||||
document.addEventListener('sl-slide-change', e => {
|
|
||||||
console.log('Slide changed:', e.detail);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Multiple slides per view
|
### Pagination
|
||||||
|
|
||||||
Setting the attribute `slides-per-view` is it possible to specify how many items are shown at a given time.
|
Use the `pagination` attribute to show the total number of slides and the current slide as a set of interactive dots.
|
||||||
Using this feature, it may be also useful to advance multiple slides at once, even though not strictly necessary.
|
|
||||||
This can be done by using the `slides-per-move` attribute.
|
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
<sl-carousel class="multi-carousel" loop navigation pagination slides-per-page="3" slides-per-move="3">
|
<sl-carousel pagination>
|
||||||
<sl-carousel-item style="background: #204ed8;">Slide 1</sl-carousel-item>
|
<sl-carousel-item>
|
||||||
<sl-carousel-item style="background: #be133d;">Slide 2</sl-carousel-item>
|
<img
|
||||||
<sl-carousel-item style="background: #6e28d9;">Slide 3</sl-carousel-item>
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
<sl-carousel-item style="background: #c2420d;">Slide 4</sl-carousel-item>
|
src="/assets/examples/carousel/mountains.jpg"
|
||||||
<sl-carousel-item style="background: #4d7c0f;">Slide 5</sl-carousel-item>
|
/>
|
||||||
<sl-carousel-item style="background: #4338cb;">Slide 6</sl-carousel-item>
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||||
|
src="/assets/examples/carousel/waterfall.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||||
|
src="/assets/examples/carousel/sunset.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||||
|
src="/assets/examples/carousel/field.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||||
|
src="/assets/examples/carousel/valley.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
</sl-carousel>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
|
||||||
|
Use the `navigation` attribute to show previous and next buttons.
|
||||||
|
|
||||||
|
```html preview
|
||||||
|
<sl-carousel navigation>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
src="/assets/examples/carousel/mountains.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||||
|
src="/assets/examples/carousel/waterfall.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||||
|
src="/assets/examples/carousel/sunset.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||||
|
src="/assets/examples/carousel/field.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||||
|
src="/assets/examples/carousel/valley.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
</sl-carousel>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Looping
|
||||||
|
|
||||||
|
By default, the carousel will not advanced beyond the first and last slides. You can change this behavior and force the carousel to "wrap" with the `loop` attribute.
|
||||||
|
|
||||||
|
```html preview
|
||||||
|
<sl-carousel loop navigation pagination>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
src="/assets/examples/carousel/mountains.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||||
|
src="/assets/examples/carousel/waterfall.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||||
|
src="/assets/examples/carousel/sunset.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||||
|
src="/assets/examples/carousel/field.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||||
|
src="/assets/examples/carousel/valley.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
</sl-carousel>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Autoplay
|
||||||
|
|
||||||
|
The carousel will automatically advance when the `autoplay` attribute is used. To change how long a slide is shown before advancing, set `autoplay-interval` to the desired number of milliseconds. For best results, use the `loop` attribute when autoplay is enabled. Note that autoplay will pause while the user interacts with the carousel.
|
||||||
|
|
||||||
|
```html preview
|
||||||
|
<sl-carousel autoplay loop pagination>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
src="/assets/examples/carousel/mountains.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||||
|
src="/assets/examples/carousel/waterfall.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||||
|
src="/assets/examples/carousel/sunset.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||||
|
src="/assets/examples/carousel/field.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||||
|
src="/assets/examples/carousel/valley.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
</sl-carousel>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mouse Dragging
|
||||||
|
|
||||||
|
The carousel uses [scroll snap](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap) to position slides at various snap positions. This allows users to scroll through the slides very naturally, especially on touch devices. Unfortunately, desktop users won't be able to click and drag with a mouse, which can feel unnatural. Adding the `mouse-dragging` attribute can help with this.
|
||||||
|
|
||||||
|
This example is best demonstrated using a mouse. Try clicking and dragging the slide to move it. Then toggle the switch and try again.
|
||||||
|
|
||||||
|
```html preview
|
||||||
|
<div class="mouse-dragging">
|
||||||
|
<sl-carousel pagination>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
src="/assets/examples/carousel/mountains.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
||||||
|
src="/assets/examples/carousel/waterfall.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
||||||
|
src="/assets/examples/carousel/sunset.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
||||||
|
src="/assets/examples/carousel/field.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
<sl-carousel-item>
|
||||||
|
<img
|
||||||
|
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
||||||
|
src="/assets/examples/carousel/valley.jpg"
|
||||||
|
/>
|
||||||
|
</sl-carousel-item>
|
||||||
|
</sl-carousel>
|
||||||
|
|
||||||
|
<sl-divider></sl-divider>
|
||||||
|
|
||||||
|
<sl-switch>Enable mouse dragging</sl-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const container = document.querySelector('.mouse-dragging');
|
||||||
|
const carousel = container.querySelector('sl-carousel');
|
||||||
|
const toggle = container.querySelector('sl-switch');
|
||||||
|
|
||||||
|
toggle.addEventListener('sl-change', () => {
|
||||||
|
carousel.toggleAttribute('mouse-dragging', toggle.checked);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Slides Per View
|
||||||
|
|
||||||
|
The `slides-per-view` attribute makes it possible to display multiple slides at a time. You can also use the `slides-per-move` attribute to advance more than once slide at a time, if desired.
|
||||||
|
|
||||||
|
```html preview
|
||||||
|
<sl-carousel class="multi-carousel" navigation pagination slides-per-page="2" slides-per-move="2">
|
||||||
|
<sl-carousel-item style="background: var(--sl-color-red-200);">Slide 1</sl-carousel-item>
|
||||||
|
<sl-carousel-item style="background: var(--sl-color-orange-200);">Slide 2</sl-carousel-item>
|
||||||
|
<sl-carousel-item style="background: var(--sl-color-yellow-200);">Slide 3</sl-carousel-item>
|
||||||
|
<sl-carousel-item style="background: var(--sl-color-green-200);">Slide 4</sl-carousel-item>
|
||||||
|
<sl-carousel-item style="background: var(--sl-color-blue-200);">Slide 5</sl-carousel-item>
|
||||||
|
<sl-carousel-item style="background: var(--sl-color-violet-200);">Slide 6</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -281,66 +313,73 @@ import { SlCarousel, SlCarouselItem } from '@shoelace-style/shoelace/dist/react'
|
||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<SlCarousel class="multi-carousel" loop navigation pagination slides-per-page="3" slides-per-move="3">
|
<SlCarousel class="multi-carousel" loop navigation pagination slides-per-page="3" slides-per-move="3">
|
||||||
<SlCarouselItem style="background: #204ed8;">Slide 1</SlCarouselItem>
|
<SlCarouselItem style="background: var(--sl-color-red-200);">Slide 1</SlCarouselItem>
|
||||||
<SlCarouselItem style="background: #be133d;">Slide 2</SlCarouselItem>
|
<SlCarouselItem style="background: var(--sl-color-orange-200);">Slide 2</SlCarouselItem>
|
||||||
<SlCarouselItem style="background: #6e28d9;">Slide 3</SlCarouselItem>
|
<SlCarouselItem style="background: var(--sl-color-yellow-200);">Slide 3</SlCarouselItem>
|
||||||
<SlCarouselItem style="background: #c2420d;">Slide 4</SlCarouselItem>
|
<SlCarouselItem style="background: var(--sl-color-green-200);">Slide 4</SlCarouselItem>
|
||||||
<SlCarouselItem style="background: #4d7c0f;">Slide 5</SlCarouselItem>
|
<SlCarouselItem style="background: var(--sl-color-blue-200);">Slide 5</SlCarouselItem>
|
||||||
<SlCarouselItem style="background: #4338cb;">Slide 6</SlCarouselItem>
|
<SlCarouselItem style="background: var(--sl-color-violet-200);">Slide 6</SlCarouselItem>
|
||||||
</SlCarousel>
|
</SlCarousel>
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Adding/removing slides
|
### Adding and Removing Slides
|
||||||
|
|
||||||
The content of the carousel can be changed by either appending or removing items, the carousel will update itself automatically.
|
The content of the carousel can be changed by appending or removing carousel items. The carousel will update itself automatically.
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
<sl-carousel class="dynamic-carousel" pagination navigation>
|
<sl-carousel class="dynamic-carousel" pagination navigation>
|
||||||
<sl-carousel-item style="background: #204ed8;">Slide 1</sl-carousel-item>
|
<sl-carousel-item style="background: var(--sl-color-red-200)">Slide 1</sl-carousel-item>
|
||||||
<sl-carousel-item style="background: #be133d;">Slide 2</sl-carousel-item>
|
<sl-carousel-item style="background: var(--sl-color-orange-200)">Slide 2</sl-carousel-item>
|
||||||
<sl-carousel-item style="background: #6e28d9;">Slide 3</sl-carousel-item>
|
<sl-carousel-item style="background: var(--sl-color-yellow-200)">Slide 3</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
<sl-divider></sl-divider>
|
|
||||||
<div class="carousel-options">
|
<div class="carousel-options">
|
||||||
<sl-button id="dynamic-add">Add slide</sl-button>
|
<sl-button id="dynamic-add">Add slide</sl-button>
|
||||||
<sl-button id="dynamic-remove">Remove slide</sl-button>
|
<sl-button id="dynamic-remove">Remove slide</sl-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.dynamic-carousel {
|
.dynamic-carousel {
|
||||||
--aspect-ratio: 3 / 2;
|
--aspect-ratio: 3 / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dynamic-carousel ~ .carousel-options {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: var(--sl-spacing-x-small);
|
||||||
|
margin-top: var(--sl-spacing-large);
|
||||||
|
}
|
||||||
|
|
||||||
.dynamic-carousel sl-carousel-item {
|
.dynamic-carousel sl-carousel-item {
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
color: white;
|
|
||||||
font-size: var(--sl-font-size-2x-large);
|
font-size: var(--sl-font-size-2x-large);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(() => {
|
(() => {
|
||||||
const dynamicCarousel = document.querySelector('.dynamic-carousel');
|
const dynamicCarousel = document.querySelector('.dynamic-carousel');
|
||||||
const dynamicAdd = document.querySelector('#dynamic-add');
|
const dynamicAdd = document.querySelector('#dynamic-add');
|
||||||
const dynamicRemove = document.querySelector('#dynamic-remove');
|
const dynamicRemove = document.querySelector('#dynamic-remove');
|
||||||
|
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'violet'];
|
||||||
const rnd = (min, max) => Math.round(Math.random() * (max - min)) + min;
|
let colorIndex = 2;
|
||||||
|
|
||||||
const getRandomColor = () => `rgb(${rnd(50, 150)}, ${rnd(50, 150)}, ${rnd(50, 150)})`;
|
|
||||||
|
|
||||||
const addSlide = () => {
|
const addSlide = () => {
|
||||||
const slide = document.createElement('sl-carousel-item');
|
const slide = document.createElement('sl-carousel-item');
|
||||||
|
const color = colors[++colorIndex % colors.length];
|
||||||
slide.innerText = `Slide ${dynamicCarousel.children.length + 1}`;
|
slide.innerText = `Slide ${dynamicCarousel.children.length + 1}`;
|
||||||
slide.style.setProperty('background', getRandomColor());
|
slide.style.setProperty('background', `var(--sl-color-${color}-200)`);
|
||||||
|
|
||||||
dynamicCarousel.appendChild(slide);
|
dynamicCarousel.appendChild(slide);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeSlide = () => {
|
const removeSlide = () => {
|
||||||
const slide = dynamicCarousel.children[dynamicCarousel.children.length - 1];
|
const slide = dynamicCarousel.children[dynamicCarousel.children.length - 1];
|
||||||
slide.remove();
|
slide.remove();
|
||||||
|
colorIndex--;
|
||||||
};
|
};
|
||||||
|
|
||||||
dynamicAdd.addEventListener('click', addSlide);
|
dynamicAdd.addEventListener('click', addSlide);
|
||||||
|
@ -358,6 +397,12 @@ const css = `
|
||||||
--aspect-ratio: 3 / 2;
|
--aspect-ratio: 3 / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dynamic-carousel ~ .carousel-options {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: var(--sl-spacing-large);
|
||||||
|
}
|
||||||
|
|
||||||
.dynamic-carousel sl-carousel-item {
|
.dynamic-carousel sl-carousel-item {
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -370,9 +415,7 @@ const css = `
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [slides, setSlides] = useState(['#204ed8', '#be133d', '#6e28d9']);
|
const [slides, setSlides] = useState(['#204ed8', '#be133d', '#6e28d9']);
|
||||||
|
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'violet'];
|
||||||
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 = () => {
|
const addSlide = () => {
|
||||||
setSlides([...slides, getRandomColor()]);
|
setSlides([...slides, getRandomColor()]);
|
||||||
|
@ -386,28 +429,31 @@ const App = () => {
|
||||||
<>
|
<>
|
||||||
<SlCarousel className="dynamic-carousel" pagination navigation>
|
<SlCarousel className="dynamic-carousel" pagination navigation>
|
||||||
{slides.map((color, i) => (
|
{slides.map((color, i) => (
|
||||||
<SlCarouselItem style={{ background: color }}>Slide {i}</SlCarouselItem>
|
<SlCarouselItem style={{ background: colors[i % colors.length }}>
|
||||||
|
Slide {i}
|
||||||
|
</SlCarouselItem>
|
||||||
))}
|
))}
|
||||||
</SlCarousel>
|
</SlCarousel>
|
||||||
<SlDivider />
|
|
||||||
<div className="carousel-options">
|
<div className="carousel-options">
|
||||||
<SlButton onClick={addSlide}>Add slide</SlButton>
|
<SlButton onClick={addSlide}>Add slide</SlButton>
|
||||||
<SlButton onClick={removeSlide}>Remove slide</SlButton>
|
<SlButton onClick={removeSlide}>Remove slide</SlButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>{css}</style>
|
<style>{css}</style>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### Vertical scrolling
|
### Vertical Scrolling
|
||||||
|
|
||||||
Setting the `orientation` attribute to `vertical`, will make the carousel laying out vertically, making it
|
Setting the `orientation` attribute to `vertical`, will make the carousel laying out vertically, making it
|
||||||
possible for the user to scroll it up and down. In case of heterogeneous content, for example images of different sizes,
|
possible for the user to scroll it up and down. In case of heterogeneous content, for example images of different sizes,
|
||||||
it's important to specify a predefined height to the carousel through CSS.
|
it's important to specify a predefined height to the carousel through CSS.
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
<sl-carousel class="vertical" loop pagination orientation="vertical">
|
<sl-carousel class="vertical" pagination orientation="vertical">
|
||||||
<sl-carousel-item>
|
<sl-carousel-item>
|
||||||
<img
|
<img
|
||||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
@ -520,12 +566,12 @@ const App = () => (
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Aspect ratio
|
### Aspect Ratio
|
||||||
|
|
||||||
Use the `--aspect-ratio` custom property to customize the size of viewport in order to make it match a particular aspect ratio.
|
Use the `--aspect-ratio` custom property to customize the size of the carousel's viewport.
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
<sl-carousel class="aspect-ratio" navigation pagination style="--aspect-ratio: 3 / 2">
|
<sl-carousel class="aspect-ratio" navigation pagination style="--aspect-ratio: 3/2">
|
||||||
<sl-carousel-item>
|
<sl-carousel-item>
|
||||||
<img
|
<img
|
||||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
@ -559,19 +605,20 @@ Use the `--aspect-ratio` custom property to customize the size of viewport in or
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
|
|
||||||
<sl-divider></sl-divider>
|
<sl-divider></sl-divider>
|
||||||
<sl-select label="Aspect ratio" name="aspect" value="3 / 2">
|
|
||||||
<sl-menu-item value="1 / 1">1 / 1</sl-menu-item>
|
<sl-select label="Aspect ratio" name="aspect" value="3/2">
|
||||||
<sl-menu-item value="3 / 2">3 / 2</sl-menu-item>
|
<sl-option value="1/1">1/1</sl-option>
|
||||||
<sl-menu-item value="16 / 9">16 / 9</sl-menu-item>
|
<sl-option value="3/2">3/2</sl-option>
|
||||||
|
<sl-option value="16/9">16/9</sl-option>
|
||||||
</sl-select>
|
</sl-select>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(() => {
|
(() => {
|
||||||
const carousel = document.querySelector('sl-carousel.aspect-ratio');
|
const carousel = document.querySelector('sl-carousel.aspect-ratio');
|
||||||
const aspect = document.querySelector('sl-select[name="aspect"]');
|
const aspectRatio = document.querySelector('sl-select[name="aspect"]');
|
||||||
|
|
||||||
aspect.addEventListener('sl-change', () => {
|
aspectRatio.addEventListener('sl-change', () => {
|
||||||
carousel.style.setProperty('--aspect-ratio', aspect.value);
|
carousel.style.setProperty('--aspect-ratio', aspectRatio.value);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@ -579,7 +626,7 @@ Use the `--aspect-ratio` custom property to customize the size of viewport in or
|
||||||
|
|
||||||
```jsx react
|
```jsx react
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { SlCarousel, SlCarouselItem, SlDivider, SlSelect, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
import { SlCarousel, SlCarouselItem, SlDivider, SlSelect, SlOption } from '@shoelace-style/shoelace/dist/react';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [aspectRatio, setAspectRatio] = useState('3/2');
|
const [aspectRatio, setAspectRatio] = useState('3/2');
|
||||||
|
@ -627,9 +674,9 @@ const App = () => {
|
||||||
value={aspectRatio}
|
value={aspectRatio}
|
||||||
onSlChange={event => setAspectRatio(event.target.value)}
|
onSlChange={event => setAspectRatio(event.target.value)}
|
||||||
>
|
>
|
||||||
<SlMenuItem value="1 / 1">1 / 1</SlMenuItem>
|
<SlOption value="1 / 1">1 / 1</SlOption>
|
||||||
<SlMenuItem value="3 / 2">3 / 2</SlMenuItem>
|
<SlOption value="3 / 2">3 / 2</SlOption>
|
||||||
<SlMenuItem value="16 / 9">16 / 9</SlMenuItem>
|
<SlOption value="16 / 9">16 / 9</SlOption>
|
||||||
</SlSelect>
|
</SlSelect>
|
||||||
|
|
||||||
<style>{css}</style>
|
<style>{css}</style>
|
||||||
|
@ -638,14 +685,12 @@ const App = () => {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### Scroll hint
|
### Scroll Hint
|
||||||
|
|
||||||
Use `--scroll-padding` to add inline padding in horizontal carousels and block padding in vertical carousels.
|
Use the `--scroll-hint` attribute to add inline padding in horizontal carousels and block padding in vertical carousels. Setting a padding will make the closest slides slightly visible, hinting that there are more items in the carousel.
|
||||||
Setting a padding, will make the closest slides visible, suggesting to the user that there are items that can
|
|
||||||
be scrolled.
|
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
<sl-carousel class="scroll-hint" navigation pagination style="--scroll-padding: calc(var(--slide-gap) + 10%);">
|
<sl-carousel class="scroll-hint" pagination style="--scroll-hint: 10%;">
|
||||||
<sl-carousel-item>
|
<sl-carousel-item>
|
||||||
<img
|
<img
|
||||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
||||||
|
@ -677,20 +722,6 @@ be scrolled.
|
||||||
/>
|
/>
|
||||||
</sl-carousel-item>
|
</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
|
|
||||||
<sl-divider></sl-divider>
|
|
||||||
<sl-range label="Size (%)" name="scroll-hint" value="5" min="0" max="15"></sl-range>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
(() => {
|
|
||||||
const carousel = document.querySelector('sl-carousel.scroll-hint');
|
|
||||||
const scrollHint = document.querySelector('sl-range[name="scroll-hint"]');
|
|
||||||
|
|
||||||
scrollHint.addEventListener('sl-input', () => {
|
|
||||||
carousel.style.setProperty('--scroll-padding', `calc(var(--slide-gap) + ${scrollHint.value}%)`);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```jsx react
|
```jsx react
|
||||||
|
@ -755,189 +786,9 @@ const App = () => {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### Custom layout
|
### Gallery Example
|
||||||
|
|
||||||
The appearance of the carousel can be easily customized through its slots or `part` attributes.
|
The carousel has a robust API that makes it possible to extend and customize. This example syncs the active slide with a set of thumbnails, effectively creating a gallery-style carousel.
|
||||||
|
|
||||||
```html preview
|
|
||||||
<sl-carousel class="custom-layout" navigation pagination>
|
|
||||||
<sl-carousel-item>
|
|
||||||
<img
|
|
||||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
|
||||||
src="/assets/examples/carousel/mountains.jpg"
|
|
||||||
/>
|
|
||||||
</sl-carousel-item>
|
|
||||||
<sl-carousel-item>
|
|
||||||
<img
|
|
||||||
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
|
||||||
src="/assets/examples/carousel/waterfall.jpg"
|
|
||||||
/>
|
|
||||||
</sl-carousel-item>
|
|
||||||
<sl-carousel-item>
|
|
||||||
<img
|
|
||||||
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
|
||||||
src="/assets/examples/carousel/sunset.jpg"
|
|
||||||
/>
|
|
||||||
</sl-carousel-item>
|
|
||||||
<sl-carousel-item>
|
|
||||||
<img
|
|
||||||
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
|
||||||
src="/assets/examples/carousel/field.jpg"
|
|
||||||
/>
|
|
||||||
</sl-carousel-item>
|
|
||||||
<sl-carousel-item>
|
|
||||||
<img
|
|
||||||
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
|
||||||
src="/assets/examples/carousel/valley.jpg"
|
|
||||||
/>
|
|
||||||
</sl-carousel-item>
|
|
||||||
|
|
||||||
<sl-icon name="arrow-right" slot="next-icon"></sl-icon>
|
|
||||||
<sl-icon name="arrow-left" slot="previous-icon"></sl-icon>
|
|
||||||
</sl-carousel>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
```
|
|
||||||
|
|
||||||
```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 = () => (
|
|
||||||
<>
|
|
||||||
<SlCarousel className="custom-layout" pagination navigation>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="The sun shines on the mountains and trees - Photo by Adam Kool on Unsplash"
|
|
||||||
src="/assets/examples/carousel/mountains.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="A waterfall in the middle of a forest - Photo by Thomas Kelly on Unsplash"
|
|
||||||
src="/assets/examples/carousel/waterfall.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="The sun is setting over a lavender field - Photo by Leonard Cotte on Unsplash"
|
|
||||||
src="/assets/examples/carousel/sunset.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="A field of grass with the sun setting in the background - Photo by Sapan Patel on Unsplash"
|
|
||||||
src="/assets/examples/carousel/field.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
<SlCarouselItem>
|
|
||||||
<img
|
|
||||||
alt="A scenic view of a mountain with clouds rolling in - Photo by V2osk on Unsplash"
|
|
||||||
src="/assets/examples/carousel/valley.jpg"
|
|
||||||
/>
|
|
||||||
</SlCarouselItem>
|
|
||||||
|
|
||||||
<SlIcon name="arrow-right" slot="next-icon"></SlIcon>
|
|
||||||
<SlIcon name="arrow-left" slot="previous-icon"></SlIcon>
|
|
||||||
</SlCarousel>
|
|
||||||
<style>{css}</style>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Gallery example
|
|
||||||
|
|
||||||
The carousel has a set of API with which is possible to interact programmatically, for example it is possible to
|
|
||||||
use `next()` or `previous()` to go respectively to the next or the previous slide.
|
|
||||||
|
|
||||||
When the active slide is changed, the `sl-slide-change` event is emitted providing the `index` of the slide.
|
|
||||||
|
|
||||||
Using the API is possible to extend the carousel, for example by syncing the active slide with a set of thumbnails, like in the example below.
|
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
<sl-carousel class="carousel-thumbnails" navigation loop>
|
<sl-carousel class="carousel-thumbnails" navigation loop>
|
||||||
|
@ -972,6 +823,7 @@ Using the API is possible to extend the carousel, for example by syncing the act
|
||||||
/>
|
/>
|
||||||
</sl-carousel-item>
|
</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
|
|
||||||
<div class="thumbnails">
|
<div class="thumbnails">
|
||||||
<div class="thumbnails__scroller">
|
<div class="thumbnails__scroller">
|
||||||
<img alt="Thumbnail Photo by 1" class="thumbnails__image active" src="/assets/examples/carousel/mountains.jpg" />
|
<img alt="Thumbnail Photo by 1" class="thumbnails__image active" src="/assets/examples/carousel/mountains.jpg" />
|
||||||
|
@ -981,6 +833,7 @@ Using the API is possible to extend the carousel, for example by syncing the act
|
||||||
<img alt="Thumbnail Photo by 5" class="thumbnails__image" src="/assets/examples/carousel/valley.jpg" />
|
<img alt="Thumbnail Photo by 5" class="thumbnails__image" src="/assets/examples/carousel/valley.jpg" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.carousel-thumbnails {
|
.carousel-thumbnails {
|
||||||
--slide-aspect-ratio: 3 / 2;
|
--slide-aspect-ratio: 3 / 2;
|
||||||
|
@ -1020,6 +873,7 @@ Using the API is possible to extend the carousel, for example by syncing the act
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
{
|
{
|
||||||
const carousel = document.querySelector('.carousel-thumbnails');
|
const carousel = document.querySelector('.carousel-thumbnails');
|
||||||
|
|
|
@ -9,25 +9,20 @@ export default css`
|
||||||
|
|
||||||
--slide-gap: var(--sl-spacing-medium, 1rem);
|
--slide-gap: var(--sl-spacing-medium, 1rem);
|
||||||
--aspect-ratio: 16 / 9;
|
--aspect-ratio: 16 / 9;
|
||||||
--scroll-padding: 0px;
|
--scroll-hint: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel {
|
.carousel {
|
||||||
min-height: 100%;
|
|
||||||
min-width: 100%;
|
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
||||||
gap: var(--sl-spacing-medium);
|
|
||||||
|
|
||||||
grid-template-columns: min-content 1fr min-content;
|
grid-template-columns: min-content 1fr min-content;
|
||||||
grid-template-rows: 1fr min-content;
|
grid-template-rows: 1fr min-content;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
'. slides .'
|
'. slides .'
|
||||||
'. pagination .';
|
'. pagination .';
|
||||||
|
gap: var(--sl-spacing-medium);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
min-height: 100%;
|
||||||
|
min-width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,19 +35,16 @@ export default css`
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel__slides {
|
.carousel__slides {
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
grid-area: slides;
|
grid-area: slides;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overscroll-behavior-x: contain;
|
overscroll-behavior-x: contain;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
|
|
||||||
aspect-ratio: calc(var(--aspect-ratio) * var(--slides-per-page));
|
aspect-ratio: calc(var(--aspect-ratio) * var(--slides-per-page));
|
||||||
|
|
||||||
--slide-size: calc((100% - (var(--slides-per-page) - 1) * var(--slide-gap)) / var(--slides-per-page));
|
--slide-size: calc((100% - (var(--slides-per-page) - 1) * var(--slide-gap)) / var(--slides-per-page));
|
||||||
|
@ -69,11 +61,9 @@ export default css`
|
||||||
grid-auto-columns: var(--slide-size);
|
grid-auto-columns: var(--slide-size);
|
||||||
grid-auto-rows: 100%;
|
grid-auto-rows: 100%;
|
||||||
column-gap: var(--slide-gap);
|
column-gap: var(--slide-gap);
|
||||||
|
|
||||||
scroll-snap-type: x mandatory;
|
scroll-snap-type: x mandatory;
|
||||||
|
scroll-padding-inline: var(--scroll-hint);
|
||||||
scroll-padding-inline: var(--scroll-padding);
|
padding-inline: var(--scroll-hint);
|
||||||
padding-inline: var(--scroll-padding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel__slides--vertical {
|
.carousel__slides--vertical {
|
||||||
|
@ -81,11 +71,9 @@ export default css`
|
||||||
grid-auto-columns: 100%;
|
grid-auto-columns: 100%;
|
||||||
grid-auto-rows: var(--slide-size);
|
grid-auto-rows: var(--slide-size);
|
||||||
row-gap: var(--slide-gap);
|
row-gap: var(--slide-gap);
|
||||||
|
|
||||||
scroll-snap-type: y mandatory;
|
scroll-snap-type: y mandatory;
|
||||||
|
scroll-padding-block: var(--scroll-hint);
|
||||||
scroll-padding-block: var(--scroll-padding);
|
padding-block: var(--scroll-hint);
|
||||||
padding-block: var(--scroll-padding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel__slides--dragging,
|
.carousel__slides--dragging,
|
||||||
|
@ -104,7 +92,6 @@ export default css`
|
||||||
.carousel__navigation {
|
.carousel__navigation {
|
||||||
grid-area: navigation;
|
grid-area: navigation;
|
||||||
display: contents;
|
display: contents;
|
||||||
|
|
||||||
font-size: var(--sl-font-size-x-large);
|
font-size: var(--sl-font-size-x-large);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ import styles from './carousel.styles';
|
||||||
import type { CSSResultGroup } from 'lit';
|
import type { CSSResultGroup } from 'lit';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Carousels display an arbitrary number of slides along a horizontal or vertical axis.
|
* @summary Carousels display an arbitrary number of content slides along a horizontal or vertical axis.
|
||||||
*
|
*
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @status experimental
|
* @status experimental
|
||||||
|
@ -42,7 +42,7 @@ import type { CSSResultGroup } from 'lit';
|
||||||
*
|
*
|
||||||
* @cssproperty --slide-gap - The space between each slide.
|
* @cssproperty --slide-gap - The space between each slide.
|
||||||
* @cssproperty --aspect-ratio - The aspect ratio of each slide.
|
* @cssproperty --aspect-ratio - The aspect ratio of each slide.
|
||||||
* @cssproperty --scroll-padding - The amount of padding to apply to the scroll area. Useful to make adjacent slides
|
* @cssproperty --scroll-hint - The amount of padding to apply to the scroll area. Useful to make adjacent slides
|
||||||
* visible.
|
* visible.
|
||||||
*/
|
*/
|
||||||
@customElement('sl-carousel')
|
@customElement('sl-carousel')
|
||||||
|
@ -320,22 +320,17 @@ export default class SlCarousel extends ShoelaceElement {
|
||||||
${map(range(pagesCount), index => {
|
${map(range(pagesCount), index => {
|
||||||
const isActive = index === currentPage;
|
const isActive = index === currentPage;
|
||||||
return html`
|
return html`
|
||||||
<span role="presentation">
|
<button
|
||||||
<button
|
part="pagination-item ${isActive ? 'pagination-item--active' : ''}"
|
||||||
@click="${() => this.goToSlide(index * slidesPerPage)}"
|
class="${classMap({
|
||||||
aria-selected="${isActive ? 'true' : 'false'}"
|
'carousel__pagination-item': true,
|
||||||
aria-label="${this.localize.term('goToCarouselSlide', index + 1, pagesCount)}"
|
'carousel__pagination-item--active': isActive
|
||||||
role="tab"
|
})}"
|
||||||
part="
|
aria-selected="${isActive ? 'true' : 'false'}"
|
||||||
pagination-item
|
aria-label="${this.localize.term('goToCarouselSlide', index + 1, pagesCount)}"
|
||||||
${isActive ? 'pagination-item--active' : ''}
|
role="tab"
|
||||||
"
|
@click="${() => this.goToSlide(index * slidesPerPage)}"
|
||||||
class="${classMap({
|
></button>
|
||||||
'carousel__pagination-item': true,
|
|
||||||
'carousel__pagination-item--active': isActive
|
|
||||||
})}"
|
|
||||||
></button>
|
|
||||||
</span>
|
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
Ładowanie…
Reference in New Issue