Skip to content

Commit 2a0edc4

Browse files
committed
feat: add new sections for bio, skills, projects, and contact; implement fade-in animation
1 parent 4d44d2e commit 2a0edc4

File tree

8 files changed

+171
-179
lines changed

8 files changed

+171
-179
lines changed

src/components/BioSection.astro

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
3+
---
4+
5+
<section id="bio" class="py-8 scroll-mt-20 visible-animate">
6+
<h2 class="mb-12 text-center text-3xl font-medium visible-animate">About Me</h2>
7+
<div class="mx-auto bg-grayblue-800 p-8 rounded-lg shadow-lg visible-animate">
8+
<p class="text-lg leading-relaxed text-grayblue-300 visible-animate">
9+
With a passion for technology and over eight years of experience in web development, I've dedicated myself to adopting and implementing the latest industry trends and tools. My portfolio includes a diverse range of cloud projects spanning websites, mobile applications, and desktop software.
10+
</p>
11+
<p class="text-lg leading-relaxed text-grayblue-300 mt-4 visible-animate">
12+
As a self-taught perfectionist and natural leader, I bring strong problem-solving abilities to every project I undertake. My consistently positive, motivating, and inclusive approach enables me to thrive in collaborative environments where knowledge sharing is valued.
13+
</p>
14+
<p class="text-lg leading-relaxed text-grayblue-300 mt-4 visible-animate">
15+
Beyond the professional realm, I find balance through music, sports, and quality time with family.
16+
</p>
17+
</div>
18+
</section>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
---
3+
4+
<section id="contact" class="py-8 scroll-mt-20 visible-animate">
5+
<h2 class="mb-12 text-center text-3xl text-grayblue-100 font-medium visible-animate">Get in Touch</h2>
6+
<div class="flex justify-center visible-animate">
7+
<div class="tidycal-embed visible-animate" data-path="jperusm/15-minute-meeting"></div>
8+
<script src="https://asset-tidycal.b-cdn.net/js/embed.js" async></script>
9+
</div>
10+
</section>

src/components/HomeSection.astro

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
import socialNetworks from '@/assets/data/social-networks.json'
3+
import { Image } from 'astro:assets'
4+
import profilePicture from '@/assets/images/profile.png'
5+
---
6+
<section id="home" class="py-8 scroll-mt-20">
7+
<div class="flex flex-col items-center lg:flex-row lg:justify-between">
8+
<div class="mb-8 text-center lg:mb-0 lg:text-left lg:w-1/2">
9+
<h1 class="mb-4 text-5xl font-medium animate-fade-up animate-delay-300">Jonas Perusquia Morales</h1>
10+
<h2 class="mb-6 text-2xl font-light text-blue-300 animate-fade-up animate-delay-600">Chief Technology Officer</h2>
11+
<p class="max-w-2xl text-xl text-grayblue-300 animate-fade-up animate-delay-900">
12+
Innovative tech leader with a passion for building scalable solutions and fostering high-performing teams.
13+
</p>
14+
<div class="flex gap-4 mt-6 justify-center lg:justify-start animate-fade-up animate-delay-1200">
15+
{socialNetworks.map(socialNetwork => (
16+
<a aria-label={socialNetwork.name} href={socialNetwork.url} class="text-grayblue-300 hover:text-blue-300 transition-transform hover:scale-110">
17+
<div class="h-6 w-6">
18+
<Fragment set:html={socialNetwork.image} />
19+
</div>
20+
</a>
21+
))}
22+
</div>
23+
</div>
24+
<div class="relative h-64 w-64 overflow-hidden rounded-full border-4 border-blue-300 lg:h-80 lg:w-80 animate-fade-up animate-delay-1600">
25+
<Image
26+
src={profilePicture}
27+
alt="Jonas Perusquia Morales"
28+
width={320}
29+
height={320}
30+
class="rounded-full object-cover"
31+
loading="eager"
32+
/>
33+
</div>
34+
</div>
35+
<div class="mt-12 animate-bounce text-center">
36+
<span class="material-symbols-rounded mx-auto text-5xl! text-blue-300 rotate-90">chevron_right</span>
37+
</div>
38+
</section>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
import { getImage } from 'astro:assets'
3+
import sorteosClickImage from '@/assets/images/sorteos.click.png'
4+
import autosolutionsImage from '@/assets/images/autosolutions.mx.png'
5+
import enerlinqImage from '@/assets/images/enerlinq.com.png'
6+
import gerardoAncerImage from '@/assets/images/gerardoancer.com.png'
7+
import hackcuuImage from '@/assets/images/hackcuu.com.png'
8+
9+
const projects = [
10+
{
11+
name: 'Enerlinq',
12+
url: 'https://enerlinq.com',
13+
description: 'Technology and innovation consulting company.',
14+
image: await getImage({ src: enerlinqImage }),
15+
},
16+
{
17+
name: 'Autosolutions',
18+
url: 'https://autosolutions.mx',
19+
description: 'On-demand auto parts for your vehicle & more.',
20+
image: await getImage({ src: autosolutionsImage }),
21+
},
22+
{
23+
name: 'Sorteos Click',
24+
url: 'https://sorteos.click',
25+
description: 'Create and manage your own raffles for free.',
26+
image: await getImage({ src: sorteosClickImage }),
27+
},
28+
{
29+
name: 'Gerardo Ancer',
30+
url: 'https://gerardoancer.com',
31+
description: 'Portfolio website for graphic designer Gerardo Ancer.',
32+
image: await getImage({ src: gerardoAncerImage }),
33+
},
34+
{
35+
name: 'HackCUU 2017',
36+
url: 'https://facebook.com/hackcuu2',
37+
description: 'HackCUU 2017 MLH hackathon lead organizer.',
38+
image: await getImage({ src: hackcuuImage }),
39+
},
40+
]
41+
---
42+
<section id="projects" class="py-8 scroll-mt-20 visible-animate">
43+
<h2 class="mb-12 text-center text-3xl font-medium visible-animate">Featured Projects</h2>
44+
<div class="grid gap-8 md:grid-cols-2 visible-animate">
45+
{projects.map(project =>
46+
<a href={project.url} class="rounded-lg bg-grayblue-800 p-6 shadow-lg scale-image grid md:grid-cols-2 gap-4 visible-animate">
47+
<div id="project-info" class="flex flex-col gap-3 visible-animate">
48+
<h3 class="text-xl font-semibold text-blue-300 visible-animate">{ project.name }</h3>
49+
<p class="text-grayblue-300 visible-animate">{ project.description }</p>
50+
</div>
51+
<div class="project-image self-center visible-animate">
52+
<div class="overflow-hidden aspect-video rounded-lg visible-animate">
53+
<img loading="lazy" class="duration-300 transition-all aspect-video visible-animate" src={ project.image.src } alt={ project.name } />
54+
</div>
55+
</div>
56+
</a>
57+
)}
58+
</div>
59+
</section>

src/components/SkillsSection.astro

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
import skills from '@/assets/data/skills.json'
3+
---
4+
<section id="skills" class="py-8 scroll-mt-20 visible-animate">
5+
<h2 class="mb-12 text-center text-3xl font-medium visible-animate">Skills & Expertise</h2>
6+
<div class="grid grid-cols-2 gap-8 md:grid-cols-4 visible-animate">
7+
{skills.map((skill: string) => (
8+
<div class="rounded-lg bg-grayblue-800 p-6 text-center shadow-lg transition-all duration-300 hover:bg-slate-700 hover:scale-110 flex items-center justify-center visible-animate">
9+
<p class="text-lg text-center break-words hyphens-auto font-medium visible-animate">{skill}</p>
10+
</div>
11+
))}
12+
</div>
13+
</section>

src/pages/index.astro

Lines changed: 11 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,150 +1,24 @@
11
---
2-
import { getImage, Image } from 'astro:assets'
32
import Layout from '@/layouts/Layout.astro'
4-
import socialNetworks from '@/assets/data/social-networks.json'
5-
import skills from '@/assets/data/skills.json'
6-
7-
import sorteosClickImage from '@/assets/images/sorteos.click.png'
8-
import autosolutionsImage from '@/assets/images/autosolutions.mx.png'
9-
import enerlinqImage from '@/assets/images/enerlinq.com.png'
10-
import gerardoAncerImage from '@/assets/images/gerardoancer.com.png'
11-
import hackcuuImage from '@/assets/images/hackcuu.com.png'
12-
import profilePicture from '@/assets/images/profile.png'
13-
14-
const projects = [
15-
{
16-
name: 'Enerlinq',
17-
url: 'https://enerlinq.com',
18-
description: 'Technology and innovation consulting company.',
19-
image: await getImage({ src: enerlinqImage }),
20-
},
21-
{
22-
name: 'Autosolutions',
23-
url: 'https://autosolutions.mx',
24-
description: 'On-demand auto parts for your vehicle & more.',
25-
image: await getImage({ src: autosolutionsImage }),
26-
},
27-
{
28-
name: 'Sorteos Click',
29-
url: 'https://sorteos.click',
30-
description: 'Create and manage your own raffles for free.',
31-
image: await getImage({ src: sorteosClickImage }),
32-
},
33-
{
34-
name: 'Gerardo Ancer',
35-
url: 'https://gerardoancer.com',
36-
description: 'Portfolio website for graphic designer Gerardo Ancer.',
37-
image: await getImage({ src: gerardoAncerImage }),
38-
},
39-
{
40-
name: 'HackCUU 2017',
41-
url: 'https://facebook.com/hackcuu2',
42-
description: 'HackCUU 2017 MLH hackathon lead organizer.',
43-
image: await getImage({ src: hackcuuImage }),
44-
},
45-
]
46-
3+
import HomeSection from '@/components/HomeSection.astro'
4+
import BioSection from '@/components/BioSection.astro'
5+
import SkillsSection from '@/components/SkillsSection.astro'
6+
import ProjectsSection from '@/components/ProjectsSection.astro'
7+
import ContactSection from '@/components/ContactSection.astro'
478
---
489

4910
<Layout title="Jonas Perusquia Morales">
5011
<main class="max-w-7xl mx-auto px-6 pt-14 xs:pt-20">
5112
<div class="flex flex-col gap-y-20">
52-
<!-- HOME SECTION -->
53-
<section id="home" class="py-8 scroll-mt-20">
54-
<div class="flex flex-col items-center lg:flex-row lg:justify-between">
55-
<div class="mb-8 text-center lg:mb-0 lg:text-left lg:w-1/2">
56-
<h1 class="mb-4 text-5xl font-medium animate-fade-up animate-delay-300">Jonas Perusquia Morales</h1>
57-
<h2 class="mb-6 text-2xl font-light text-blue-300 animate-fade-up animate-delay-600">Chief Technology Officer</h2>
58-
<p class="max-w-2xl text-xl text-grayblue-300 animate-fade-up animate-delay-900">
59-
Innovative tech leader with a passion for building scalable solutions and fostering high-performing teams.
60-
</p>
61-
<div class="flex gap-4 mt-6 justify-center lg:justify-start animate-fade-up animate-delay-1200">
62-
{
63-
socialNetworks.map(socialNetwork => (
64-
<a aria-label={socialNetwork.name} href={socialNetwork.url} class="text-grayblue-300 hover:text-blue-300 transition-transform hover:scale-110">
65-
<div class="h-6 w-6">
66-
<Fragment set:html={socialNetwork.image} />
67-
</div>
68-
</a>
69-
))
70-
}
71-
</div>
72-
</div>
73-
<div class="relative h-64 w-64 overflow-hidden rounded-full border-4 border-blue-300 lg:h-80 lg:w-80 animate-fade-up animate-delay-1600">
74-
<Image
75-
src={profilePicture}
76-
alt="Jonas Perusquia Morales"
77-
width={320}
78-
height={320}
79-
class="rounded-full object-cover"
80-
loading="eager"
81-
/>
82-
</div>
83-
</div>
84-
<div class="mt-12 animate-bounce text-center">
85-
<span class="material-symbols-rounded mx-auto text-5xl! text-blue-300 rotate-90">chevron_right</span>
86-
</div>
87-
</section>
88-
89-
<!-- BIO SECTION -->
90-
<section id="bio" class="py-8 scroll-mt-20">
91-
<h2 class="mb-12 text-center text-3xl font-medium">About Me</h2>
92-
<div class="mx-auto bg-grayblue-800 p-8 rounded-lg shadow-lg">
93-
<p class="text-lg leading-relaxed text-grayblue-300">
94-
With a passion for technology and over eight years of experience in web development, I've dedicated myself to adopting and implementing the latest industry trends and tools. My portfolio includes a diverse range of cloud projects spanning websites, mobile applications, and desktop software.
95-
</p>
96-
<p class="text-lg leading-relaxed text-grayblue-300 mt-4">
97-
As a self-taught perfectionist and natural leader, I bring strong problem-solving abilities to every project I undertake. My consistently positive, motivating, and inclusive approach enables me to thrive in collaborative environments where knowledge sharing is valued.
98-
</p>
99-
<p class="text-lg leading-relaxed text-grayblue-300 mt-4">
100-
Beyond the professional realm, I find balance through music, sports, and quality time with family.
101-
</p>
102-
</div>
103-
</section>
104-
105-
<section id="skills" class="py-8 scroll-mt-20">
106-
<h2 class="mb-12 text-center text-3xl font-medium">Skills & Expertise</h2>
107-
<div class="grid grid-cols-2 gap-8 md:grid-cols-4">
108-
{skills.map((skill) => (
109-
<div class="rounded-lg bg-grayblue-800 p-6 text-center shadow-lg transition-all duration-300 hover:bg-slate-700 hover:scale-110 flex items-center justify-center">
110-
<p class="text-lg text-center break-words hyphens-auto font-medium">{skill}</p>
111-
</div>
112-
))}
113-
</div>
114-
</section>
115-
116-
<section id="projects" class="py-8 scroll-mt-20">
117-
<h2 class="mb-12 text-center text-3xl font-medium">Featured Projects</h2>
118-
<div class="grid gap-8 md:grid-cols-2">
119-
{
120-
projects.map(project =>
121-
<a href={project.url} class="rounded-lg bg-grayblue-800 p-6 shadow-lg scale-image grid md:grid-cols-2 gap-4">
122-
<div id="project-info" class="flex flex-col gap-3">
123-
<h3 class="text-xl font-semibold text-blue-300">{ project.name }</h3>
124-
<p class="text-grayblue-300">{ project.description }</p>
125-
</div>
126-
<div class="project-image self-center">
127-
<div class="overflow-hidden aspect-video rounded-lg">
128-
<img loading="lazy" class="duration-300 transition-all aspect-video " src={ project.image.src } alt={ project.name }></img>
129-
</div>
130-
</div>
131-
</a>
132-
)
133-
}
134-
</div>
135-
</section>
136-
137-
<!-- GET IN TOUCH SECTION -->
138-
<section id="contact" class="py-8 scroll-mt-20">
139-
<h2 class="mb-12 text-center text-3xl text-grayblue-100 font-medium">Get in Touch</h2>
140-
<div class="flex justify-center">
141-
<div class="tidycal-embed" data-path="jperusm/15-minute-meeting"></div><script src="https://asset-tidycal.b-cdn.net/js/embed.js" async></script>
142-
</div>
143-
</section>
13+
<HomeSection />
14+
<BioSection />
15+
<SkillsSection />
16+
<ProjectsSection />
17+
<ContactSection />
14418
</div>
14519
</main>
146-
14720
<footer class="bg-grayblue-800 py-6 text-center text-sm text-grayblue-400">
14821
<p>Made with ♥️ from Chihuahua, Mexico.</p>
14922
</footer>
23+
<script type="module" src="/src/scripts/fade-in-observer.js"></script>
15024
</Layout>

src/scripts/fade-in-observer.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// src/scripts/fade-in-observer.js
2+
export function observeFadeIn(selector = '.visible-animate') {
3+
if (typeof window === 'undefined' || !('IntersectionObserver' in window)) return;
4+
const elements = document.querySelectorAll(selector);
5+
const observer = new window.IntersectionObserver((entries, obs) => {
6+
entries.forEach(entry => {
7+
if (entry.isIntersecting) {
8+
entry.target.classList.remove('opacity-0');
9+
entry.target.classList.add('animate-fade-up');
10+
obs.unobserve(entry.target);
11+
}
12+
});
13+
}, { threshold: 0.2 });
14+
elements.forEach(el => {
15+
el.classList.add('opacity-0');
16+
observer.observe(el);
17+
});
18+
}
19+
20+
document.addEventListener('DOMContentLoaded', () => {
21+
observeFadeIn();
22+
});

src/styles/global.css

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -300,48 +300,6 @@
300300
--breakpoint-2xl: 1536px;
301301

302302
--font-sans: Inter, sans-serif;
303-
304-
--animate-skill-background: skill-background-change 300ms ease-in-out 0s 1
305-
both;
306-
--animate-typewriter:
307-
typewriter 8s steps(23) -6s infinite alternate both,
308-
blinkTextCursor 800ms infinite normal;
309-
--animate-fade-in: fadeIn 800ms calc(var(--delay-index) * 0.5s) ease-out
310-
forwards;
311-
--animate-bounce-slow: bounce 3s infinite;
312-
313-
@keyframes fadeIn {
314-
0% {
315-
opacity: 0;
316-
transform: translateY(-30px);
317-
}
318-
100% {
319-
opacity: 1;
320-
transform: translateY(0px);
321-
}
322-
}
323-
@keyframes typewriter {
324-
0% {
325-
width: 0%;
326-
}
327-
37.5% {
328-
width: 0%;
329-
}
330-
62.5% {
331-
width: 100%;
332-
}
333-
100% {
334-
width: 100%;
335-
}
336-
}
337-
@keyframes blinkTextCursor {
338-
from {
339-
border-right-color: rgba(42, 0, 61, 1);
340-
}
341-
to {
342-
border-right-color: transparent;
343-
}
344-
}
345303
}
346304

347305
/*

0 commit comments

Comments
 (0)