frontend: dashboard recent-activities widget no longer scrolls
Build and push images / validate (push) Successful in 3s
Build and push images / build-backend (push) Successful in 6s
Build and push images / build-worker (push) Successful in 5s
Build and push images / build-frontend (push) Successful in 10s

Rows now flex to fill the card height so the list always fits exactly,
removing the vertical scrollbar that appeared once rows carried a route
line, and the spurious horizontal scrollbar caused by overflow-auto +
the -mx-2 hover bleed. Empty state preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-18 22:00:42 +01:00
co-authored by Claude Opus 4.8
parent c14f3d60fa
commit a0912fd09a
+26 -22
View File
@@ -459,28 +459,32 @@ function RecentActivities({ activities }) {
const unit = useUnit() const unit = useUnit()
return ( return (
<Card title="Recent activities" viewHref="/activities"> <Card title="Recent activities" viewHref="/activities">
<div className="space-y-2 overflow-auto h-full"> {activities?.length ? (
{activities?.slice(0, 6).map(activity => ( // Rows flex to fill the card height so the list always fits exactly —
<Link key={activity.id} to={`/activities/${activity.id}`} // no scrollbars (and never a spurious horizontal one). The visible count
className="flex items-center gap-3 py-2 border-b border-gray-800/50 hover:bg-gray-800/30 rounded-lg px-2 -mx-2 transition-colors"> // adapts to the widget's height rather than a fixed slice overflowing.
<span className="text-lg">{sportIcon(activity.sport_type)}</span> <div className="h-full flex flex-col overflow-hidden">
<div className="flex-1 min-w-0"> {activities.slice(0, 6).map(activity => (
<p className="text-sm font-medium text-white truncate">{activity.name}</p> <Link key={activity.id} to={`/activities/${activity.id}`}
{activity.named_route_name && ( className="flex items-center gap-3 flex-1 min-h-0 overflow-hidden px-2 border-b border-gray-800/50 last:border-0 hover:bg-gray-800/30 rounded-lg transition-colors">
<p className="text-xs text-blue-400 truncate">📍 {activity.named_route_name}</p> <span className="text-lg shrink-0">{sportIcon(activity.sport_type)}</span>
)} <div className="flex-1 min-w-0">
<p className="text-xs text-gray-500">{formatDate(activity.start_time)}</p> <p className="text-sm font-medium text-white truncate">{activity.name}</p>
</div> {activity.named_route_name && (
<div className="text-right text-sm"> <p className="text-xs text-blue-400 truncate">📍 {activity.named_route_name}</p>
<p className="text-gray-200">{formatDistance(activity.distance_m, unit)}</p> )}
<p className="text-xs text-red-400">{formatHeartRate(activity.avg_heart_rate)}</p> <p className="text-xs text-gray-500">{formatDate(activity.start_time)}</p>
</div> </div>
</Link> <div className="text-right text-sm shrink-0">
))} <p className="text-gray-200">{formatDistance(activity.distance_m, unit)}</p>
{!activities?.length && ( <p className="text-xs text-red-400">{formatHeartRate(activity.avg_heart_rate)}</p>
<p className="text-gray-600 text-sm text-center py-8">No activities yet <Link to="/upload" className="text-blue-400 hover:underline">import some data</Link></p> </div>
)} </Link>
</div> ))}
</div>
) : (
<p className="text-gray-600 text-sm text-center py-8">No activities yet <Link to="/upload" className="text-blue-400 hover:underline">import some data</Link></p>
)}
</Card> </Card>
) )
} }