Skip to content

Commit 26fabe8

Browse files
committed
apply with devfolio
1 parent 13ec392 commit 26fabe8

File tree

1 file changed

+70
-14
lines changed

1 file changed

+70
-14
lines changed

src/components/sections/HeroSection.jsx

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,61 @@ import { EXTERNAL_LINKS, IMAGE_PATHS } from '@/lib/constants';
55
import { motion, useScroll, useTransform } from 'framer-motion';
66
import { Sparkles } from 'lucide-react';
77
import Image from 'next/image';
8+
import { useEffect, useRef, useState } from 'react';
89

910
export default function HeroSection() {
1011
const { scrollY } = useScroll();
1112
const yText = useTransform(scrollY, [0, 500], [0, 150]);
1213
const yImg = useTransform(scrollY, [0, 500], [0, -80]);
1314
const opacity = useTransform(scrollY, [0, 300], [1, 0]);
15+
const devfolioContainerRef = useRef(null);
16+
const [devfolioButtonVisible, setDevfolioButtonVisible] = useState(false);
17+
18+
// Load Devfolio apply button SDK on this page
19+
useEffect(() => {
20+
const existing = document.querySelector(
21+
'script[src="https://apply.devfolio.co/v2/sdk.js"]'
22+
);
23+
const script = existing || document.createElement('script');
24+
script.src = 'https://apply.devfolio.co/v2/sdk.js';
25+
script.async = true;
26+
script.defer = true;
27+
28+
if (!existing) {
29+
document.body.appendChild(script);
30+
}
31+
32+
return () => {
33+
if (!existing && script.parentNode) {
34+
script.parentNode.removeChild(script);
35+
}
36+
};
37+
}, []);
38+
39+
// Detect when Devfolio widget renders and fall back to native button if it doesn't
40+
useEffect(() => {
41+
if (!devfolioContainerRef.current) return undefined;
42+
43+
const target = devfolioContainerRef.current;
44+
const observer = new MutationObserver(() => {
45+
if (target.childElementCount > 0) {
46+
setDevfolioButtonVisible(true);
47+
}
48+
});
49+
50+
observer.observe(target, { childList: true });
51+
52+
const timeout = setTimeout(() => {
53+
if (target.childElementCount > 0) {
54+
setDevfolioButtonVisible(true);
55+
}
56+
}, 2000);
57+
58+
return () => {
59+
observer.disconnect();
60+
clearTimeout(timeout);
61+
};
62+
}, []);
1463

1564
return (
1665
<section
@@ -100,21 +149,28 @@ export default function HeroSection() {
100149

101150
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-md">
102151
<div className="sm:col-span-2">
103-
<Button
104-
variant="devfolio"
105-
size="default"
106-
className="group w-full font-semibold gap-1.5"
107-
onClick={() => window.open(EXTERNAL_LINKS.devfolio, '_blank')}
108-
>
109-
<Image
110-
src="/images/devwhite-removebg-preview.png"
111-
alt="DEVFOLIO LOGO"
112-
width={44}
113-
height={44}
114-
className="object-contain"
152+
<div className="w-full flex justify-center">
153+
<div
154+
ref={devfolioContainerRef}
155+
className="apply-button"
156+
data-hackathon-slug="opencode25"
157+
data-button-theme="dark"
158+
style={{ height: '44px', width: '312px' }}
159+
aria-label="Apply with Devfolio"
115160
/>
116-
Apply with Devfolio
117-
</Button>
161+
{!devfolioButtonVisible && (
162+
<Button
163+
variant="devfolio"
164+
size="default"
165+
className="absolute w-[312px] h-[44px] font-semibold gap-1.5"
166+
onClick={() =>
167+
window.open(EXTERNAL_LINKS.devfolio, '_blank')
168+
}
169+
>
170+
Apply with Devfolio
171+
</Button>
172+
)}
173+
</div>
118174
</div>
119175

120176
<Button

0 commit comments

Comments
 (0)