Skip to content

Commit 0366caa

Browse files
committed
Add nametags promo page
1 parent 8aae350 commit 0366caa

5 files changed

Lines changed: 212 additions & 0 deletions

File tree

app/components/Header.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ const Container = styled.header`
294294
backdrop-filter: blur(38px);
295295
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
296296
z-index: 100;
297+
298+
body.full & {
299+
position: fixed;
300+
}
297301
`
298302

299303
const Nav = styled.nav`

app/nametags/page.tsx

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
"use client"
2+
import styled from "styled-components"
3+
import { motion, useInView } from "framer-motion"
4+
import { useRef, useEffect } from "react"
5+
import { PotionBackground } from "../components/PotionBackground"
6+
import { ErrorBoundary } from "../components/ErrorBoundary"
7+
import { Button } from "../components/Button"
8+
9+
// Components //
10+
11+
export default function NametagPage() {
12+
const headingRef = useRef(null)
13+
const ctaRef = useRef(null)
14+
const videoRef = useRef<HTMLVideoElement>(null)
15+
const headingInView = useInView(headingRef, { amount: 0.3 })
16+
const ctaInView = useInView(ctaRef, { amount: 0.3 })
17+
18+
useEffect(() => {
19+
// Add .full class to body to make header fixed instead of sticky
20+
document.body.classList.add("full")
21+
22+
return () => {
23+
// Remove .full class when component unmounts
24+
document.body.classList.remove("full")
25+
}
26+
}, [])
27+
28+
const handleVideoEnd = () => {
29+
if (videoRef.current) {
30+
videoRef.current.currentTime = 0
31+
videoRef.current.play()
32+
}
33+
}
34+
35+
return (
36+
<>
37+
<BackgroundContainer>
38+
<VideoBackground ref={videoRef} autoPlay loop muted playsInline onEnded={handleVideoEnd}>
39+
<source src="/videos/nametags-hero.mp4" type="video/mp4" />
40+
<source
41+
src="/videos/nametags-hero-h265.mp4"
42+
type="video/mp4"
43+
media="(max-width: 768px)"
44+
/>
45+
<source src="/videos/nametags-hero.webm" type="video/webm" />
46+
</VideoBackground>
47+
<ErrorBoundary
48+
fallback={<div style={{ backgroundColor: "black", width: "100%", height: "100%" }} />}
49+
>
50+
<PotionBackground />
51+
</ErrorBoundary>
52+
</BackgroundContainer>
53+
<Main>
54+
<Hero>
55+
<HeadingContainer
56+
ref={headingRef}
57+
animate={{
58+
opacity: headingInView ? 1 : 0,
59+
y: headingInView ? 0 : -20
60+
}}
61+
transition={{ duration: 0.6, ease: "easeOut" }}
62+
as={motion.div}
63+
>
64+
<Heading>Introducing Nametags</Heading>
65+
</HeadingContainer>
66+
<BottomContent
67+
ref={ctaRef}
68+
animate={{
69+
opacity: ctaInView ? 1 : 0,
70+
y: ctaInView ? 0 : 20
71+
}}
72+
transition={{ duration: 0.6, ease: "easeOut" }}
73+
as={motion.div}
74+
>
75+
<Description>
76+
Nametags are your digital persona, a way to say &quot;hello&quot; to the community and
77+
introduce yourself, your interests and skills. Nametags are your personal brand and
78+
profile communicated through DEVx.
79+
</Description>
80+
<ButtonContainer>
81+
<Button href="/login" size="default">
82+
Get your Nametag
83+
</Button>
84+
</ButtonContainer>
85+
</BottomContent>
86+
</Hero>
87+
</Main>
88+
</>
89+
)
90+
}
91+
92+
// Styled Components //
93+
94+
const Main = styled.main`
95+
color: white;
96+
display: flex;
97+
flex-direction: column;
98+
align-items: center;
99+
justify-content: center;
100+
`
101+
102+
const BackgroundContainer = styled.section`
103+
background-color: #0a0a0a;
104+
position: fixed;
105+
height: 100vh;
106+
width: 100vw;
107+
top: 0;
108+
left: 0;
109+
display: flex;
110+
flex-direction: column;
111+
align-items: center;
112+
justify-content: center;
113+
overflow: hidden;
114+
`
115+
116+
const VideoBackground = styled.video`
117+
position: absolute;
118+
top: 50%;
119+
left: 50%;
120+
width: 100%;
121+
height: 100%;
122+
object-fit: cover;
123+
transform: translate(-50%, -50%);
124+
z-index: 0;
125+
`
126+
127+
const Hero = styled.section`
128+
position: relative;
129+
height: 100vh;
130+
width: 100vw;
131+
display: flex;
132+
flex-direction: column;
133+
align-items: center;
134+
justify-content: space-between;
135+
padding-top: 6rem;
136+
padding-bottom: 4rem;
137+
138+
&::before {
139+
content: "";
140+
position: absolute;
141+
top: 0;
142+
left: 0;
143+
right: 0;
144+
bottom: 0;
145+
background: linear-gradient(
146+
to bottom,
147+
rgba(0, 0, 0, 1) 0%,
148+
rgba(0, 0, 0, 0.3) 20%,
149+
transparent 40%,
150+
transparent 60%,
151+
rgba(0, 0, 0, 0.5) 80%,
152+
rgba(0, 0, 0, 1) 100%
153+
);
154+
pointer-events: none;
155+
z-index: 1;
156+
}
157+
158+
@media (max-width: 768px) {
159+
padding-top: 6rem;
160+
padding-bottom: 6rem;
161+
}
162+
`
163+
164+
const HeadingContainer = styled(motion.div)`
165+
display: flex;
166+
flex-direction: column;
167+
align-items: center;
168+
justify-content: center;
169+
text-align: center;
170+
padding: 0 2rem;
171+
max-width: 1024px;
172+
position: relative;
173+
z-index: 2;
174+
`
175+
176+
const BottomContent = styled(motion.div)`
177+
display: flex;
178+
flex-direction: column;
179+
align-items: center;
180+
justify-content: center;
181+
gap: 2rem;
182+
text-align: center;
183+
padding: 0 2rem;
184+
max-width: 1024px;
185+
position: relative;
186+
z-index: 2;
187+
`
188+
189+
const Heading = styled.h1`
190+
font-size: clamp(2.5rem, 8vw, 5rem);
191+
font-weight: 700;
192+
margin: 0;
193+
letter-spacing: 0.02em;
194+
`
195+
196+
const Description = styled.p`
197+
font-size: clamp(1.25rem, 2vw, 1.75rem);
198+
margin: 0;
199+
color: rgba(255, 255, 255, 0.9);
200+
line-height: 1.4;
201+
`
202+
203+
const ButtonContainer = styled.div`
204+
margin-top: 1rem;
205+
display: flex;
206+
justify-content: center;
207+
align-items: center;
208+
`
13.2 MB
Binary file not shown.

public/videos/nametags-hero.mp4

40.9 MB
Binary file not shown.

public/videos/nametags-hero.webm

31.2 MB
Binary file not shown.

0 commit comments

Comments
 (0)