Skip to content

Commit 4294d95

Browse files
committed
improve page layout
1 parent fadd3b7 commit 4294d95

File tree

2 files changed

+244
-22
lines changed

2 files changed

+244
-22
lines changed

frontend/src/App.css

Lines changed: 167 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@
265265
min-height: 100vh;
266266
display: flex;
267267
flex-direction: column;
268+
background: radial-gradient(900px 520px at 16% 0%, rgba(37, 99, 235, 0.14), transparent 60%),
269+
radial-gradient(900px 520px at 86% 0%, rgba(239, 68, 68, 0.12), transparent 60%),
270+
#f8fafc;
268271
}
269272

270273
.landingHeader {
@@ -273,20 +276,78 @@
273276
justify-content: space-between;
274277
padding: 14px 16px;
275278
border-bottom: 1px solid #e2e8f0;
276-
background: #ffffff;
279+
background: rgba(255, 255, 255, 0.75);
280+
backdrop-filter: blur(10px);
281+
position: sticky;
282+
top: 0;
283+
z-index: 10;
277284
}
278285

279286
.landingBrand {
280287
font-weight: 800;
281288
letter-spacing: 0.2px;
289+
color: #0f172a;
290+
display: flex;
291+
align-items: center;
292+
gap: 10px;
293+
}
294+
295+
.landingBrandTag {
296+
font-size: 11px;
297+
font-weight: 700;
298+
padding: 4px 8px;
299+
border-radius: 999px;
300+
color: #334155;
301+
background: rgba(226, 232, 240, 0.7);
302+
border: 1px solid rgba(226, 232, 240, 0.9);
282303
}
283304

284305
.landingMain {
306+
flex: 1;
285307
width: min(1040px, 100%);
286308
margin: 0 auto;
287309
padding: 24px 16px 40px 16px;
288310
}
289311

312+
.landingHero {
313+
border: 1px solid rgba(226, 232, 240, 0.9);
314+
border-radius: 18px;
315+
padding: 18px 18px;
316+
background: linear-gradient(180deg, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.72));
317+
box-shadow: 0 18px 40px rgba(15, 23, 42, 0.07);
318+
}
319+
320+
.landingHeroGrid {
321+
display: grid;
322+
grid-template-columns: 1.25fr 0.75fr;
323+
gap: 18px;
324+
align-items: center;
325+
}
326+
327+
.landingHeroLeft {
328+
min-width: 0;
329+
}
330+
331+
.landingPills {
332+
display: flex;
333+
flex-wrap: wrap;
334+
gap: 8px;
335+
margin-bottom: 10px;
336+
}
337+
338+
.pill {
339+
display: inline-flex;
340+
align-items: center;
341+
gap: 6px;
342+
padding: 6px 10px;
343+
border-radius: 999px;
344+
font-size: 12px;
345+
font-weight: 650;
346+
color: #0f172a;
347+
border: 1px solid rgba(226, 232, 240, 0.9);
348+
background: rgba(248, 250, 252, 0.85);
349+
}
350+
290351
.landingHero h1 {
291352
margin: 0;
292353
font-size: 34px;
@@ -316,6 +377,89 @@
316377
color: #475569;
317378
}
318379

380+
.landingHeroRight {
381+
min-width: 0;
382+
}
383+
384+
.landingMock {
385+
border: 1px solid rgba(226, 232, 240, 0.9);
386+
border-radius: 16px;
387+
overflow: hidden;
388+
background: rgba(255, 255, 255, 0.88);
389+
box-shadow: 0 10px 26px rgba(15, 23, 42, 0.1);
390+
}
391+
392+
.landingMockMap {
393+
height: 170px;
394+
position: relative;
395+
background: radial-gradient(260px 150px at 30% 30%, rgba(37, 99, 235, 0.22), transparent 70%),
396+
radial-gradient(240px 150px at 70% 70%, rgba(239, 68, 68, 0.18), transparent 70%),
397+
linear-gradient(180deg, rgba(241, 245, 249, 0.9), rgba(226, 232, 240, 0.65));
398+
}
399+
400+
.landingMockPin {
401+
position: absolute;
402+
width: 12px;
403+
height: 12px;
404+
border-radius: 999px;
405+
border: 2px solid rgba(255, 255, 255, 0.95);
406+
box-shadow: 0 8px 20px rgba(15, 23, 42, 0.22);
407+
transform: translate(-50%, -50%);
408+
}
409+
410+
.landingMockPin.listing {
411+
background: #2563eb;
412+
}
413+
414+
.landingMockPin.target {
415+
width: 14px;
416+
height: 14px;
417+
background: #ef4444;
418+
box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.22), 0 8px 20px rgba(15, 23, 42, 0.22);
419+
}
420+
421+
.landingMockList {
422+
padding: 12px 12px 12px 12px;
423+
display: flex;
424+
flex-direction: column;
425+
gap: 10px;
426+
}
427+
428+
.landingMockItem {
429+
display: flex;
430+
align-items: center;
431+
gap: 10px;
432+
padding: 8px 10px;
433+
border-radius: 12px;
434+
border: 1px solid rgba(226, 232, 240, 0.9);
435+
background: rgba(248, 250, 252, 0.88);
436+
font-size: 12px;
437+
color: #0f172a;
438+
}
439+
440+
.landingMockDot {
441+
width: 10px;
442+
height: 10px;
443+
border-radius: 999px;
444+
flex: 0 0 auto;
445+
}
446+
447+
.landingMockDot.listing {
448+
background: #2563eb;
449+
}
450+
451+
.landingMockText {
452+
overflow: hidden;
453+
text-overflow: ellipsis;
454+
white-space: nowrap;
455+
}
456+
457+
.landingMockMeta {
458+
margin-left: auto;
459+
color: #475569;
460+
font-variant-numeric: tabular-nums;
461+
}
462+
319463
.landingGrid {
320464
margin-top: 24px;
321465
display: grid;
@@ -352,10 +496,27 @@
352496

353497
.landingFooter {
354498
border-top: 1px solid #e2e8f0;
355-
background: #ffffff;
499+
background: rgba(255, 255, 255, 0.75);
500+
backdrop-filter: blur(10px);
356501
padding: 14px 16px;
357502
font-size: 12px;
358503
color: #475569;
504+
display: flex;
505+
gap: 8px;
506+
flex-wrap: wrap;
507+
align-items: center;
508+
justify-content: center;
509+
text-align: center;
510+
}
511+
512+
.landingFooter a {
513+
color: inherit;
514+
text-decoration: underline;
515+
text-underline-offset: 2px;
516+
}
517+
518+
.landingFooter a:hover {
519+
color: #0f172a;
359520
}
360521

361522
@media (max-width: 960px) {
@@ -373,6 +534,10 @@
373534
grid-template-columns: 1fr;
374535
}
375536

537+
.landingHeroGrid {
538+
grid-template-columns: 1fr;
539+
}
540+
376541
.landingHero h1 {
377542
font-size: 28px;
378543
}

frontend/src/pages/LandingPage.tsx

Lines changed: 77 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,75 @@ export default function LandingPage() {
66
return (
77
<div className="landing">
88
<header className="landingHeader">
9-
<div className="landingBrand">EasyRelocate</div>
10-
<div className="actions">
11-
<Link className="button" to="/compare">
12-
Open app
13-
</Link>
9+
<div className="landingBrand">
10+
EasyRelocate <span className="landingBrandTag">US-only MVP</span>
1411
</div>
1512
</header>
1613

1714
<main className="landingMain">
1815
<section className="landingHero">
19-
<h1>Relocation housing, compared in one place.</h1>
20-
<p>
21-
EasyRelocate is an open-source, non-commercial decision-support tool
22-
for interns/students relocating to a new city. Save listings while
23-
you browse (starting with Airbnb), then compare them on a single map
24-
with price + distance filters.
25-
</p>
26-
<div className="landingCtas">
27-
<Link className="button" to="/compare">
28-
Start comparing
29-
</Link>
30-
</div>
31-
<div className="landingNote">
32-
MVP is US-only for now. Listing locations may be approximate.
16+
<div className="landingHeroGrid">
17+
<div className="landingHeroLeft">
18+
<div className="landingPills" aria-label="Highlights">
19+
<span className="pill">Chrome extension</span>
20+
<span className="pill">Map + list</span>
21+
<span className="pill">Open-source</span>
22+
</div>
23+
<h1>Relocation housing, compared in one place.</h1>
24+
<p>
25+
EasyRelocate is a non-commercial decision-support tool for interns/students
26+
relocating to a new city. Save listings while you browse (starting with
27+
Airbnb), then compare them on one map with price + distance filters.
28+
</p>
29+
<div className="landingCtas">
30+
<Link className="button" to="/compare">
31+
Start comparing
32+
</Link>
33+
<a
34+
className="button secondary"
35+
href="https://github.com/YuWei-CH/EasyRelocate/blob/main/docs/PLATFORM_ORGANIZATION.md"
36+
target="_blank"
37+
rel="noreferrer"
38+
>
39+
How it works
40+
</a>
41+
</div>
42+
<div className="landingNote">
43+
US-only MVP for now. Listing locations may be approximate.
44+
</div>
45+
</div>
46+
47+
<div className="landingHeroRight" aria-hidden="true">
48+
<div className="landingMock">
49+
<div className="landingMockMap">
50+
<div className="landingMockPin target" style={{ left: '56%', top: '42%' }} />
51+
<div className="landingMockPin listing" style={{ left: '34%', top: '34%' }} />
52+
<div className="landingMockPin listing" style={{ left: '70%', top: '62%' }} />
53+
<div className="landingMockPin listing" style={{ left: '46%', top: '68%' }} />
54+
</div>
55+
<div className="landingMockList">
56+
<div className="landingMockItem">
57+
<span className="landingMockDot listing" />
58+
<span className="landingMockText">Airbnb · 1BR · $3,200/mo</span>
59+
<span className="landingMockMeta">3.4 km</span>
60+
</div>
61+
<div className="landingMockItem">
62+
<span className="landingMockDot listing" />
63+
<span className="landingMockText">Airbnb · Studio · $2,750/mo</span>
64+
<span className="landingMockMeta">5.1 km</span>
65+
</div>
66+
<div className="landingMockItem">
67+
<span className="landingMockDot listing" />
68+
<span className="landingMockText">Airbnb · 2BR · $3,900/mo</span>
69+
<span className="landingMockMeta">7.8 km</span>
70+
</div>
71+
</div>
72+
</div>
73+
</div>
3374
</div>
3475
</section>
3576

36-
<section className="landingGrid">
77+
<section className="landingGrid" id="how">
3778
<div className="landingCard">
3879
<h2>What &amp; why</h2>
3980
<ul>
@@ -73,6 +114,22 @@ export default function LandingPage() {
73114

74115
<footer className="landingFooter">
75116
<div>EasyRelocate — open-source, non-commercial.</div>
117+
<div>
118+
All copyright reserved by{' '}
119+
<a href="https://github.com/YuWei-CH" target="_blank" rel="noreferrer">
120+
YuWei-CH
121+
</a>
122+
</div>
123+
<div>
124+
Welcome to contribute:{' '}
125+
<a
126+
href="https://github.com/YuWei-CH/EasyRelocate"
127+
target="_blank"
128+
rel="noreferrer"
129+
>
130+
https://github.com/YuWei-CH/EasyRelocate
131+
</a>
132+
</div>
76133
</footer>
77134
</div>
78135
)

0 commit comments

Comments
 (0)