chore(carousel): animation timeline poc

This commit is contained in:
Alessandro
2024-10-04 15:31:17 +00:00
committed by GitHub
parent 1fb72ad4eb
commit 1eff2f888f
2 changed files with 47 additions and 29 deletions

View File

@@ -17,6 +17,7 @@ import SlIcon from '../icon/icon.component.js';
import styles from './carousel.styles.js';
import type { CSSResultGroup, PropertyValueMap } from 'lit';
import type SlCarouselItem from '../carousel-item/carousel-item.component.js';
import { styleMap } from 'lit/directives/style-map.js';
/**
* @summary Carousels display an arbitrary number of content slides along a horizontal or vertical axis.
@@ -506,11 +507,11 @@ export default class SlCarousel extends ShoelaceElement {
id="scroll-container"
part="scroll-container"
class="${classMap({
carousel__slides: true,
'carousel__slides--horizontal': this.orientation === 'horizontal',
'carousel__slides--vertical': this.orientation === 'vertical',
'carousel__slides--dragging': this.dragging
})}"
carousel__slides: true,
'carousel__slides--horizontal': this.orientation === 'horizontal',
'carousel__slides--vertical': this.orientation === 'vertical',
'carousel__slides--dragging': this.dragging
})}"
style="--slides-per-page: ${this.slidesPerPage};"
aria-busy="${scrolling ? 'true' : 'false'}"
aria-atomic="true"
@@ -524,15 +525,15 @@ export default class SlCarousel extends ShoelaceElement {
</div>
${this.navigation
? html`
? html`
<div part="navigation" class="carousel__navigation">
<button
part="navigation-button navigation-button--previous"
class="${classMap({
'carousel__navigation-button': true,
'carousel__navigation-button--previous': true,
'carousel__navigation-button--disabled': !prevEnabled
})}"
'carousel__navigation-button': true,
'carousel__navigation-button--previous': true,
'carousel__navigation-button--disabled': !prevEnabled
})}"
aria-label="${this.localize.term('previousSlide')}"
aria-controls="scroll-container"
aria-disabled="${prevEnabled ? 'false' : 'true'}"
@@ -546,10 +547,10 @@ export default class SlCarousel extends ShoelaceElement {
<button
part="navigation-button navigation-button--next"
class=${classMap({
'carousel__navigation-button': true,
'carousel__navigation-button--next': true,
'carousel__navigation-button--disabled': !nextEnabled
})}
'carousel__navigation-button': true,
'carousel__navigation-button--next': true,
'carousel__navigation-button--disabled': !nextEnabled
})}
aria-label="${this.localize.term('nextSlide')}"
aria-controls="scroll-container"
aria-disabled="${nextEnabled ? 'false' : 'true'}"
@@ -561,19 +562,21 @@ export default class SlCarousel extends ShoelaceElement {
</button>
</div>
`
: ''}
: ''}
${this.pagination
? html`
<div part="pagination" role="tablist" class="carousel__pagination" aria-controls="scroll-container">
? html`
<div part="pagination" role="tablist" class="carousel__pagination" aria-controls="scroll-container" style="${styleMap({
'--pages': pagesCount
})}">
${map(range(pagesCount), index => {
const isActive = index === currentPage;
return html`
const isActive = index === currentPage;
return html`
<button
part="pagination-item ${isActive ? 'pagination-item--active' : ''}"
class="${classMap({
'carousel__pagination-item': true,
'carousel__pagination-item--active': isActive
})}"
class="carousel__pagination-item"
style="${styleMap({
'--index': index
})}"
role="tab"
aria-selected="${isActive ? 'true' : 'false'}"
aria-label="${this.localize.term('goToSlide', index + 1, pagesCount)}"
@@ -582,10 +585,10 @@ export default class SlCarousel extends ShoelaceElement {
@keydown=${this.handleKeyDown}
></button>
`;
})}
})}
</div>
`
: ''}
: ''}
</div>
`;
}

View File

@@ -10,6 +10,7 @@ export default css`
}
.carousel {
timeline-scope: --carousel;
display: grid;
grid-template-columns: min-content 1fr min-content;
grid-template-rows: 1fr min-content;
@@ -33,7 +34,6 @@ export default css`
.carousel__slides {
grid-area: slides;
display: grid;
height: 100%;
width: 100%;
@@ -55,6 +55,7 @@ export default css`
}
.carousel__slides--horizontal {
scroll-timeline: --carousel x;
grid-auto-flow: column;
grid-auto-columns: var(--slide-size);
grid-auto-rows: 100%;
@@ -66,6 +67,7 @@ export default css`
}
.carousel__slides--vertical {
scroll-timeline: --carousel y;
grid-auto-flow: row;
grid-auto-columns: 100%;
grid-auto-rows: var(--slide-size);
@@ -140,9 +142,22 @@ export default css`
margin: 0;
}
.carousel__pagination-item--active {
background-color: var(--sl-color-neutral-700);
transform: scale(1.2);
@keyframes pagination-item-active {
0%,
100% {
background-color: var(--sl-color-neutral-700);
transform: scale(1.2);
}
}
@supports (animation-timeline: view()) {
.carousel__pagination-item {
animation: pagination-item-active linear;
animation-timeline: --carousel;
animation-range:
calc(var(--index) * calc(100% / var(--pages)))
calc((var(--index) + 1) * calc(100% / var(--pages) + 1px));
}
}
/* Focus styles */