Basic Carousel
A slide carousel with prev/next arrows, dots and a polite live region.
6 個のフレームワーク中級
A quote slider with gradient initials avatars and no image assets.
<!-- Testimonial slider: each slide is a blockquote with a gradient avatar built
from the author's initials, so there are no image assets. Slides page with a
transform; the avatar tile is aria-hidden since the name is real text. -->
<section class="max-w-xl" aria-roledescription="carousel" aria-label="What customers say" data-tc>
<div class="overflow-hidden rounded-2xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-gray-950" aria-live="polite">
<div class="flex transition-transform duration-500 ease-out motion-reduce:transition-none" data-tc-track>
<figure class="shrink-0 basis-full p-6 sm:p-8" role="group" aria-roledescription="slide" aria-label="1 of 2">
<blockquote class="text-base leading-relaxed text-gray-800 dark:text-gray-100">"The dashboard paid for itself in a week - we stopped exporting to spreadsheets entirely."</blockquote>
<figcaption class="mt-5 flex items-center gap-3">
<span class="grid h-10 w-10 place-items-center rounded-full bg-gradient-to-br from-blue-600 to-indigo-600 text-sm font-semibold text-white" aria-hidden="true">AL</span>
<span class="text-sm"><span class="block font-semibold text-gray-900 dark:text-gray-100">Ada Lovelace</span><span class="block text-gray-500 dark:text-gray-400">CTO, Analytical Engines</span></span>
</figcaption>
</figure>
<figure class="shrink-0 basis-full p-6 sm:p-8" role="group" aria-roledescription="slide" aria-label="2 of 2" aria-hidden="true">
<blockquote class="text-base leading-relaxed text-gray-800 dark:text-gray-100">"Setup took an afternoon and the audit log alone got us through the SOC 2 review."</blockquote>
<figcaption class="mt-5 flex items-center gap-3">
<span class="grid h-10 w-10 place-items-center rounded-full bg-gradient-to-br from-teal-700 to-sky-700 text-sm font-semibold text-white" aria-hidden="true">GH</span>
<span class="text-sm"><span class="block font-semibold text-gray-900 dark:text-gray-100">Grace Hopper</span><span class="block text-gray-500 dark:text-gray-400">VP Eng, Compiler Co</span></span>
</figcaption>
</figure>
</div>
</div>
<div class="mt-4 flex items-center justify-between">
<div class="flex gap-2" data-tc-dots>
<button class="h-2 w-2 rounded-full bg-gray-500 hover:bg-gray-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 aria-[current=true]:w-5 aria-[current=true]:bg-blue-600 dark:hover:bg-gray-400 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950 dark:aria-[current=true]:bg-blue-400" type="button" aria-label="Go to testimonial 1" aria-current="true"></button>
<button class="h-2 w-2 rounded-full bg-gray-500 hover:bg-gray-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 aria-[current=true]:w-5 aria-[current=true]:bg-blue-600 dark:hover:bg-gray-400 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950 dark:aria-[current=true]:bg-blue-400" type="button" aria-label="Go to testimonial 2"></button>
</div>
<div class="flex gap-1.5">
<button class="grid h-9 w-9 place-items-center rounded-full border border-gray-200 bg-white text-gray-700 hover:bg-gray-50 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700 dark:hover:text-white dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950" type="button" aria-label="Previous testimonial" data-tc-prev>
<svg class="h-[1.125rem] w-[1.125rem]" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="m12.5 5-5 5 5 5" stroke-linecap="round" stroke-linejoin="round" /></svg>
</button>
<button class="grid h-9 w-9 place-items-center rounded-full border border-gray-200 bg-white text-gray-700 hover:bg-gray-50 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700 dark:hover:text-white dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950" type="button" aria-label="Next testimonial" data-tc-next>
<svg class="h-[1.125rem] w-[1.125rem]" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="m7.5 5 5 5-5 5" stroke-linecap="round" stroke-linejoin="round" /></svg>
</button>
</div>
</div>
</section>
<script>
(function () {
document.querySelectorAll('[data-tc]').forEach(function (root) {
var track = root.querySelector('[data-tc-track]');
var slides = Array.prototype.slice.call(track.children);
var dots = Array.prototype.slice.call(root.querySelectorAll('[data-tc-dots] 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'); });
dots.forEach(function (d, i) { if (i === index) d.setAttribute('aria-current', 'true'); else d.removeAttribute('aria-current'); });
}
root.querySelector('[data-tc-prev]').addEventListener('click', function () { go(index - 1); });
root.querySelector('[data-tc-next]').addEventListener('click', function () { go(index + 1); });
dots.forEach(function (d, i) { d.addEventListener('click', function () { go(i); }); });
});
})();
</script>| Prop | 型 | デフォルト | 説明 |
|---|---|---|---|
items必須 | Testimonial[] | - | レンダリングする項目の配列。 |
className | string | - | ルート要素にマージされる追加クラス。 |
ariaLabel | string | 'Testimonials' | ボタンのアクセシブルな名前。アイコンのみのボタンでは必須です。 |
Each slide is a `figure`/`blockquote` with a gradient avatar built from the author's initials, so there is nothing to host. Slides page with a transform and the avatar tile is `aria-hidden` because the name is already real text.