What you'll learn:
Card
componentCard
style
attributeCard
componentWe’ve got a swipeable card so far. Let’s now make a deck of cards!
As review, we’ll start by extracting the code into a Card
component so that we can easily reuse it. Do you remember how to do it?
function Card(){
return ...
}
We first create a capitalized function and place a return
inside. We can either have the tags to be return on the same line as the return
or the return
must have parentheses that enclose the tags.
Card
Let's copy our big <Frame/>
tag and move it to our Card
component.
function Card(){
return (
<Frame
center
drag="x"
x={mv}
rotate={rotateMv}
opacity={opacityMv}
dragConstraints={{ left: -200, right: 200 }}
style={style}
animate={animControls}
onDragEnd={function(_, info) {
if (Math.abs(info.point.x) < 150) {
animControls.start({ x: 0 })
} else {
animControls.start({ x: info.point.x < 0 ? -200 : 200 })
}
}}
/>
)
}
Lot's of errors will be shown since we also have to move all our required variables: mv
, animControls
, rotateMv
, and opacityMv
.
function Card(){
let mv = useMotionValue(0)
let animControls = useAnimation()
let rotateMv = useTransform(mv, [-200, 200], [-50, 50])
let opacityMv = useTransform(mv, [-200, -150, 0, 150, 200], [0, 1, 1, 1, 0])
return (
...
)
}
We can now create the <Card />
tag inside our App
div
.
function App() {
return (
<div className="App">
<Card />
</div>
)
}
The reason for extracting the component is that it gives us the ability for to re-use and create multiple cards. Therefore, let's add more Cards!
function App() {
return (
<div className="App">
<Card />
<Card />
<Card />
<Card />
</div>
)
}
We now have multiple cards behind each other, but we need to display a few different cards, with different images and background colors.
Typically, we can add different attributes to each card.
function App() {
return (
<div className="App">
<Card image="https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fbird_fat_black_medium.svg?v=1557968629951" color="#FF88AA" />
<Card />
<Card />
<Card />
</div>
)
}
However, we got an error here because we haven’t told the Card
component what to do with these props. As a result, we have to add the props
parameter to Card
.
function Card(props){
...
}
We could use the convenient Frame props such as image
and backgroundColor
.
function Card(props){
return (
<Frame
...
style={style}
image={props.image}
backgroundColor={props.backgroundColor}
/>
)
}
But just for a change and since we’ve already been using the style
attribute, let’s simply update our style
attribute.
style
attributeCurrently, the style
variable is defined outside, so we need to move it inside the Card
function so that we could make it dynamic with our props
parameter.
function Card(props){
...
const style = {
backgroundImage: "url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fbird_strong_small.svg?v=1560032432704)",
backgroundRepeat: "no-repeat",
backgroundSize: "contain",
backgroundPosition: "center",
backgroundColor: "#55CCFF",
boxShadow: "2px 2px 10px 0 rgba(0,0,0,0.25)",
borderRadius: 10,
height: 300
}
return (
<Frame
...
style={style}
/>
)
}
We have to move style
inside Card
because we can't see things inside a room from outside. Therefore, we have to enter the room.
We can make backgroundColor
dynamic quite easily, but image url will take some more effort.
function Card(props){
...
const style = {
backgroundImage: "url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fbird_strong_small.svg?v=1560032432704)",
backgroundRepeat: "no-repeat",
backgroundSize: "contain",
backgroundPosition: "center",
backgroundColor: props.color,
boxShadow: "2px 2px 10px 0 rgba(0,0,0,0.25)",
borderRadius: 10,
height: 300
}
...
}
For the image, we want to replace the URL in the string, but we have to keep the url(...)
surrounding our image link. Unfortunately, this is just the format enforced by CSS when setting the background image.
backgroundImage
dynamicThere are 2 ways we can fix make our url link dynamic.
function Card(props){
...
const style = {
backgroundImage: "url("+props.image+")",
backgroundRepeat: "no-repeat",
backgroundSize: "contain",
backgroundPosition: "center",
backgroundColor: props.color,
boxShadow: "2px 2px 10px 0 rgba(0,0,0,0.25)",
borderRadius: 10,
height: 300
}
...
}
"url("+props.image+")"
concatenates three strings and we get one final string.
Another, preferred, method is called template string. Instead of quotes surrounding our strings, we use a backtick which is the key on the top left of your keyboard. The plus +
is removed and we surround what we want, props.image
with ${...}
to make it dynamic.
function Card(props){
...
const style = {
backgroundImage: `url(${props.image})`,
backgroundRepeat: "no-repeat",
backgroundSize: "contain",
backgroundPosition: "center",
backgroundColor: props.color,
boxShadow: "2px 2px 10px 0 rgba(0,0,0,0.25)",
borderRadius: 10,
height: 300
}
...
}
This is similar to using the curly brackets in JSX to make something dynamic, but there is a dollar sign in the front. Both methods will execute our code inside and put the result back into the string, but this method looks nicer.
Now that we have multiple cards that can be customized, in the next post, we'll make our code robust so that it won't be repetitive if we need 100 cards!