Rotating sequence of content panels.
<div class="carousel carousel--slide" style="--accent:#E8A020;">
<input class="carousel__radio" type="radio" name="carousel-slide" id="carousel-s1" checked />
<input class="carousel__radio" type="radio" name="carousel-slide" id="carousel-s2" />
<input class="carousel__radio" type="radio" name="carousel-slide" id="carousel-s3" />
<div class="carousel__viewport" style="border-radius:12px;">
<div class="carousel__track">
<figure class="carousel__slide" aria-hidden="true">
<svg viewBox="0 0 400 240" width="100%" height="100%"><rect width="400" height="240" fill="#A8E6C1"/><circle cx="200" cy="120" r="60" fill="#FAF7F2"/></svg>
</figure>
<figure class="carousel__slide" aria-hidden="true">
<svg viewBox="0 0 400 240" width="100%" height="100%"><rect width="400" height="240" fill="#BFD9F2"/><circle cx="200" cy="120" r="60" fill="#FAF7F2"/></svg>
</figure>
<figure class="carousel__slide" aria-hidden="true">
<svg viewBox="0 0 400 240" width="100%" height="100%"><rect width="400" height="240" fill="#F5C2E0"/><circle cx="200" cy="120" r="60" fill="#FAF7F2"/></svg>
</figure>
</div>
<div class="carousel__arrows">
<label class="carousel__arrow carousel__arrow--prev carousel__arrow--for-1" for="carousel-s3" aria-label="Previous slide">‹</label>
<label class="carousel__arrow carousel__arrow--next carousel__arrow--for-1" for="carousel-s2" aria-label="Next slide">›</label>
<label class="carousel__arrow carousel__arrow--prev carousel__arrow--for-2" for="carousel-s1" aria-label="Previous slide">‹</label>
<label class="carousel__arrow carousel__arrow--next carousel__arrow--for-2" for="carousel-s3" aria-label="Next slide">›</label>
<label class="carousel__arrow carousel__arrow--prev carousel__arrow--for-3" for="carousel-s2" aria-label="Previous slide">‹</label>
<label class="carousel__arrow carousel__arrow--next carousel__arrow--for-3" for="carousel-s1" aria-label="Next slide">›</label>
</div>
</div>
<div class="carousel__dots">
<label class="carousel__dot" for="carousel-s1" aria-label="Go to slide 1"></label>
<label class="carousel__dot" for="carousel-s2" aria-label="Go to slide 2"></label>
<label class="carousel__dot" for="carousel-s3" aria-label="Go to slide 3"></label>
</div>
</div>
<style>
.carousel { max-width: 360px; font: 13px/1.4 system-ui, sans-serif; color: #241430; }
.carousel__radio { position: absolute; opacity: 0; width: 1px; height: 1px; overflow: hidden; }
.carousel__viewport { position: relative; overflow: hidden; border: 1px solid #24143022; background: #FAF7F2; }
.carousel__track { display: flex; width: 300%; }
@media (prefers-reduced-motion: no-preference) {
.carousel__track { transition: transform .2s ease; }
}
.carousel__slide { flex: 0 0 33.333%; margin: 0; aspect-ratio: 5 / 3; }
.carousel__slide svg { display: block; width: 100%; height: 100%; }
#carousel-s1:checked ~ .carousel__viewport .carousel__track { transform: translateX(0%); }
#carousel-s2:checked ~ .carousel__viewport .carousel__track { transform: translateX(-33.333%); }
#carousel-s3:checked ~ .carousel__viewport .carousel__track { transform: translateX(-66.666%); }
.carousel--fade .carousel__track { width: 100%; transform: none !important; position: relative; }
.carousel--fade .carousel__slide { position: absolute; inset: 0; flex-basis: 100%; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
.carousel--fade .carousel__slide { transition: opacity .2s ease; }
}
.carousel--fade #carousel-s1:checked ~ .carousel__viewport .carousel__slide:nth-child(1) { opacity: 1; }
.carousel--fade #carousel-s2:checked ~ .carousel__viewport .carousel__slide:nth-child(2) { opacity: 1; }
.carousel--fade #carousel-s3:checked ~ .carousel__viewport .carousel__slide:nth-child(3) { opacity: 1; }
.carousel__arrows { position: absolute; inset: 0; display: flex; align-items: center; justify-content: space-between; padding: 0 8px; pointer-events: none; }
.carousel__arrow { pointer-events: auto; display: none; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: #FAF7F2cc; color: #241430; cursor: pointer; font-size: 16px; line-height: 1; text-decoration: none; }
.carousel__arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#carousel-s1:checked ~ .carousel__viewport .carousel__arrow--for-1 { display: flex; }
#carousel-s2:checked ~ .carousel__viewport .carousel__arrow--for-2 { display: flex; }
#carousel-s3:checked ~ .carousel__viewport .carousel__arrow--for-3 { display: flex; }
.carousel__dots { display: flex; gap: 6px; justify-content: center; margin-top: 10px; }
.carousel__dot { display: block; width: 8px; height: 8px; border-radius: 50%; background: #24143033; cursor: pointer; }
.carousel__dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#carousel-s1:checked ~ .carousel__dots label:nth-of-type(1) { background: var(--accent); }
#carousel-s2:checked ~ .carousel__dots label:nth-of-type(2) { background: var(--accent); }
#carousel-s3:checked ~ .carousel__dots label:nth-of-type(3) { background: var(--accent); }
</style><div class="carousel-tw max-w-[360px] font-sans text-[13px] text-[#241430]" data-transition="slide" style="--accent:#E8A020;">
<input class="carousel-tw__radio" type="radio" name="carousel-tw-slide" id="carousel-tw-s1" checked />
<input class="carousel-tw__radio" type="radio" name="carousel-tw-slide" id="carousel-tw-s2" />
<input class="carousel-tw__radio" type="radio" name="carousel-tw-slide" id="carousel-tw-s3" />
<div class="carousel-tw__viewport relative overflow-hidden border border-[#24143022] bg-[#FAF7F2]" style="border-radius:12px;">
<div class="carousel-tw__track flex w-[300%] motion-safe:transition-transform motion-safe:duration-300">
<figure class="carousel-tw__slide m-0" style="flex:0 0 33.333%;aspect-ratio:5/3;" aria-hidden="true">
<svg viewBox="0 0 400 240" width="100%" height="100%" class="block w-full h-full"><rect width="400" height="240" fill="#A8E6C1"/><circle cx="200" cy="120" r="60" fill="#FAF7F2"/></svg>
</figure>
<figure class="carousel-tw__slide m-0" style="flex:0 0 33.333%;aspect-ratio:5/3;" aria-hidden="true">
<svg viewBox="0 0 400 240" width="100%" height="100%" class="block w-full h-full"><rect width="400" height="240" fill="#BFD9F2"/><circle cx="200" cy="120" r="60" fill="#FAF7F2"/></svg>
</figure>
<figure class="carousel-tw__slide m-0" style="flex:0 0 33.333%;aspect-ratio:5/3;" aria-hidden="true">
<svg viewBox="0 0 400 240" width="100%" height="100%" class="block w-full h-full"><rect width="400" height="240" fill="#F5C2E0"/><circle cx="200" cy="120" r="60" fill="#FAF7F2"/></svg>
</figure>
</div>
<div class="carousel-tw__arrows absolute inset-0 flex items-center justify-between px-2" style="pointer-events:none;">
<label class="carousel-tw__arrow carousel-tw__arrow--for-1 w-7 h-7 rounded-full items-center justify-center bg-[#FAF7F2]/80 text-[#241430] cursor-pointer" style="pointer-events:auto;" for="carousel-tw-s3" aria-label="Previous slide">‹</label>
<label class="carousel-tw__arrow carousel-tw__arrow--for-1 w-7 h-7 rounded-full items-center justify-center bg-[#FAF7F2]/80 text-[#241430] cursor-pointer" style="pointer-events:auto;" for="carousel-tw-s2" aria-label="Next slide">›</label>
<label class="carousel-tw__arrow carousel-tw__arrow--for-2 w-7 h-7 rounded-full items-center justify-center bg-[#FAF7F2]/80 text-[#241430] cursor-pointer" style="pointer-events:auto;" for="carousel-tw-s1" aria-label="Previous slide">‹</label>
<label class="carousel-tw__arrow carousel-tw__arrow--for-2 w-7 h-7 rounded-full items-center justify-center bg-[#FAF7F2]/80 text-[#241430] cursor-pointer" style="pointer-events:auto;" for="carousel-tw-s3" aria-label="Next slide">›</label>
<label class="carousel-tw__arrow carousel-tw__arrow--for-3 w-7 h-7 rounded-full items-center justify-center bg-[#FAF7F2]/80 text-[#241430] cursor-pointer" style="pointer-events:auto;" for="carousel-tw-s2" aria-label="Previous slide">‹</label>
<label class="carousel-tw__arrow carousel-tw__arrow--for-3 w-7 h-7 rounded-full items-center justify-center bg-[#FAF7F2]/80 text-[#241430] cursor-pointer" style="pointer-events:auto;" for="carousel-tw-s1" aria-label="Next slide">›</label>
</div>
</div>
<div class="carousel-tw__dots flex gap-1.5 justify-center mt-2.5">
<label class="carousel-tw__dot block w-2 h-2 rounded-full bg-[#24143033] cursor-pointer" for="carousel-tw-s1" aria-label="Go to slide 1"></label>
<label class="carousel-tw__dot block w-2 h-2 rounded-full bg-[#24143033] cursor-pointer" for="carousel-tw-s2" aria-label="Go to slide 2"></label>
<label class="carousel-tw__dot block w-2 h-2 rounded-full bg-[#24143033] cursor-pointer" for="carousel-tw-s3" aria-label="Go to slide 3"></label>
</div>
</div>
<style>
.carousel-tw__radio { position: absolute; opacity: 0; width: 1px; height: 1px; overflow: hidden; }
#carousel-tw-s1:checked ~ .carousel-tw__viewport .carousel-tw__track { transform: translateX(0%); }
#carousel-tw-s2:checked ~ .carousel-tw__viewport .carousel-tw__track { transform: translateX(-33.333%); }
#carousel-tw-s3:checked ~ .carousel-tw__viewport .carousel-tw__track { transform: translateX(-66.666%); }
[data-transition="fade"] .carousel-tw__track { width: 100%; transform: none !important; position: relative; }
[data-transition="fade"] .carousel-tw__slide { position: absolute; inset: 0; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
[data-transition="fade"] .carousel-tw__slide { transition: opacity .2s ease; }
}
[data-transition="fade"] #carousel-tw-s1:checked ~ .carousel-tw__viewport .carousel-tw__slide:nth-child(1) { opacity: 1; }
[data-transition="fade"] #carousel-tw-s2:checked ~ .carousel-tw__viewport .carousel-tw__slide:nth-child(2) { opacity: 1; }
[data-transition="fade"] #carousel-tw-s3:checked ~ .carousel-tw__viewport .carousel-tw__slide:nth-child(3) { opacity: 1; }
.carousel-tw__arrow { display: none; }
.carousel-tw__arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#carousel-tw-s1:checked ~ .carousel-tw__viewport .carousel-tw__arrow--for-1 { display: flex; }
#carousel-tw-s2:checked ~ .carousel-tw__viewport .carousel-tw__arrow--for-2 { display: flex; }
#carousel-tw-s3:checked ~ .carousel-tw__viewport .carousel-tw__arrow--for-3 { display: flex; }
.carousel-tw__dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#carousel-tw-s1:checked ~ .carousel-tw__dots label:nth-of-type(1) { background: var(--accent); }
#carousel-tw-s2:checked ~ .carousel-tw__dots label:nth-of-type(2) { background: var(--accent); }
#carousel-tw-s3:checked ~ .carousel-tw__dots label:nth-of-type(3) { background: var(--accent); }
</style>export function Carousel({
transition = "slide",
accent = "#E8A020",
showArrows = true,
radius = 12,
}) {
const fills = ["#A8E6C1", "#BFD9F2", "#F5C2E0"];
return (
<div className={`carousel-rc carousel-rc--${transition}`} style={{ maxWidth: 360, font: "13px/1.4 system-ui, sans-serif", color: "#241430", "--accent": accent }}>
<input className="carousel-rc__radio" type="radio" name="carousel-rc-slide" id="carousel-rc-s1" defaultChecked />
<input className="carousel-rc__radio" type="radio" name="carousel-rc-slide" id="carousel-rc-s2" />
<input className="carousel-rc__radio" type="radio" name="carousel-rc-slide" id="carousel-rc-s3" />
<div className="carousel-rc__viewport" style={{ position: "relative", overflow: "hidden", border: "1px solid #24143022", background: "#FAF7F2", borderRadius: radius }}>
<div className="carousel-rc__track" style={{ display: "flex", width: "300%" }}>
{fills.map((fill, i) => (
<figure key={i} className="carousel-rc__slide" style={{ flex: "0 0 33.333%", margin: 0, aspectRatio: "5 / 3" }} aria-hidden="true">
<svg viewBox="0 0 400 240" width="100%" height="100%" style={{ display: "block" }}><rect width="400" height="240" fill={fill} /><circle cx="200" cy="120" r="60" fill="#FAF7F2" /></svg>
</figure>
))}
</div>
{showArrows && (
<div className="carousel-rc__arrows" style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "space-between", padding: "0 8px", pointerEvents: "none" }}>
<label className="carousel-rc__arrow carousel-rc__arrow--for-1" htmlFor="carousel-rc-s3" aria-label="Previous slide">‹</label>
<label className="carousel-rc__arrow carousel-rc__arrow--for-1" htmlFor="carousel-rc-s2" aria-label="Next slide">›</label>
<label className="carousel-rc__arrow carousel-rc__arrow--for-2" htmlFor="carousel-rc-s1" aria-label="Previous slide">‹</label>
<label className="carousel-rc__arrow carousel-rc__arrow--for-2" htmlFor="carousel-rc-s3" aria-label="Next slide">›</label>
<label className="carousel-rc__arrow carousel-rc__arrow--for-3" htmlFor="carousel-rc-s2" aria-label="Previous slide">‹</label>
<label className="carousel-rc__arrow carousel-rc__arrow--for-3" htmlFor="carousel-rc-s1" aria-label="Next slide">›</label>
</div>
)}
</div>
<div className="carousel-rc__dots" style={{ display: "flex", gap: 6, justifyContent: "center", marginTop: 10 }}>
<label className="carousel-rc__dot" htmlFor="carousel-rc-s1" aria-label="Go to slide 1" />
<label className="carousel-rc__dot" htmlFor="carousel-rc-s2" aria-label="Go to slide 2" />
<label className="carousel-rc__dot" htmlFor="carousel-rc-s3" aria-label="Go to slide 3" />
</div>
<style>{`
.carousel-rc__radio { position: absolute; opacity: 0; width: 1px; height: 1px; overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
.carousel-rc__track { transition: transform .2s ease; }
}
#carousel-rc-s1:checked ~ .carousel-rc__viewport .carousel-rc__track { transform: translateX(0%); }
#carousel-rc-s2:checked ~ .carousel-rc__viewport .carousel-rc__track { transform: translateX(-33.333%); }
#carousel-rc-s3:checked ~ .carousel-rc__viewport .carousel-rc__track { transform: translateX(-66.666%); }
.carousel-rc--fade .carousel-rc__track { width: 100%; transform: none !important; position: relative; }
.carousel-rc--fade .carousel-rc__slide { position: absolute; inset: 0; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
.carousel-rc--fade .carousel-rc__slide { transition: opacity .2s ease; }
}
.carousel-rc--fade #carousel-rc-s1:checked ~ .carousel-rc__viewport .carousel-rc__slide:nth-child(1) { opacity: 1; }
.carousel-rc--fade #carousel-rc-s2:checked ~ .carousel-rc__viewport .carousel-rc__slide:nth-child(2) { opacity: 1; }
.carousel-rc--fade #carousel-rc-s3:checked ~ .carousel-rc__viewport .carousel-rc__slide:nth-child(3) { opacity: 1; }
.carousel-rc__arrow { display: none; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: #FAF7F2cc; color: #241430; cursor: pointer; font-size: 16px; line-height: 1; text-decoration: none; pointer-events: auto; }
.carousel-rc__arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#carousel-rc-s1:checked ~ .carousel-rc__viewport .carousel-rc__arrow--for-1 { display: flex; }
#carousel-rc-s2:checked ~ .carousel-rc__viewport .carousel-rc__arrow--for-2 { display: flex; }
#carousel-rc-s3:checked ~ .carousel-rc__viewport .carousel-rc__arrow--for-3 { display: flex; }
.carousel-rc__dot { display: block; width: 8px; height: 8px; border-radius: 50%; background: #24143033; cursor: pointer; }
.carousel-rc__dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#carousel-rc-s1:checked ~ .carousel-rc__dots label:nth-of-type(1) { background: var(--accent); }
#carousel-rc-s2:checked ~ .carousel-rc__dots label:nth-of-type(2) { background: var(--accent); }
#carousel-rc-s3:checked ~ .carousel-rc__dots label:nth-of-type(3) { background: var(--accent); }
`}</style>
</div>
);
}