I have a grid of 'cards' displaying games that when clicked expand down to show more information however when I click on one ALL of the cards expand open and I'm wanting only one to expand at a time.
Here is a codesandbox of what I have so far. Thanks for any help!
CodePudding user response:
Here's working component. The component state must reflect currently open card or null if no card is open.
Also changed class
to className
since it's the proper way to set component class from CSS
export const GameCard = () => {
const [openedCard, setOpenedCard] = useState(null);
return (
<div id="card_wrapper">
{games.map((game) => (
<motion.div
transition={{ layout: { duration: 1, type: "spring" } }}
layout
onClick={() => setOpenedCard(game.id)}
key={game.id}
className="card"
name={game.name}
style={{
backgroundImage: `url(${game.background})`,
backgroundSize: "cover",
backgroundRepeat: "no-repeat"
}}
>
<motion.h2 layout="position">
{" "}
<img src={game.logo} alt={game.alt} />
</motion.h2>
{openedCard === game.id && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1 }}
className="expand"
>
<p> {game.description} </p>
</motion.div>
)}
</motion.div>
))}
</div>
);
};
CodePudding user response:
try this :
// add new state to capture the index of the clicked element :
const [elementId, setElementId] = useState(null);
and in the return part capture the clicked index inside the onClick :
return (
<div id="card_wrapper">
{games.map((game) => (
<motion.div
transition={{ layout: { duration: 1, type: "spring" } }}
layout
onClick={() => {
setIsOpen(!isOpen);
setElementId(game.id);
}}
...)
and finally render motion only when (isOpen) and (game.id === elementId) :
{isOpen && game.id === elementId && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1 }}
>
full sandbox example : here