The goal is that we can swipe the cards up and down, and they will cycle back and forth. We'll use framer/motion to control the animations and typescrypt to keep things tidy. This is what we are building:
Let's get started
First, we need to install the dependencies. Run the following command in an existing react project:
Now, let's create a new file called swipeable-deck.tsx and add the following code:
There we have the basic structure of our component. We have a Card type with an id and content (notice I used ReactNode instead of string so that we can use components if we want to). We also have our SwipeableDeck component that receives a deck prop which is an array of Card objects and an optional className.
Now let's add some basic markup to our component:
We will also need some styles. Create a new file called swipeable-deck.css and add the following code:
Then import the styles into our component:
Let's add some cards
Now let's create a new file called index.tsx and add the following code:
How it looks so far
If you run your project, you should see a deck of cards stacked on top of each other. Now let's add the swipe functionality.
Enter framer-motion
First, let's add the motion component to our cards. Replace the li tag in the SwipeableDeck component with a motion.li tag.
Then we need to add the swipe functionality. We will use the drag property of the motion component to enable dragging on the y-axis and define an animation using the animate property. We will also add a dragConstraints property to limit the dragging to the y-axis.
Still not swiping
If you run your project now, you will see that the first card is draggable, but it doesn't move back to the bottom of the deck. To fix this, we need to add some logic to handle the dragging.
Handling swipes
We will add an onDragEnd event handler to the motion.li component. This handler will check if the card was dragged past a certain threshold and if so, it will move the card to the bottom of the deck.
For framer to animate the change, we need to change the order of the cards in the deck. For that we will introduce a new cards state variable and a move function to move the cards around.
Here's the final code:
We added a generic move function that moves array elements between specific indexes. We also added a moveToEnd function that moves the card to the end of the deck and hooked it up to the onDragEnd event handler.
To decide whether to move the card to the end of the deck or back to the top, we check the offset.y property of the info object passed to the onDragEnd event handler. If the offset.y is negative, we move the card to the end of the deck, otherwise, we move it back to the top.
Finally working
Customizing the deck
Remember we can pass React components as Cards? Let's give it a try by creating a new component called PokerCard in our index.tsx file.
And let's update our cards array to use the PokerCard component.
Finally let's create some styles for our PokerCard component.
And that's it! You can now run your project and see the PokerCard component in action.
Bonus
With a few more tweaks you can make a credit card stack as well. Here's an example: