1- import { useEffect } from 'react'
1+ import { useEffect , useState } from 'react'
22import { createPortal } from 'react-dom'
3- import { X , GitFork } from 'lucide-react'
3+ import { X , GitFork , Copy , Check , ExternalLink } from 'lucide-react'
44import HeroSection from '../templates/threejs/HeroSection'
55import GitHubSection from '../templates/threejs/GitHubSection'
66import StatsSection from '../templates/threejs/StatsSection'
@@ -166,9 +166,84 @@ function buildStats(user: PreviewUser, allRepos: PreviewRepo[]) {
166166 }
167167}
168168
169- // ─────────────────────────────────────────────────────────────────────────────
169+ // ── Fork button — copies repo name then opens GitHub fork page ────────────────
170+
171+ const FORK_BASE = 'https://github.com/amide-init/gitfolio/fork'
172+
173+ /**
174+ * Two-step fork flow:
175+ * 1. Show a small panel with the suggested repo name + copy button.
176+ * 2. "Go fork" button opens the GitHub fork page in a new tab.
177+ *
178+ * GitHub's web fork form cannot be pre-filled via URL params, so we give
179+ * the user the name ready to paste.
180+ */
181+ function ForkButton ( { login, className } : { login : string ; className ?: string } ) {
182+ const [ step , setStep ] = useState < 'idle' | 'confirm' > ( 'idle' )
183+ const [ copied , setCopied ] = useState ( false )
184+ const repoName = `${ login } .github.io`
185+
186+ const copy = async ( ) => {
187+ await navigator . clipboard . writeText ( repoName ) . catch ( ( ) => { } )
188+ setCopied ( true )
189+ setTimeout ( ( ) => setCopied ( false ) , 2000 )
190+ }
170191
171- const FORK_URL = 'https://github.com/amide-init/gitfolio/fork'
192+ const goFork = ( ) => {
193+ window . open ( FORK_BASE , '_blank' , 'noreferrer' )
194+ }
195+
196+ if ( step === 'confirm' ) {
197+ return (
198+ < div className = "inline-flex flex-col items-stretch gap-2 rounded-xl border border-indigo-500/30 bg-[#0d1527] p-3 text-left shadow-[0_0_20px_rgba(99,102,241,0.15)]" >
199+ < p className = "text-xs text-zinc-400" >
200+ After forking, set the repository name to:
201+ </ p >
202+ { /* Repo name + copy */ }
203+ < div className = "flex items-center gap-2 rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2" >
204+ < code className = "flex-1 text-sm font-mono font-semibold text-cyan-300" > { repoName } </ code >
205+ < button
206+ type = "button"
207+ onClick = { copy }
208+ className = "flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-zinc-400 hover:text-zinc-100 transition"
209+ >
210+ { copied ? < Check className = "h-3.5 w-3.5 text-green-400" /> : < Copy className = "h-3.5 w-3.5" /> }
211+ { copied ? 'Copied!' : 'Copy' }
212+ </ button >
213+ </ div >
214+ { /* Actions */ }
215+ < div className = "flex gap-2" >
216+ < button
217+ type = "button"
218+ onClick = { ( ) => setStep ( 'idle' ) }
219+ className = "flex-1 rounded-md border border-zinc-700 py-1.5 text-xs text-zinc-400 hover:bg-zinc-800 transition"
220+ >
221+ Back
222+ </ button >
223+ < button
224+ type = "button"
225+ onClick = { goFork }
226+ className = "group relative flex-1 overflow-hidden rounded-md bg-indigo-600 py-1.5 text-xs font-semibold text-white hover:bg-indigo-500 transition flex items-center justify-center gap-1.5"
227+ >
228+ < ExternalLink className = "h-3.5 w-3.5" /> Go fork →
229+ </ button >
230+ </ div >
231+ </ div >
232+ )
233+ }
234+
235+ return (
236+ < button
237+ type = "button"
238+ onClick = { ( ) => setStep ( 'confirm' ) }
239+ className = { className }
240+ >
241+ < GitFork className = "h-3.5 w-3.5" /> Fork & make yours
242+ </ button >
243+ )
244+ }
245+
246+ // ─────────────────────────────────────────────────────────────────────────────
172247
173248type Props = {
174249 user : PreviewUser
@@ -185,12 +260,8 @@ export function PortfolioPreviewModal({ user, repos: _, allRepos, onClose }: Pro
185260 return ( ) => { document . body . style . overflow = prev }
186261 } , [ ] )
187262
188- // Close on Escape
189- useEffect ( ( ) => {
190- const h = ( e : KeyboardEvent ) => { if ( e . key === 'Escape' ) onClose ( ) }
191- window . addEventListener ( 'keydown' , h )
192- return ( ) => window . removeEventListener ( 'keydown' , h )
193- } , [ onClose ] )
263+ // Escape is handled by NavSearch (it dismisses preview first, then closes search)
264+ // No duplicate listener here.
194265
195266 const hero = buildHero ( user , allRepos )
196267 const snapshot = buildSnapshot ( user , allRepos )
@@ -216,14 +287,10 @@ export function PortfolioPreviewModal({ user, repos: _, allRepos, onClose }: Pro
216287 </ span >
217288 </ div >
218289 < div className = "flex items-center gap-2" >
219- < a
220- href = { FORK_URL }
221- target = "_blank"
222- rel = "noreferrer"
290+ < ForkButton
291+ login = { user . login }
223292 className = "hidden sm:inline-flex items-center gap-1.5 rounded-md border border-indigo-500/40 bg-indigo-500/10 px-3 py-1.5 text-xs font-semibold text-indigo-300 transition hover:bg-indigo-500/20"
224- >
225- < GitFork className = "h-3.5 w-3.5" /> Fork & make yours
226- </ a >
293+ />
227294 < button
228295 type = "button"
229296 onClick = { onClose }
@@ -263,22 +330,14 @@ export function PortfolioPreviewModal({ user, repos: _, allRepos, onClose }: Pro
263330 </ span >
264331 </ h2 >
265332 < p className = "mt-2 text-sm text-zinc-500" >
266- Fork the repo, rename it to{ ' ' }
267- < code className = "rounded bg-zinc-800 px-1.5 py-0.5 text-zinc-300" >
268- { '<username>.github.io' }
269- </ code >
270- , and GitHub Actions auto-builds it with your data.
333+ Fork the repo — GitHub Actions will auto-build your portfolio with your GitHub data.
271334 </ p >
272- < a
273- href = { FORK_URL }
274- target = "_blank"
275- rel = "noreferrer"
276- className = "group relative mt-6 inline-flex items-center gap-2 overflow-hidden rounded-xl bg-gradient-to-r from-blue-600 to-cyan-500 px-6 py-3 text-sm font-bold text-white shadow-[0_0_30px_rgba(59,130,246,0.35)] transition hover:shadow-[0_0_40px_rgba(59,130,246,0.55)]"
277- >
278- < span className = "pointer-events-none absolute inset-0 -translate-x-full skew-x-[-20deg] bg-white/20 transition-transform duration-500 group-hover:translate-x-[150%]" />
279- < GitFork className = "h-4 w-4" />
280- Fork this template
281- </ a >
335+ < div className = "mt-6 flex justify-center" >
336+ < ForkButton
337+ login = { user . login }
338+ className = "group relative inline-flex items-center gap-2 overflow-hidden rounded-xl bg-gradient-to-r from-blue-600 to-cyan-500 px-6 py-3 text-sm font-bold text-white shadow-[0_0_30px_rgba(59,130,246,0.35)] transition hover:shadow-[0_0_40px_rgba(59,130,246,0.55)]"
339+ />
340+ </ div >
282341 </ div >
283342 </ section >
284343
0 commit comments