In the previous section we focused on
how to fetch data from an API.
How to refresh the data using
Incremental Static Regeneration, and so on.
In this section we'll focus more
on the user interface.
In our HomePage at the moment we're displaying
a very basic list of products.
So let's start by designing a nicer HomePage.
For each product we currently display
a simple text link.
But I'd like to have a product card instead,
showing not just the product name
but also an image and the price.
So what I'm going to do is
extract this code into its own component,
called "ProductCard".
And this will be a typical
React function component.
It will render the same code
we had in the HomePage.
Let's not forget to export
the component function as "default".
We also need to import the "Link" component.
Since we're displaying the product properties,
we'll need to the "product" in the props.
At this point we can replace the old code
with the new "ProductCard" component,
which expects a "product" prop
so let's pass that value.
Ok. As things stand
the page will look the same as before,
because we just moved some code around.
But now we can go and add
some styling to this ProductCard.
Let's start by adding a "border",
so we can also see
how much space each ProductCard takes.
Next, I mentioned I would like to show an image.
To start with I'm going to use
a placeholder from "dummyimage.com".
We can specify the dimensions in the URL,
like "320x240".
Each "img" element requires
an "alt" attribute for accessibility,
but in this case I think we can leave it empty,
because this image will represent the product,
and we're already displaying
the "product.title" below,
so if somebody is browsing our website
using a screen reader
the "product.title" already describes
what this link is about.
Now, if you have ESLint enabled
you may see an error on this line,
saying something like "don't use ".
Just ignore it and continue anyway,
it's only a suggestion from the Next.js rules.
We'll make it go away later in this section.
Anyway, if we save this,
we can now see the placeholder images.
We could do with some spacing
between each product card.
Let's add some margin on the Y axis,
and this looks a bit better.
However there is some blank space on the right
that doesn't look so great.
Let's set an explicit "width" for each ProductCard.
"w-80" in Tailwind is effectively 320 pixels.
This way each card should be
as wide as the picture. Good.
Now, let's style the product title.
I'll add a "div", so we can group together
everything that goes below the image.
And the title could be an "h2" heading.
Let me move the "product.title" inside.
I'm using an "h2" to help search engines
understand that each product
is like a different section of our website.
Now, let's add some spacing around the text.
We could use some padding, say "p-2".
And we could also make the title text
a bit more visible,
by setting "text-lg",
and maybe also "font-bold".
Ok, that looks fine.
Next, we want to display the price for each product,
so let's add a "span",
and here we'll show the price,
for example 15 dollars.
But we don't want the price to be below the title,
we'd like it to be on the right side.
So let's change this "div" to use Flexbox.
This displays all the elements inside it
on the same row.
Now we can use "justify-between"
to add all the space between those two elements.
It seems that the price is showing
a bit higher than the title.
So let's also add "items-baseline"
that should align them vertically.
Ok, I think that's looking good.
What we should do now
is display the real price
rather than a hard-coded value.
And for that we'll need to modify
the function where we fetch the product data.
We just need to add the "price"
to the fields that we pass through,
because the CMS does return that property.
And now in the ProductCard
we should be able to display that "product.price".
Ok, it's showing the price,
but it's a plain number.
We should really display it as a monetary amount.
Just to do it quickly,
I'll prepend a dollar sign here,
and also always show 2 decimal places.
Just to be clear, this is not the best way
to format currencies.
A better approach would be to use
the Internationalization API.
But this works for this simple example.
We can see the prices formatted as dollar amounts.
Now, I'd like to make some final tweaks
to the card appearance.
Tailwind includes a "shadow" class
that will show a little shadow on each box,
so each card appears to be slightly raised.
I'm also going to show a different shadow
for the "hover" state.
In this case we can use a "shadow-xl",
or extra-large.
This way when we move the mouse over a card
it will give the impression
of raising itself a bit more.
Ok. I think that's enough for now.
Later on we'll obviously show
the real product images as well.
But this is a nice little ProductCard,
styled up using Tailwind CSS.