Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 52 additions & 7 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// src/App.js
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file comment says "src/App.js" but the file is named "App.jsx". Update the comment to match the actual filename.

Suggested change
// src/App.js
// src/App.jsx

Copilot uses AI. Check for mistakes.

import React from 'react';
import React, { useEffect } from 'react';
import GlobalStyles from './styles/GlobalStyles';
import Header from './Components/Header';
import AboutMe from './Components/AboutMe';
Expand All @@ -12,18 +12,63 @@ import Contact from './Components/Contact';
import Footer from './Components/Footer';
import GithubRepos from './Components/GithubRepos';
import ProjectsWithGithub from './Components/ProjectsWithGithub';
import ScrollReveal from './Components/ScrollReveal';

function App() {
useEffect(() => {
let ticking = false;

const updateScrollProgress = () => {
const maxScroll =
document.documentElement.scrollHeight - window.innerHeight;
const progress = maxScroll > 0 ? window.scrollY / maxScroll : 0;
document.documentElement.style.setProperty(
'--scroll-progress',
progress.toFixed(4)
);
};

const handleScroll = () => {
if (ticking) return;
ticking = true;
window.requestAnimationFrame(() => {
updateScrollProgress();
ticking = false;
});
};

updateScrollProgress();
window.addEventListener('scroll', handleScroll, { passive: true });
window.addEventListener('resize', handleScroll);
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resize event listener should use the passive option for better scroll performance, similar to the scroll listener. Resize handlers that don't call preventDefault can benefit from being marked as passive.

Suggested change
window.addEventListener('resize', handleScroll);
window.addEventListener('resize', handleScroll, { passive: true });

Copilot uses AI. Check for mistakes.

return () => {
window.removeEventListener('scroll', handleScroll);
window.removeEventListener('resize', handleScroll);
};
}, []);

return (
<>
<GlobalStyles />
<Header />
<Skills />
<ProjectsWithGithub />
<Experience />
<Certifications />
<Contact />
<Footer />
<ScrollReveal>
<Skills />
</ScrollReveal>
<ScrollReveal delay={0.1}>
<ProjectsWithGithub />
</ScrollReveal>
<ScrollReveal delay={0.15}>
<Experience />
</ScrollReveal>
<ScrollReveal delay={0.2}>
<Certifications />
</ScrollReveal>
<ScrollReveal delay={0.25}>
<Contact />
</ScrollReveal>
<ScrollReveal delay={0.3}>
<Footer />
</ScrollReveal>
</>
);
}
Expand Down
101 changes: 101 additions & 0 deletions src/Components/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,90 @@ const HeaderSection = styled.section`
padding: 3rem;
background-color: #f8f8f8;
min-height: 80vh;
position: relative;
overflow: hidden;
`;

const HeroScene = styled.div`
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
perspective: 1200px;
z-index: 0;
transform: translateY(calc(var(--scroll-progress) * 30px));
`;

const Orb = styled.div`
position: relative;
width: 220px;
height: 220px;
transform-style: preserve-3d;
animation: orbSpin 14s linear infinite;
opacity: 0.65;

&::before {
content: '';
position: absolute;
inset: 25px;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.9), rgba(255, 111, 97, 0.25));
box-shadow: 0 0 40px rgba(255, 111, 97, 0.2);
transform: translateZ(20px);
}

&::after {
content: '';
position: absolute;
inset: 50px;
border-radius: 50%;
border: 1px solid rgba(255, 111, 97, 0.35);
transform: translateZ(-20px);
}

@keyframes orbSpin {
from {
transform: rotateX(18deg) rotateY(0deg);
}
to {
transform: rotateX(18deg) rotateY(360deg);
}
}
Comment on lines +58 to +65
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keyframes animation is defined inside the styled component definition. While this works, it creates duplicate keyframe definitions in the generated CSS each time the component is used. Move the keyframes definition outside the styled component using styled-components' keyframes helper to avoid duplication and improve performance.

Copilot uses AI. Check for mistakes.
`;

const Ring = styled.span`
position: absolute;
inset: 25px;
border-radius: 50%;
border: 1px solid rgba(51, 51, 51, 0.15);
transform-style: preserve-3d;
animation: ringFloat 7s ease-in-out infinite;

&:nth-child(1) {
transform: rotateX(65deg) rotateZ(20deg) translateZ(25px);
}

&:nth-child(2) {
transform: rotateY(75deg) rotateZ(-15deg) translateZ(-10px);
animation-delay: 1.5s;
}

&:nth-child(3) {
transform: rotateX(80deg) rotateZ(80deg) translateZ(10px);
animation-delay: 3s;
}
Comment on lines +76 to +88
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The animation on the Ring component will not work as intended. The nth-child selectors apply static transforms that override the animation property. The ringFloat animation will be superseded by the transform declarations in the nth-child rules. Either remove the transform from nth-child selectors and apply them via CSS variables in the animation, or use a different approach to differentiate the rings.

Copilot uses AI. Check for mistakes.

@keyframes ringFloat {
0%,
100% {
filter: drop-shadow(0 0 8px rgba(255, 111, 97, 0.2));
}
50% {
filter: drop-shadow(0 0 18px rgba(73, 135, 255, 0.3));
}
}
Comment on lines +90 to +98
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keyframes animation is defined inside the styled component definition. While this works, it creates duplicate keyframe definitions in the generated CSS each time the component is used. Move the keyframes definition outside the styled component using styled-components' keyframes helper to avoid duplication and improve performance.

Copilot uses AI. Check for mistakes.
`;

const ProfileImage = styled.img`
Expand All @@ -21,13 +105,17 @@ const ProfileImage = styled.img`
object-fit: cover;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
margin-bottom: 1.5rem;
position: relative;
z-index: 1;
`;

const Name = styled.h1`
font-size: 2.5rem;
font-weight: bold;
color: #333;
margin-bottom: 1rem;
position: relative;
z-index: 1;
`;

const Description = styled.p`
Expand All @@ -36,12 +124,16 @@ const Description = styled.p`
line-height: 1.6;
max-width: 600px;
margin-bottom: 2rem;
position: relative;
z-index: 1;
`;

const ButtonContainer = styled.div`
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
position: relative;
z-index: 1;

a {
text-decoration: none;
Expand Down Expand Up @@ -75,6 +167,8 @@ const ConnectSection = styled.div`
display: flex;
gap: 1rem;
justify-content: center;
position: relative;
z-index: 1;

a {
color: #ff6f61;
Expand All @@ -90,6 +184,13 @@ const ConnectSection = styled.div`
const Header = () => {
return (
<HeaderSection>
<HeroScene>
<Orb>
<Ring />
<Ring />
<Ring />
</Orb>
</HeroScene>
Comment on lines +187 to +193
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 3D orb and rings are purely decorative but may confuse screen reader users. Add aria-hidden="true" to the HeroScene component to hide it from assistive technologies.

Copilot uses AI. Check for mistakes.
Comment on lines +187 to +193
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HeroScene, Orb, and Ring elements are decorative and use pointer-events: none, but they should have aria-hidden="true" to ensure screen readers skip them entirely. Consider adding this attribute to the HeroScene component to improve accessibility.

Copilot uses AI. Check for mistakes.
<ProfileImage src={profilePic} alt="Yasar Nazzarian" />
<Name>Yasar Nazzarian</Name>
<Description>
Expand Down
21 changes: 21 additions & 0 deletions src/Components/ScrollReveal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { motion } from 'framer-motion';

const ScrollReveal = ({ children, delay = 0 }) => {
return (
<motion.div
initial={{ opacity: 0, y: 24, scale: 0.98 }}
whileInView={{ opacity: 1, y: 0, scale: 1 }}
viewport={{ once: true, amount: 0.25 }}
transition={{
duration: 0.6,
ease: [0.22, 1, 0.36, 1],
delay,
}}
>
{children}
</motion.div>
);
};

export default ScrollReveal;
52 changes: 52 additions & 0 deletions src/styles/GlobalStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,63 @@
import { createGlobalStyle } from 'styled-components';

const GlobalStyles = createGlobalStyle`
:root {
--scroll-progress: 0;
}

body {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial', sans-serif;
background-color: #f8f8f8;
color: #222;
}

body::before,
body::after {
content: '';
position: fixed;
inset: -20%;
pointer-events: none;
z-index: -1;
transition: transform 0.25s ease-out;
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using both transform and transition on pseudo-elements that update via CSS custom properties can cause layout thrashing. Since --scroll-progress changes frequently during scrolling, the transition: transform 0.25s will attempt to animate every scroll update, creating a laggy effect. Consider removing the transition property to allow transforms to update smoothly with the scroll position, or use will-change: transform to optimize rendering.

Suggested change
transition: transform 0.25s ease-out;
will-change: transform;

Copilot uses AI. Check for mistakes.
}

body::before {
background: radial-gradient(circle at top, rgba(255, 255, 255, 0.85), transparent 60%),
radial-gradient(circle at 25% 20%, rgba(255, 111, 97, 0.25), transparent 55%),
radial-gradient(circle at 80% 10%, rgba(73, 135, 255, 0.2), transparent 45%);
transform: translate3d(
0,
calc(var(--scroll-progress) * 80px),
0
)
scale(1.02);
filter: blur(0px);
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The blur filter is set to 0px which has no effect. Either remove this line if no blur is intended, or set it to a non-zero value if a blur effect is desired.

Suggested change
filter: blur(0px);

Copilot uses AI. Check for mistakes.
}

body::after {
background: linear-gradient(
120deg,
rgba(255, 255, 255, 0.8) 0%,
rgba(248, 248, 248, 0.9) 45%,
rgba(240, 240, 240, 0.9) 100%
),
repeating-linear-gradient(
135deg,
rgba(0, 0, 0, 0.035) 0,
rgba(0, 0, 0, 0.035) 1px,
transparent 1px,
transparent 12px
);
opacity: 0.25;
transform: translate3d(
0,
calc(var(--scroll-progress) * -60px),
0
)
rotate(calc(var(--scroll-progress) * 2deg));
}

Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users with vestibular motion disorders may experience discomfort from the scroll-driven parallax effects on the backdrop pseudo-elements. Consider adding a prefers-reduced-motion media query to disable the transform animations for users who have requested reduced motion in their system settings.

Suggested change
@media (prefers-reduced-motion: reduce) {
body::before,
body::after {
transition: none;
transform: none;
}
}

Copilot uses AI. Check for mistakes.
h2 {
Expand Down
Loading