TailwindCSS Text Carousel
The title speaks volumes.
import React, { useEffect, useState } from 'react';
import { useSwipeable } from 'react-swipeable';
import caret from '../images/caret-down.svg';
import { renderRichText } from 'gatsby-source-contentful/rich-text';
import { useStaticQuery, graphql } from 'gatsby';
const TailwindTextCarousel = () => {
const [activeIndex, setActiveIndex] = useState(0);
const [paused, setPaused] = useState(true);
const data = useStaticQuery(graphql`
// ENTER YOUR QUERY HERE
`);
const textItems = data.queryStuff;
const updateIndex = (newIndex) => {
if (newIndex < 0) {
newIndex = textItems.length - 1;
} else if (newIndex >= textItems.length) {
newIndex = 0;
}
setActiveIndex(newIndex);
};
useEffect(() => {
const interval = setInterval(() => {
if (!paused) {
updateIndex(activeIndex + 1);
}
}, 300000);
return () => {
if (interval) {
clearInterval(interval);
}
};
});
const handlers = useSwipeable({
onSwipedLeft: () => updateIndex(activeIndex + 1),
onSwipedRight: () => updateIndex(activeIndex - 1),
});
return (
<div className="flex flex-col py-24 text-white">
<div
{...handlers}
className="width-wrapper relative overflow-hidden"
onMouseEnter={() => setPaused(true)}
onMouseLeave={() => setPaused(false)}
>
<ul
className="whitespace-nowrap transition-transform duration-[0.3s]"
style={{ transform: `translateX(-${activeIndex * 100}%)` }}
>
{textItems.map((testimonial, idx) => (
<li
className="z-10 inline-flex w-full items-center justify-center text-center "
key={idx}
>
<blockquote className="flex flex-col items-center gap-[4.625rem] whitespace-nowrap px-24 sm:px-8">
<div className="max-w-[66rem] whitespace-normal font-transducer">
{renderRichText(testimonial.quote)}
</div>
<cite className="text-center sm:text-xl">{`- ${testimonial.cite}`}</cite>
</blockquote>
</li>
))}
</ul>
{textItems.length > 1 && (
<>
<button
className="absolute top-[5rem] left-[5%] rotate-90 cursor-pointer rounded-none p-0 opacity-70 "
onClick={() => {
updateIndex(activeIndex - 1);
}}
>
<img src={caret} alt="previous slide" />
</button>
<button
className="absolute top-[5rem] right-[5%] -rotate-90 cursor-pointer rounded-none p-0 opacity-70 "
onClick={() => {
updateIndex(activeIndex + 1);
}}
>
<img src={caret} alt="next slide" />
</button>{' '}
</>
)}
</div>
</div>
);
};
export default TailwindTextCarousel;