feat: add TypingRoomIntro component and integrate it into Home page

This commit is contained in:
Space-Banane
2026-04-12 17:04:49 +02:00
parent 8d2548c74c
commit 3c020928b3
3 changed files with 328 additions and 94 deletions
+97 -82
View File
@@ -11,7 +11,8 @@ import { MiniProjectModal } from "../components/MiniProjectModal";
import { Navbar } from "../components/Navbar";
import { Footer } from "../sections/Footer";
import { TechStack } from "../sections/TechStack";
import { useState } from "react";
import { TypingRoomIntro } from "../components/TypingRoomIntro";
import { useCallback, useEffect, useState } from "react";
import type { Experience } from "../types";
export default function Home() {
@@ -24,12 +25,21 @@ export default function Home() {
} = useProfile();
const [showOldNames, setShowOldNames] = useState(false);
const [showTypingIntro, setShowTypingIntro] = useState(true);
const oldUsernames = [
"getspaced (ingame)",
"Space (alternative)",
"Space-Banane (2022-2024)",
];
useEffect(() => {
// keep intro visible on every full page load; no-op here
}, []);
const handleIntroFinish = useCallback(() => {
setShowTypingIntro(false);
}, []);
const groupedExperiences = experiences.reduce(
(acc, exp) => {
if (!acc[exp.type]) acc[exp.type] = [];
@@ -41,95 +51,100 @@ export default function Home() {
return (
<>
<Navbar />
<div className="space-y-24 pb-20 pt-20">
<Hero
glowColor={glowColor}
borderStatus={borderStatus}
displayMessage={displayMessage}
rotatingMessages={rotatingMessages}
statusMessage={statusMessage}
showOldNames={showOldNames}
setShowOldNames={setShowOldNames}
oldUsernames={oldUsernames}
/>
<TypingRoomIntro active={showTypingIntro} onFinish={handleIntroFinish} />
{!showTypingIntro && (
<>
<Navbar />
<div className="space-y-24 pb-20 pt-20">
<Hero
glowColor={glowColor}
borderStatus={borderStatus}
displayMessage={displayMessage}
rotatingMessages={rotatingMessages}
statusMessage={statusMessage}
showOldNames={showOldNames}
setShowOldNames={setShowOldNames}
oldUsernames={oldUsernames}
/>
<WorkExperience realWork={realWork} />
<WorkExperience realWork={realWork} />
<TechStack />
<TechStack />
<section className="w-full max-w-6xl mx-auto space-y-12 px-4">
<div className="text-center space-y-4">
<h2 className="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
Featured Projects
</h2>
<p className="text-gray-400 max-w-2xl mx-auto">
A selection of my personal favorites. Many more on my GitHub.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{projects.map((project, index) => (
<ProjectCard key={index} project={project} />
))}
</div>
</section>
<section className="w-full max-w-6xl mx-auto space-y-12 px-4">
<div className="text-center space-y-4">
<h2 className="text-3xl font-bold">More Projects</h2>
<p className="text-gray-400">Smaller projects or tools I've built.</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{miniProjects.map((project, index) => (
<MiniProjectCard
key={index}
project={project}
onClick={() => setSelectedMiniProject(project)}
/>
))}
</div>
</section>
<section className="w-full max-w-6xl mx-auto space-y-12 px-4 pb-20">
<div className="text-center space-y-4">
<h2 className="text-3xl font-bold">Skills & Experience</h2>
<p className="text-gray-400">Things I've worked with over the years.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
{Object.entries(groupedExperiences).map(([type, items]) => (
<div key={type} className="space-y-6">
<h3 className="text-xl font-semibold border-l-4 border-blue-500 pl-4 capitalize">
{type}
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{items.map((exp, index) => (
<ExperienceCard
key={index}
experience={exp}
onClick={() => setSelectedExperience(exp)}
/>
))}
</div>
<section className="w-full max-w-6xl mx-auto space-y-12 px-4">
<div className="text-center space-y-4">
<h2 className="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500">
Featured Projects
</h2>
<p className="text-gray-400 max-w-2xl mx-auto">
A selection of my personal favorites. Many more on my GitHub.
</p>
</div>
))}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{projects.map((project, index) => (
<ProjectCard key={index} project={project} />
))}
</div>
</section>
<section className="w-full max-w-6xl mx-auto space-y-12 px-4">
<div className="text-center space-y-4">
<h2 className="text-3xl font-bold">More Projects</h2>
<p className="text-gray-400">Smaller projects or tools I've built.</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{miniProjects.map((project, index) => (
<MiniProjectCard
key={index}
project={project}
onClick={() => setSelectedMiniProject(project)}
/>
))}
</div>
</section>
<section className="w-full max-w-6xl mx-auto space-y-12 px-4 pb-20">
<div className="text-center space-y-4">
<h2 className="text-3xl font-bold">Skills & Experience</h2>
<p className="text-gray-400">Things I've worked with over the years.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
{Object.entries(groupedExperiences).map(([type, items]) => (
<div key={type} className="space-y-6">
<h3 className="text-xl font-semibold border-l-4 border-blue-500 pl-4 capitalize">
{type}
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{items.map((exp, index) => (
<ExperienceCard
key={index}
experience={exp}
onClick={() => setSelectedExperience(exp)}
/>
))}
</div>
</div>
))}
</div>
</section>
</div>
</section>
</div>
<Footer />
<Footer />
{selectedMiniProject && (
<MiniProjectModal
project={selectedMiniProject}
onClose={() => setSelectedMiniProject(null)}
/>
)}
{selectedExperience && (
<ExperienceModal
experience={selectedExperience}
onClose={() => setSelectedExperience(null)}
/>
{selectedMiniProject && (
<MiniProjectModal
project={selectedMiniProject}
onClose={() => setSelectedMiniProject(null)}
/>
)}
{selectedExperience && (
<ExperienceModal
experience={selectedExperience}
onClose={() => setSelectedExperience(null)}
/>
)}
</>
)}
</>
);