The source code for this library is available on GitHub.

Vaiva's Pattern Library.

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;

More Components

Button

There is no description. Have a poem instead.

When I heard the learn’d astronomer,
When the proofs, the figures, were ranged in columns before me,
When I was shown the charts and diagrams, to add, divide, and measure them,
When I sitting heard the astronomer where he lectured with much applause in the lecture-room,
How soon unaccountable I became tired and sick,
Till rising and gliding out I wander’d off by myself,
In the mystical moist night-air, and from time to time,
Look’d up in perfect silence at the stars.

useClickOutside Hook

Clicking outside a referential element will close it. This hook is useful for dropdowns, modals, etc. To use it you must import useRef and create a variable named 'wrapperRef' with a value of 'useRef(null)'. You then attach 'ref={wrapperRef} to the element you'd like the user to click outside of. To close the element, create a 'closeInput' function sets state to the desired value.