<div id="root"></div>
html {
  overflow: scroll;
}
import React, {
  useEffect,
  useState
} from "https://cdn.skypack.dev/react@17.0.1";
import ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";
import {
  motion,
  useAnimation
} from "https://cdn.skypack.dev/framer-motion@4.1.17";

const images = [
  "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8ZmFjZXxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60",
  "https://images.unsplash.com/photo-1592124549776-a7f0cc973b24?ixid=MnwxMjA3fDB8MHxzZWFyY2h8NXx8ZmFjZXxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60",
  "https://images.unsplash.com/photo-1557296387-5358ad7997bb?ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8ZmFjZXxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60",
  "https://images.unsplash.com/photo-1521146764736-56c929d59c83?ixid=MnwxMjA3fDB8MHxzZWFyY2h8OHx8ZmFjZXxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60",
  "https://images.unsplash.com/photo-1593529467220-9d721ceb9a78?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTV8fGZhY2V8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60",
  "https://images.unsplash.com/photo-1544348817-5f2cf14b88c8?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MjB8fGZhY2V8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60",
  "https://images.unsplash.com/photo-1596215143922-eedeaba0d91c?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MzR8fGZhY2V8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60",
  "https://images.unsplash.com/photo-1560787313-5dff3307e257?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mjd8fGZhY2V8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=60"
];

const Accordion = ({ children, expanded }) => {
  const controls = useAnimation();

  const variants = {
    expanded: { opacity: 1, height: "auto" },
    collapsed: { opacity: 0, height: 0 }
  };

  useEffect(() => {
    if (expanded) {
      controls.start("expanded");
    } else {
      controls.start("collapsed");
    }
  }, [expanded]);

  return (
    <motion.div
      initial="collapsed"
      className="z-0 overflow-hidden"
      animate={controls}
      transition={{ duration: 0.3 }}
      variants={variants}
    >
      {children}
    </motion.div>
  );
};

const Trigger = ({ expanded, onClick, showLabel, hideLabel }) => {
  return (
    <button
      onClick={onClick}
      className="rounded-md bg-stone-400 text-white font-sans p-4 text-center my-2 uppercase focus:outline-none"
    >
      {expanded ? hideLabel ?? showLabel : showLabel}
    </button>
  );
};

Accordion.Trigger = Trigger;

const Example = () => {
  const [expanded, setExpanded] = useState(false);
  return (
    <div className="max-w-screen-xl mx-auto flex flex-col items-center">
      <Accordion.Trigger
        onClick={() => setExpanded((prevExpanded) => !prevExpanded)}
        expanded={expanded}
        showLabel="Show Content"
        hideLabel="Hide Content"
      />
      <Accordion expanded={expanded}>
        <div className="grid grid-cols-4">
          {images.map((image, index) => (
            <img
              alt=""
              key={index}
              className="w-full h-full object-cover"
              src={image}
            />
          ))}
        </div>
      </Accordion>
    </div>
  );
};

ReactDOM.render(<Example />, document.getElementById("root"));
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.tailwindcss.com