personal website
1import type { RefObject } from "react"
2import { personalInfo, currentRole, skills } from "../../data/portfolio"
3
4interface HeaderProps {
5 sectionRef: (el: HTMLElement | null) => void
6}
7
8export function Header({ sectionRef }: HeaderProps) {
9 const scrollToWork = () => {
10 document.getElementById('work')?.scrollIntoView({ behavior: 'smooth' })
11 }
12
13 return (
14 <header id="intro" ref={sectionRef} className="min-h-screen flex items-center opacity-0 relative">
15 {/* Background Image - Full Width */}
16 <div
17 className="absolute top-0 bottom-0 left-1/2 right-1/2 -ml-[50vw] -mr-[50vw] w-screen z-0"
18 style={{
19 backgroundImage: 'url(https://cdn.donmai.us/original/31/2f/__kazusa_blue_archive_drawn_by_astelia__312fc11a21c5d4ce06dc3aa8bfbb7221.jpg)',
20 backgroundSize: 'cover',
21 backgroundPosition: 'center',
22 backgroundRepeat: 'no-repeat',
23 }}
24 >
25 {/* Overlay for better text readability */}
26 <div className="absolute inset-0 bg-background/70"></div>
27 </div>
28
29 <div className="grid lg:grid-cols-5 gap-12 sm:gap-16 w-full relative z-10">
30 <div className="lg:col-span-3 space-y-6 sm:space-y-8">
31 <div className="space-y-3 sm:space-y-2">
32 <div className="text-sm text-gray-300 font-mono tracking-wider">PORTFOLIO / 2025</div>
33 <h1 className="text-md sm:text-md lg:text-4xl font-light tracking-tight text-cyan-400">
34 {personalInfo.name.first}
35 <br />
36 <span className=" text-gray-400">{personalInfo.name.last}</span>
37 </h1>
38 </div>
39
40 <div className="space-y-6 max-w-md">
41 <p className="text-lg sm:text-xl text-stone-200 leading-relaxed">
42 {personalInfo.description.map((part, i) => {
43 if (part.url) {
44 return (
45 <a
46 key={i}
47 href={part.url}
48 target="_blank"
49 rel="noopener noreferrer"
50 className="text-cyan-400/70 hover:text-cyan-300 font-medium transition-colors duration-300 underline decoration-cyan-400/30 hover:decoration-cyan-300/50"
51 >
52 {part.text}
53 </a>
54 )
55 }
56
57 if (part.bold) {
58 return (
59 <span key={i} className="text-white font-medium">
60 {part.text}
61 </span>
62 )
63 }
64
65 return part.text
66 })}
67 </p>
68
69 <div className="space-y-4">
70 <div className="flex items-center gap-2 text-sm text-gray-300">
71 <div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
72 {personalInfo.availability.status}
73 </div>
74 <div className="flex items-center gap-4">
75 <a
76 href={`mailto:${personalInfo.contact.email}`}
77 className="glass glass-hover px-6 py-3 rounded-lg transition-all duration-300 inline-flex items-center justify-center gap-2 text-sm text-gray-300 hover:text-white flex-1"
78 >
79 <svg
80 className="w-4 h-4"
81 fill="none"
82 stroke="currentColor"
83 viewBox="0 0 24 24"
84 strokeWidth={2}
85 >
86 <path
87 strokeLinecap="round"
88 strokeLinejoin="round"
89 d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
90 />
91 </svg>
92 Email me
93 </a>
94 <a
95 href="https://nekomimi.leaflet.pub"
96 target="_blank"
97 rel="noopener noreferrer"
98 className="glass glass-hover px-6 py-3 rounded-lg transition-all duration-300 inline-flex items-center justify-center gap-2 text-sm text-gray-300 hover:text-white flex-1"
99 >
100 <svg
101 className="w-4 h-4"
102 fill="none"
103 stroke="currentColor"
104 viewBox="0 0 24 24"
105 strokeWidth={2}
106 >
107 <path
108 strokeLinecap="round"
109 strokeLinejoin="round"
110 d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
111 />
112 </svg>
113 Read my blog
114 </a>
115 </div>
116 </div>
117 </div>
118 </div>
119
120 <div className="lg:col-span-2 flex flex-col justify-end space-y-6 sm:space-y-8 mt-8 lg:mt-0">
121 <div className="space-y-4">
122 <div className="text-sm text-gray-300 font-mono">CURRENTLY</div>
123 <div className="space-y-2">
124 <div className="text-white">{currentRole.title}</div>
125 <div className="text-sm text-gray-300">{personalInfo.availability.location}</div>
126 <div className="text-gray-300">@ {currentRole.company}</div>
127 <div className="text-xs text-gray-100">{currentRole.period}</div>
128 </div>
129 </div>
130
131 <div className="space-y-4">
132 <div className="text-sm text-gray-300 font-mono">FOCUS</div>
133 <div className="flex flex-wrap gap-2">
134 {skills.map((skill) => (
135 <span
136 key={skill}
137 className="glass glass-hover px-3 py-1 text-xs rounded-full transition-colors duration-300"
138 >
139 {skill}
140 </span>
141 ))}
142 </div>
143 </div>
144 </div>
145 </div>
146
147 {/* Image Source Link */}
148 <a
149 href="https://danbooru.donmai.us/posts/9959832"
150 target="_blank"
151 rel="noopener noreferrer"
152 className="absolute bottom-8 right-8 glass glass-hover p-2 rounded-lg transition-all duration-300 z-20 text-xs dark:text-gray-400 text-gray-600 hover:dark:text-gray-200 hover:text-gray-800"
153 aria-label="View image source"
154 >
155 <svg
156 className="w-4 h-4 inline-block mr-1"
157 fill="none"
158 stroke="currentColor"
159 viewBox="0 0 24 24"
160 strokeWidth={2}
161 >
162 <path
163 strokeLinecap="round"
164 strokeLinejoin="round"
165 d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
166 />
167 </svg>
168 Source
169 </a>
170
171 {/* Scroll Down Arrow */}
172 <button
173 onClick={scrollToWork}
174 className="absolute bottom-8 left-1/2 -translate-x-1/2 glass glass-hover p-3 rounded-full animate-bounce-slow transition-all duration-300 z-20"
175 aria-label="Scroll to work section"
176 >
177 <svg
178 className="w-5 h-5 text-gray-300"
179 fill="none"
180 stroke="currentColor"
181 viewBox="0 0 24 24"
182 strokeWidth={2}
183 >
184 <path
185 strokeLinecap="round"
186 strokeLinejoin="round"
187 d="M19 14l-7 7m0 0l-7-7m7 7V3"
188 />
189 </svg>
190 </button>
191 </header>
192 )
193}