Redesign restaurant list with card UI
Rounded corners, shadows, hover lift effect, rating display, and color-coded cuisine/price tags for better visual hierarchy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,30 +30,45 @@ export default function RestaurantList({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="divide-y divide-gray-100">
|
<div className="p-3 space-y-2">
|
||||||
{restaurants.map((r) => (
|
{restaurants.map((r) => (
|
||||||
<button
|
<button
|
||||||
key={r.id}
|
key={r.id}
|
||||||
onClick={() => onSelect(r)}
|
onClick={() => onSelect(r)}
|
||||||
className={`w-full text-left px-4 py-3 hover:bg-gray-50 transition-colors ${
|
className={`w-full text-left p-3 rounded-xl shadow-sm border transition-all hover:shadow-md hover:-translate-y-0.5 ${
|
||||||
selectedId === r.id ? "bg-blue-50 border-l-2 border-blue-500" : ""
|
selectedId === r.id
|
||||||
|
? "bg-blue-50 border-blue-300 shadow-blue-100"
|
||||||
|
: "bg-white border-gray-100 hover:bg-gray-50"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<h4 className="font-medium text-sm">
|
<div className="flex items-start justify-between gap-2">
|
||||||
|
<h4 className="font-semibold text-sm">
|
||||||
<span className="mr-1">{getCuisineIcon(r.cuisine_type)}</span>
|
<span className="mr-1">{getCuisineIcon(r.cuisine_type)}</span>
|
||||||
{r.name}
|
{r.name}
|
||||||
</h4>
|
</h4>
|
||||||
<div className="flex gap-2 mt-1 text-xs text-gray-500">
|
{r.rating && (
|
||||||
{r.cuisine_type && <span>{r.cuisine_type}</span>}
|
<span className="text-xs text-yellow-600 font-medium whitespace-nowrap shrink-0">
|
||||||
{r.region && <span>{r.region}</span>}
|
★ {r.rating}
|
||||||
{r.price_range && <span>{r.price_range}</span>}
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-x-2 gap-y-0.5 mt-1.5 text-xs text-gray-500">
|
||||||
|
{r.cuisine_type && (
|
||||||
|
<span className="px-1.5 py-0.5 bg-gray-100 rounded text-gray-600">{r.cuisine_type}</span>
|
||||||
|
)}
|
||||||
|
{r.price_range && (
|
||||||
|
<span className="px-1.5 py-0.5 bg-green-50 rounded text-green-700">{r.price_range}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{r.region && (
|
||||||
|
<p className="mt-1 text-xs text-gray-400 truncate">{r.region}</p>
|
||||||
|
)}
|
||||||
{r.channels && r.channels.length > 0 && (
|
{r.channels && r.channels.length > 0 && (
|
||||||
<div className="flex flex-wrap gap-1 mt-1">
|
<div className="flex flex-wrap gap-1 mt-1.5">
|
||||||
{r.channels.map((ch) => (
|
{r.channels.map((ch) => (
|
||||||
<span
|
<span
|
||||||
key={ch}
|
key={ch}
|
||||||
className="px-1.5 py-0.5 bg-red-50 text-red-600 rounded text-[10px] font-medium"
|
className="px-1.5 py-0.5 bg-red-50 text-red-600 rounded-full text-[10px] font-medium"
|
||||||
>
|
>
|
||||||
{ch}
|
{ch}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -5,18 +5,21 @@ function Block({ className = "" }: { className?: string }) {
|
|||||||
return <div className={`animate-pulse bg-gray-200 rounded ${className}`} />;
|
return <div className={`animate-pulse bg-gray-200 rounded ${className}`} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Skeleton for a single restaurant list item */
|
/** Skeleton for a single restaurant card */
|
||||||
export function RestaurantCardSkeleton() {
|
export function RestaurantCardSkeleton() {
|
||||||
return (
|
return (
|
||||||
<div className="px-4 py-3 space-y-2">
|
<div className="p-3 rounded-xl border border-gray-100 shadow-sm space-y-2">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
<Block className="h-4 w-3/5" />
|
<Block className="h-4 w-3/5" />
|
||||||
<div className="flex gap-2">
|
<Block className="h-3 w-10" />
|
||||||
<Block className="h-3 w-16" />
|
|
||||||
<Block className="h-3 w-20" />
|
|
||||||
<Block className="h-3 w-14" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Block className="h-5 w-16 rounded" />
|
||||||
|
<Block className="h-5 w-14 rounded" />
|
||||||
|
</div>
|
||||||
|
<Block className="h-3 w-2/3" />
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
<Block className="h-4 w-14 rounded-sm" />
|
<Block className="h-4 w-14 rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -25,7 +28,7 @@ export function RestaurantCardSkeleton() {
|
|||||||
/** Skeleton for the restaurant list (multiple cards) */
|
/** Skeleton for the restaurant list (multiple cards) */
|
||||||
export function RestaurantListSkeleton({ count = 8 }: { count?: number }) {
|
export function RestaurantListSkeleton({ count = 8 }: { count?: number }) {
|
||||||
return (
|
return (
|
||||||
<div className="divide-y divide-gray-100">
|
<div className="p-3 space-y-2">
|
||||||
{Array.from({ length: count }, (_, i) => (
|
{Array.from({ length: count }, (_, i) => (
|
||||||
<RestaurantCardSkeleton key={i} />
|
<RestaurantCardSkeleton key={i} />
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user