From c12acda86284e59c1c22cb3bd286fdd154d8c9ad Mon Sep 17 00:00:00 2001 From: Crownite Date: Tue, 12 May 2026 09:14:42 -0400 Subject: [PATCH] feat: Polish mobile responsive for bounty cards, hero, navigation, and detail views - BountyCard: responsive padding, reward text, meta row gap, abbreviated PR count, collapsible status label on xs - HeroSection: responsive min-height, terminal card width, font sizes, CTA button sizing, stats strip wrapping - BountyGrid: responsive heading, horizontal scroll filter pills on mobile - BountyDetail: responsive padding, title sizing, repo name truncation - index.css: add scrollbar-none utility class All changes target 375px and 768px breakpoints as specified. --- frontend/src/components/bounty/BountyCard.tsx | 47 ++++++++++--------- .../src/components/bounty/BountyDetail.tsx | 40 ++++++++-------- frontend/src/components/bounty/BountyGrid.tsx | 34 +++++++------- frontend/src/components/home/HeroSection.tsx | 20 ++++---- frontend/src/index.css | 9 ++++ 5 files changed, 80 insertions(+), 70 deletions(-) diff --git a/frontend/src/components/bounty/BountyCard.tsx b/frontend/src/components/bounty/BountyCard.tsx index aa974a474..4c24aac3d 100644 --- a/frontend/src/components/bounty/BountyCard.tsx +++ b/frontend/src/components/bounty/BountyCard.tsx @@ -61,7 +61,7 @@ export function BountyCard({ bounty }: BountyCardProps) { initial="rest" whileHover="hover" onClick={() => navigate(`/bounties/${bounty.id}`)} - className="relative rounded-xl border border-border bg-forge-900 p-5 cursor-pointer transition-colors duration-200 overflow-hidden group" + className="relative rounded-xl border border-border bg-forge-900 p-4 sm:p-5 cursor-pointer transition-colors duration-200 overflow-hidden group" > {/* Row 1: Repo + Tier */}
@@ -100,30 +100,31 @@ export function BountyCard({ bounty }: BountyCardProps) { {/* Separator */}
- {/* Row 4: Reward + Meta */} -
- - {formatCurrency(bounty.reward_amount, bounty.reward_token)} + {/* Row 4: Reward + Meta */} +
+ + {formatCurrency(bounty.reward_amount, bounty.reward_token)} + +
+ + + {bounty.submission_count} PRs + {bounty.submission_count} + + {bounty.deadline && ( + + + {timeLeft(bounty.deadline)} -
- - - {bounty.submission_count} PRs - - {bounty.deadline && ( - - - {timeLeft(bounty.deadline)} - - )} -
-
+ )} +
+
- {/* Status badge */} - - - {statusLabel} - + {/* Status badge */} + + + {statusLabel} + ); } diff --git a/frontend/src/components/bounty/BountyDetail.tsx b/frontend/src/components/bounty/BountyDetail.tsx index 65653fa8f..7f038ecdd 100644 --- a/frontend/src/components/bounty/BountyDetail.tsx +++ b/frontend/src/components/bounty/BountyDetail.tsx @@ -25,27 +25,27 @@ export function BountyDetail({ bounty }: BountyDetailProps) { }; return ( - - {/* Back link */} - - Back to Bounties - + + {/* Back link */} + + Back to Bounties + -
- {/* Main content */} -
- {/* Title + meta */} -
-
-
-
- {bounty.org_avatar_url && ( - - )} - {bounty.org_name}/{bounty.repo_name} - {bounty.issue_number && #{bounty.issue_number}} -
-

{bounty.title}

+
+ {/* Main content */} +
+ {/* Title + meta */} +
+
+
+
+ {bounty.org_avatar_url && ( + + )} + {bounty.org_name}/{bounty.repo_name} + {bounty.issue_number && #{bounty.issue_number}} +
+

{bounty.title}

- ))} + {/* Filter pills — horizontal scroll on mobile */} +
+ {FILTER_SKILLS.map((skill) => ( + + ))}
{/* Loading state */} diff --git a/frontend/src/components/home/HeroSection.tsx b/frontend/src/components/home/HeroSection.tsx index e37307166..481e803b4 100644 --- a/frontend/src/components/home/HeroSection.tsx +++ b/frontend/src/components/home/HeroSection.tsx @@ -87,7 +87,7 @@ export function HeroSection() { }; return ( -
+
{/* Background layers */}
@@ -98,7 +98,7 @@ export function HeroSection() { variants={fadeIn} initial="initial" animate="animate" - className="w-full max-w-xl rounded-xl border border-border bg-forge-900/90 backdrop-blur-sm overflow-hidden shadow-2xl shadow-black/50" + className="w-full max-w-sm sm:max-w-xl rounded-xl border border-border bg-forge-900/90 backdrop-blur-sm overflow-hidden shadow-2xl shadow-black/50" > {/* Title bar */}
@@ -111,7 +111,7 @@ export function HeroSection() {
{/* Terminal body */} -
+
$ @@ -154,7 +154,7 @@ export function HeroSection() { initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.3, duration: 0.5 }} - className="font-display text-4xl md:text-5xl font-bold text-text-primary tracking-wider text-center mt-10" + className="font-display text-3xl sm:text-4xl md:text-5xl font-bold text-text-primary tracking-wider text-center mt-8 sm:mt-10" > THE AI-POWERED BOUNTY{' '} FORGE @@ -164,7 +164,7 @@ export function HeroSection() { initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.45, duration: 0.5 }} - className="font-sans text-lg text-text-secondary text-center mt-4 max-w-lg" + className="font-sans text-base sm:text-lg text-text-secondary text-center mt-3 sm:mt-4 max-w-lg px-2" > Fund bounties. Ship code. Earn rewards. @@ -174,12 +174,12 @@ export function HeroSection() { initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.6, duration: 0.5 }} - className="flex flex-wrap items-center justify-center gap-4 mt-8" + className="flex flex-wrap items-center justify-center gap-3 sm:gap-4 mt-6 sm:mt-8" > Browse Bounties @@ -188,7 +188,7 @@ export function HeroSection() { Post a Bounty @@ -198,7 +198,7 @@ export function HeroSection() { @@ -211,7 +211,7 @@ export function HeroSection() { initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.8, duration: 0.5 }} - className="flex items-center justify-center gap-6 mt-8 font-mono text-sm text-text-muted" + className="flex flex-wrap items-center justify-center gap-x-4 gap-y-2 sm:gap-6 mt-6 sm:mt-8 font-mono text-xs sm:text-sm text-text-muted" > diff --git a/frontend/src/index.css b/frontend/src/index.css index 33799d725..858635114 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -143,3 +143,12 @@ input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } + +/* Hide scrollbar utility */ +.scrollbar-none { + -ms-overflow-style: none; + scrollbar-width: none; +} +.scrollbar-none::-webkit-scrollbar { + display: none; +}