Basic Carousel
A slide carousel with prev/next arrows, dots and a polite live region.
6 个框架中级
A main stage and a thumbnail rail that stay in sync, with the active thumb auto-scrolling into view.
<!-- Main stage synced to a thumbnail rail: arrows move the stage, and whichever
thumb becomes current scrolls itself into view, so the rail and stage never
drift apart. Each thumb is a real button labelled with the frame name. -->
<section class="max-w-2xl" aria-roledescription="carousel" aria-label="Screens" data-ts>
<div class="overflow-hidden rounded-xl" aria-live="polite">
<div class="flex transition-transform duration-500 ease-out motion-reduce:transition-none" data-ts-track>
<div class="flex aspect-[16/9] shrink-0 basis-full items-end bg-gradient-to-br from-blue-600 to-indigo-600 p-5 text-white" role="group" aria-roledescription="slide" aria-label="1 of 3"><span class="text-lg font-semibold">Overview</span></div>
<div class="flex aspect-[16/9] shrink-0 basis-full items-end bg-gradient-to-br from-indigo-600 to-violet-600 p-5 text-white" role="group" aria-roledescription="slide" aria-label="2 of 3" aria-hidden="true"><span class="text-lg font-semibold">Reports</span></div>
<div class="flex aspect-[16/9] shrink-0 basis-full items-end bg-gradient-to-br from-teal-700 to-sky-700 p-5 text-white" role="group" aria-roledescription="slide" aria-label="3 of 3" aria-hidden="true"><span class="text-lg font-semibold">Settings</span></div>
</div>
</div>
<div class="mt-3 flex gap-2 overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden" data-ts-thumbs>
<button class="h-12 w-20 shrink-0 rounded-lg bg-gradient-to-br from-blue-600 to-indigo-600 opacity-50 ring-2 ring-transparent transition focus-visible:outline-none focus-visible:ring-blue-600 aria-[current=true]:opacity-100 aria-[current=true]:ring-blue-600 dark:focus-visible:ring-blue-400 dark:aria-[current=true]:ring-blue-400" type="button" aria-label="Show Overview" aria-current="true"></button>
<button class="h-12 w-20 shrink-0 rounded-lg bg-gradient-to-br from-indigo-600 to-violet-600 opacity-50 ring-2 ring-transparent transition focus-visible:outline-none focus-visible:ring-blue-600 aria-[current=true]:opacity-100 aria-[current=true]:ring-blue-600 dark:focus-visible:ring-blue-400 dark:aria-[current=true]:ring-blue-400" type="button" aria-label="Show Reports"></button>
<button class="h-12 w-20 shrink-0 rounded-lg bg-gradient-to-br from-teal-700 to-sky-700 opacity-50 ring-2 ring-transparent transition focus-visible:outline-none focus-visible:ring-blue-600 aria-[current=true]:opacity-100 aria-[current=true]:ring-blue-600 dark:focus-visible:ring-blue-400 dark:aria-[current=true]:ring-blue-400" type="button" aria-label="Show Settings"></button>
</div>
</section>
<script>
(function () {
document.querySelectorAll('[data-ts]').forEach(function (root) {
var track = root.querySelector('[data-ts-track]');
var slides = Array.prototype.slice.call(track.children);
var thumbs = Array.prototype.slice.call(root.querySelectorAll('[data-ts-thumbs] button'));
var index = 0;
function go(next) {
index = (next + slides.length) % slides.length;
track.style.transform = 'translateX(' + index * -100 + '%)';
slides.forEach(function (s, i) { if (i === index) s.removeAttribute('aria-hidden'); else s.setAttribute('aria-hidden', 'true'); });
thumbs.forEach(function (t, i) {
if (i === index) { t.setAttribute('aria-current', 'true'); t.scrollIntoView({ block: 'nearest', inline: 'nearest' }); }
else t.removeAttribute('aria-current');
});
}
thumbs.forEach(function (t, i) { t.addEventListener('click', function () { go(i); }); });
});
})();
</script>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
items必填 | Frame[] | - | 要渲染的项目数组。 |
className | string | - | 合并到根元素上的额外类名。 |
ariaLabel | string | 'Gallery' | 按钮的无障碍名称。仅有图标的按钮必须设置。 |
Selecting a thumb pages the stage, and whichever thumb becomes current calls `scrollIntoView`, so a long rail never drifts away from the stage. Each thumb is a real button labelled with the frame name, and the active one shows as full opacity plus a ring - two signals, never colour alone.