Skip to content

Commit 316a934

Browse files
committed
quick mvp of landing page, polish coming still
1 parent fa1dfef commit 316a934

51 files changed

Lines changed: 1299 additions & 869 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

devcon/src/assets/css/global/general.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,34 @@
88
user-select: none;
99
}
1010

11+
/* Radix Dialog overlay fade animation */
12+
.dialog-overlay {
13+
&[data-state='open'] {
14+
animation: dialog-overlay-in 400ms ease-out;
15+
}
16+
&[data-state='closed'] {
17+
animation: dialog-overlay-out 300ms ease-in;
18+
}
19+
}
20+
21+
@keyframes dialog-overlay-in {
22+
from {
23+
opacity: 0;
24+
}
25+
to {
26+
opacity: 1;
27+
}
28+
}
29+
30+
@keyframes dialog-overlay-out {
31+
from {
32+
opacity: 1;
33+
}
34+
to {
35+
opacity: 0;
36+
}
37+
}
38+
1139
.aspect {
1240
position: relative;
1341
height: 0;
Lines changed: 125 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,52 @@
1-
import React from 'react'
1+
import React, { useEffect, useState } from 'react'
22
import Image from 'next/image'
3-
import BannerImage from 'components/domain/landing-page/images/devcon-india-banner.png'
4-
import TicketCard from 'components/domain/landing-page/images/ticket-card.png'
5-
import TicketBack from 'components/domain/ticket-sharing/ticket-backside.png'
3+
import BannerImage from './images/devcon-8-india-bg.png'
4+
import DevconLogo from './images/devcon-8-india-logo.svg'
65
import IconX from 'assets/icons/twitter.svg'
76
import IconInstagram from 'assets/icons/instagram.svg'
87
import IconTelegram from 'assets/icons/telegram.svg'
98
import IconEmail from 'assets/icons/ui-email.svg'
109
import { Link } from 'components/common/link'
1110
import useGetElementHeight from 'hooks/useGetElementHeight'
11+
import { ChevronDown } from 'lucide-react'
12+
import { GetReminderDialog } from 'components/domain/landing-page/GetReminderDialog'
13+
14+
// Ticket launch date — May 12, 2026 @ 3:00 PM UTC
15+
const TICKET_LAUNCH_DATE = new Date(Date.UTC(2026, 4, 12, 15, 0, 0))
16+
17+
type Countdown = { days: number; hours: number; mins: number; secs: number }
18+
19+
function computeCountdown(): Countdown {
20+
const now = Date.now()
21+
const diff = Math.max(0, TICKET_LAUNCH_DATE.getTime() - now)
22+
const days = Math.floor(diff / 86_400_000)
23+
const hours = Math.floor((diff % 86_400_000) / 3_600_000)
24+
const mins = Math.floor((diff % 3_600_000) / 60_000)
25+
const secs = Math.floor((diff % 60_000) / 1000)
26+
return { days, hours, mins, secs }
27+
}
28+
29+
const CountdownUnit = ({ value, label, width }: { value: number; label: string; width?: string }) => (
30+
<div className={`flex flex-col items-center justify-center text-center ${width || ''}`}>
31+
<p className="text-2xl font-extrabold text-white leading-[28.8px] tracking-[-0.5px]">{value}</p>
32+
<p className="text-xs text-[#9188a2] leading-4">{label}</p>
33+
</div>
34+
)
35+
36+
const Separator = () => <div className="w-px h-4 bg-white/10" aria-hidden />
1237

1338
export const Hero = () => {
1439
const stripHeight = useGetElementHeight('strip')
40+
const [mounted, setMounted] = useState(false)
41+
const [countdown, setCountdown] = useState<Countdown>({ days: 0, hours: 0, mins: 0, secs: 0 })
42+
const [reminderOpen, setReminderOpen] = useState(false)
43+
44+
useEffect(() => {
45+
setMounted(true)
46+
setCountdown(computeCountdown())
47+
const interval = setInterval(() => setCountdown(computeCountdown()), 1000)
48+
return () => clearInterval(interval)
49+
}, [])
1550

1651
return (
1752
<div className="relative w-full h-[90vh] md:h-screen overflow-hidden">
@@ -22,84 +57,115 @@ export const Hero = () => {
2257
fill
2358
priority
2459
placeholder="blur"
25-
className="object-cover object-top"
60+
className="object-cover object-center"
2661
style={{ paddingTop: stripHeight }}
2762
/>
2863

2964
{/* Edge gradients for smooth blending */}
3065
<div
31-
className="absolute bottom-0 left-0 w-full h-[150px] mix-blend-hard-light"
32-
style={{
33-
background: 'linear-gradient(to top, rgba(34,17,68,1) 4.5%, rgba(34,17,68,0) 100%)',
34-
}}
66+
className="absolute bottom-0 left-0 w-full h-[150px] mix-blend-hard-light pointer-events-none"
67+
style={{ background: 'linear-gradient(to top, rgba(34,17,68,1) 4.5%, rgba(34,17,68,0) 100%)' }}
3568
/>
3669
<div
37-
className="absolute top-0 left-0 h-full w-[160px] mix-blend-hard-light"
38-
style={{
39-
background: 'linear-gradient(to right, rgba(34,17,68,1) 0%, rgba(34,17,68,0) 100%)',
40-
}}
70+
className="absolute top-0 left-0 h-full w-[60px] md:w-[160px] mix-blend-hard-light pointer-events-none"
71+
style={{ background: 'linear-gradient(to right, rgba(34,17,68,1) 0%, rgba(34,17,68,0) 100%)' }}
4172
/>
4273
<div
43-
className="absolute top-0 right-0 h-full w-[160px] mix-blend-hard-light"
44-
style={{
45-
background: 'linear-gradient(to left, rgba(34,17,68,1) 0%, rgba(34,17,68,0) 100%)',
46-
}}
74+
className="absolute top-0 right-0 h-full w-[60px] md:w-[160px] mix-blend-hard-light pointer-events-none"
75+
style={{ background: 'linear-gradient(to left, rgba(34,17,68,1) 0%, rgba(34,17,68,0) 100%)' }}
4776
/>
4877

4978
{/* Hero content at bottom */}
50-
<div className="absolute bottom-0 left-0 right-0 pb-8 lg:pb-12">
79+
<div className="absolute bottom-0 left-0 right-0 pb-6 md:pb-8 lg:pb-14">
5180
<div className="section">
52-
<div className="flex items-end justify-between">
53-
{/* Left: Location + Social */}
54-
<div className="flex flex-col gap-4">
55-
<div className="flex flex-col gap-1.5 text-white" style={{ textShadow: '0 2px 12px rgba(34,17,68,1)' }}>
56-
<h1 className="text-3xl lg:text-[32px] font-extrabold leading-[1.2] tracking-[-0.5px]">
57-
Mumbai, India
58-
</h1>
59-
<p className="text-xl lg:text-2xl tracking-[-0.5px]">3—6 November, 2026</p>
60-
</div>
61-
62-
<div className="backdrop-blur-[2px] bg-[rgba(26,13,51,0.8)] border border-[rgba(255,255,255,0.1)] flex gap-4 items-center px-4 py-2 rounded-lg w-fit [&_path]:!fill-white">
63-
<span className="text-white text-base">Follow us</span>
64-
<Link to="https://x.com/efdevcon" className="text-white hover:text-white/80 transition-colors">
65-
<IconX className="w-[18px] h-[18px]" />
66-
</Link>
67-
<Link to="https://instagram.com/efdevcon" className="text-white hover:text-white/80 transition-colors">
68-
<IconInstagram className="w-[18px] h-[18px]" />
69-
</Link>
70-
<Link to="https://t.me/+sitvvHw8D8EzN2Yx" className="text-white hover:text-white/80 transition-colors">
71-
<IconTelegram className="w-[18px] h-[18px]" />
72-
</Link>
73-
<Link to="mailto:devcon@ethereum.org" className="text-white hover:text-white/80 transition-colors">
74-
<IconEmail className="w-[18px] h-[18px]" />
75-
</Link>
81+
<div className="flex flex-col md:flex-row gap-4 md:gap-8 md:items-end md:justify-between">
82+
{/* Left: Logo + Location */}
83+
<div className="flex flex-col gap-4 md:gap-6 [filter:drop-shadow(0_2px_12px_#214)]">
84+
<DevconLogo className="w-[160px] md:w-[263px] h-auto text-white" />
85+
<div className="flex flex-col gap-1 md:gap-2 text-white">
86+
<h1 className="text-3xl md:text-5xl font-extrabold leading-[1.2] tracking-[-0.5px]">Mumbai, India</h1>
87+
<p className="text-xl md:text-4xl font-light leading-[1.2] tracking-[-0.5px]">3—6 November, 2026</p>
7688
</div>
7789
</div>
7890

79-
{/* Right: Ticket card with fan-out effect — commented out while ticket sales are delayed
80-
<Link to="/tickets" className="hidden md:flex flex-col gap-3 items-center w-[348px] shrink-0 group">
81-
<div className="relative w-[338px] h-[190px]">
82-
<div
83-
className="absolute inset-0 origin-center scale-[0.90] transition-transform duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:rotate-[-9deg] group-hover:translate-x-[0px] group-hover:translate-y-[2px] group-hover:scale-[0.93]"
84-
style={{ filter: 'drop-shadow(0 8px 20px rgba(0, 0, 0, 0.3))' }}
85-
>
86-
<Image src={TicketBack} alt="" width={338} height={190} />
91+
{/* Right: Ticket countdown + social links */}
92+
<div className="flex flex-col gap-2 w-full sm:w-[315px] shrink-0">
93+
{/* Ticket Countdown Widget */}
94+
<div className="backdrop-blur-[3px] bg-[rgba(26,13,51,0.8)] border border-solid border-[rgba(150,142,166,0.19)] rounded-lg p-4 flex flex-col gap-4">
95+
<div className="flex flex-col gap-3">
96+
<p className="text-xs font-semibold text-[#ffa366] text-center tracking-[2px] leading-none">
97+
TICKETS LAUNCH MAY 12
98+
</p>
99+
100+
{/* Countdown row — only render on client to avoid hydration mismatch */}
101+
<div className="flex items-center justify-between min-h-[44px]">
102+
{mounted && (
103+
<>
104+
<CountdownUnit value={countdown.days} label="days" width="w-12" />
105+
<Separator />
106+
<CountdownUnit value={countdown.hours} label="hours" />
107+
<Separator />
108+
<CountdownUnit value={countdown.mins} label="mins" width="w-10" />
109+
<Separator />
110+
<CountdownUnit value={countdown.secs} label="secs" width="w-10" />
111+
</>
112+
)}
113+
</div>
114+
115+
{/* Early bird pricing */}
116+
<div className="flex items-center justify-between font-extrabold text-sm">
117+
<p className="text-white leading-[14px]">Global Early Bird</p>
118+
<div className="flex gap-1 items-end">
119+
<p className="text-[#9188a2] line-through leading-[14px]">$699</p>
120+
<p className="text-white text-base leading-4">$349</p>
121+
</div>
122+
</div>
87123
</div>
88-
<div
89-
className="absolute inset-0 transition-transform duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)]"
90-
style={{ filter: 'drop-shadow(0 12px 30px rgba(0, 0, 0, 0.4))' }}
124+
125+
<button
126+
type="button"
127+
onClick={() => setReminderOpen(true)}
128+
className="flex gap-1 items-center justify-center w-full cursor-pointer hover:opacity-80 transition-opacity"
129+
aria-label="Remind me when tickets launch"
91130
>
92-
<Image src={TicketCard} alt="Devcon Early Bird Ticket" width={338} height={190} />
131+
<span className="text-sm font-bold text-[#9668f1] leading-none">Remind me</span>
132+
<ChevronDown className="w-3.5 h-3.5 text-[#9668f1]" strokeWidth={2.5} />
133+
</button>
134+
</div>
135+
136+
{/* Social Links */}
137+
<div className="backdrop-blur-[3px] bg-[rgba(26,13,51,0.8)] border border-solid border-[rgba(150,142,166,0.19)] rounded-lg px-4 py-2 flex items-center justify-center gap-4 sm:justify-between sm:gap-0 [&_path]:!fill-white">
138+
<p className="text-sm text-white leading-5">Follow for updates</p>
139+
<div className="flex gap-4 items-center">
140+
<Link to="https://x.com/efdevcon" className="text-white hover:text-white/80 transition-colors">
141+
<IconX className="w-[18px] h-[18px]" />
142+
</Link>
143+
<Link
144+
to="https://instagram.com/efdevcon"
145+
className="text-white hover:text-white/80 transition-colors"
146+
>
147+
<IconInstagram className="w-[18px] h-[18px]" />
148+
</Link>
149+
<Link
150+
to="https://t.me/+sitvvHw8D8EzN2Yx"
151+
className="text-white hover:text-white/80 transition-colors"
152+
>
153+
<IconTelegram className="w-[18px] h-[18px]" />
154+
</Link>
155+
<Link
156+
to="https://paragraph.com/@efevents"
157+
className="text-white hover:text-white/80 transition-colors"
158+
>
159+
<IconEmail className="w-[18px] h-[18px]" />
160+
</Link>
93161
</div>
94162
</div>
95-
<p className="text-white font-bold text-base text-center translate-y-[0px] group-hover:translate-y-[8px] transition-transform duration-300">
96-
Local Early Bird tickets now available!
97-
</p>
98-
</Link>
99-
*/}
163+
</div>
100164
</div>
101165
</div>
102166
</div>
167+
168+
<GetReminderDialog open={reminderOpen} onOpenChange={setReminderOpen} />
103169
</div>
104170
)
105171
}
8.48 MB
Loading

0 commit comments

Comments
 (0)