React for Designers and PMs
Coffee cards grid
A React component that displays a grid of gift cards by mapping over an array of objects.
LLM Written
Human Reviewed
Output
Starbucks
A 'Giftzy Latte'
NewOne venti Caffe Latte and one Double Chocolate Brownie from Starbucks.
$11.07
Cold Stone
Berry Good Combo
A medium Berry Berry Berry Good ice cream with waffle cone and topping.
$8.49
The Cheesecake Factory
Slice of Heaven
NewOne slice of Original Cheesecake with a fresh strawberry topping.
$9.95
Crumbl
Cookie Party Box
A four-pack of weekly rotating flavors from Crumbl Cookies.
$15.99
Dunkin'
Morning Kickstart
NewA medium iced coffee and a bacon egg & cheese on a croissant.
$7.89
Nothing Bundt Cakes
Bundtlet Duo
Two personal-sized bundtlets in your choice of classic flavors.
$12.50
File Structure
├── src
` `├── App.tsx `← we are here`
` `├── index.css
` `└── main.tsxDistraction free code
const [cards, setCards] = useState([
{ icon: Coffee, header: 'Starbucks', title: "A 'Giftzy Latte'", ... },
{ icon: IceCreamCone, header: 'Cold Stone', title: "Berry Good Combo", ... },
...
]);
{/*Grid*/}
<div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4'>
{cards.map((card, index) => (
<div key={index}>
{/*Header*/}
<card.icon />
<span>{card.header}</span>
<Star />
{/*Body*/}
<h2>{card.title}</h2>
{card.isNew && <span>New</span>}
<p>{card.description}</p>
{/*Footer*/}
<span>{card.price}</span>
<button><Info /></button>
<button>Details</button>
</div>
))}
</div>Code
'use client';
import { Coffee, Star, Info, IceCreamCone, Cake, Cookie } from 'lucide-react';
import { useState } from 'react';
export default function Home() {
const [cards, setCards] = useState([
{
icon: Coffee,
header: 'Starbucks',
title: "A 'Giftzy Latte'",
description: 'One venti Caffe Latte and one Double Chocolate Brownie from Starbucks.',
price: '$11.07',
isNew: true,
},
{
icon: IceCreamCone,
header: 'Cold Stone',
title: 'Berry Good Combo',
description: 'A medium Berry Berry Berry Good ice cream with waffle cone and topping.',
price: '$8.49',
isNew: false,
},
{
icon: Cake,
header: 'The Cheesecake Factory',
title: 'Slice of Heaven',
description: 'One slice of Original Cheesecake with a fresh strawberry topping.',
price: '$9.95',
isNew: true,
},
{
icon: Cookie,
header: 'Crumbl',
title: 'Cookie Party Box',
description: 'A four-pack of weekly rotating flavors from Crumbl Cookies.',
price: '$15.99',
isNew: false,
},
{
icon: Coffee,
header: "Dunkin'",
title: 'Morning Kickstart',
description: 'A medium iced coffee and a bacon egg & cheese on a croissant.',
price: '$7.89',
isNew: true,
},
{
icon: Cake,
header: 'Nothing Bundt Cakes',
title: 'Bundtlet Duo',
description: 'Two personal-sized bundtlets in your choice of classic flavors.',
price: '$12.50',
isNew: false,
},
]);
return (
<div className='py-4 bg-gray-200 min-h-screen p-4'>
<div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 max-w-5xl mx-auto'>
{cards.map((card, index) => (
<div key={index} className='bg-white rounded-2xl shadow-md w-full overflow-hidden'>
{/* Header */}
<div className='flex items-center justify-between px-5 pt-5 pb-4'>
<div className='flex items-center gap-3'>
<div className='w-10 h-10 bg-green-700 rounded-full flex items-center justify-center'>
<card.icon className='w-5 h-5 text-white' />
</div>
<span className='text-base font-semibold text-gray-900'>{card.header}</span>
</div>
<button className='text-gray-300 hover:text-yellow-400 transition-colors'>
<Star className='w-5 h-5' />
</button>
</div>
{/* Divider */}
<div className='border-t border-gray-100 mx-5' />
{/* Body */}
<div className='px-5'>
<div className='flex items-center'>
<h2 className='text-lg font-semibold text-gray-900 pt-4'>{card.title}</h2>
{card.isNew && (
<span className='text-xs font-medium text-green-600 bg-green-50 px-2 py-0.5 rounded-full'>New</span>
)}
</div>
<p className='text-sm text-gray-500 leading-relaxed pb-2'>{card.description}</p>
</div>
{/* Footer */}
<div className='flex items-center justify-between px-5 pt-3 pb-5'>
<div className='flex items-center gap-1.5'>
<span className='text-xl font-bold text-gray-900'>{card.price}</span>
<button className='text-gray-300 hover:text-gray-500 transition-colors'>
<Info className='w-4 h-4' />
</button>
</div>
<button className='text-sm font-medium text-teal-600 border border-teal-600 rounded-full px-5 py-1.5 hover:bg-teal-50 transition-colors'>
Details
</button>
</div>
</div>
))}
</div>
</div>
);
}Layer Visualisation
Layers
Approximation of how this code would look in Figma's layer panel.
Home
LucideImport
ReactImport
cards"[{ icon, header, title, description, price, isNew }, ...]"
cardsData"[{ icon: Coffee, header: 'Starbucks', isNew: true }, ...]"
PageWrapper
CardGrid
GiftCard
CardHeader
BrandGroup
BrandIconWrapper
CardIcon
BrandName"{card.header}"
FavoriteButton
StarIcon
Divider
CardBody
TitleRow
CardTitle"{card.title}"
ShowNewBadgeIfNew
NewBadge"New"
CardDescription"{card.description}"
CardFooter
PriceGroup
PriceLabel"{card.price}"
InfoButton
InfoIcon
DetailsButton"Details"
Select a layer to inspect
What's new and what's happening?
Yay!