Carousel
Керована карусель зі swipe, клавіатурою, autoplay-паузою та reduced motion.
Приклад
API
Props
| Назва | Тип | Типово | Опис |
|---|---|---|---|
items* | T[] | — | Слайди. Рендер кожного — слот `slide`. |
modelValue | number | 0 | Індекс поточного слайда. Використовуйте через `v-model`. |
interval | number | 5000 | Пауза між автоматичними переходами, мс. |
ariaLabel | string | "Карусель" | Доступна назва каруселі. |
loop | boolean | false | З останнього слайда переходити на перший. |
autoplay | boolean | false | Автоматичне гортання. Вимикається саме собою при `prefers-reduced-motion`, на час наведення чи фокуса і доки вкладка у фоні. |
pauseOnHover | boolean | true | Спинати автогортання під курсором. |
draggable | boolean | true | Перетягування слайда пальцем або мишею. Вимикайте, коли всередині слайда є текст для виділення або поля вводу. |
Події
| Назва | Payload | Опис |
|---|---|---|
update:modelValue | [value: number] | Індекс активного слайда. |
change | [value: number] | Новий індекс після переходу. |
Слоти
| Назва | Опис |
|---|---|
slide | — |
previous | — |
next | — |
Доступно через ref
| Назва | Тип | Опис |
|---|---|---|
previous | () => void | — |
next | () => void | — |
goTo | (index: number) => void | — |
pause | () => void | — |
play | () => void | — |
Коли використовувати
Для невеликої послідовності промо, onboarding або медіа, де один елемент має бути в центрі уваги. Компонент підтримує controlled index і кастомний слот слайда.
Коли НЕ використовувати
Не ховайте критичний контент чи основну навігацію в каруселі. Для списку карток краще звичайна grid, а для великих наборів — pagination.
На мобільних пристроях
Основний жест — свайп. Поріг перемикання масштабується від ширини треку
(15%, але не менше 40px), а швидкий короткий змах (флік до 200 мс) листає
слайд навіть без «дотягування» — відчуття жесту однакове на телефоні та
планшеті. Жест класифікується за домінантною віссю: горизонтальний рух
веде слайд один-в-один (з гумовими краями без loop), вертикальний —
цілком віддається скролу сторінки. Вказівник захоплюється
setPointerCapture, тож палець, що з'їхав із компонента, не обриває
перетягування. Другий палець не збиває активний жест. Стрілки навігації на
coarse-вказівнику приховані — вони конфліктували б із пальцем поверх
контенту; навігація — свайп і крапки-індикатори з зоною дотику 44×44.
Доступність
Region і слайди мають carousel-ролі та позицію «N з M». Стрілки, Home й End
працюють із клавіатури. Autoplay зупиняється під час focus і hover, має явну
кнопку Pause, стає на паузу, доки вкладка у фоні, та не запускається при
prefers-reduced-motion — який також вимикає slide-transition переходу.
Перетягування (draggable) — піксель-в-піксель за вказівником; клік одразу
після жесту проковтується, щоб не «натискати» те, що було під пальцем у
момент відпускання. touch-pan-y лишає вертикальне гортання сторінці, тож
жест не конфліктує з прокруткою.
Деталі реалізації
Логіка жесту — чисті функції в app/utils/carousel.ts (dragThreshold,
dragAxis, shouldAdvance, rubberBandDelta, swipeDirection), покриті
тестами без рендеру. Трек зсувається translate3d — шар на GPU без
перестворень на кожному pointermove.