feat: add hero section and navigation components
Deploy Portfolio Selfmade / deploy (push) Successful in 31s

- Created HeroSection component for the landing page.
- Implemented Navigation component with smooth scrolling to sections.
- Added useNavigation hook to manage active section and scroll state.
- Introduced useScrollToSection hook for smooth scrolling functionality.

feat: add projects section with project cards

- Developed ProjectCard component to display individual project details.
- Created ProjectsSection component to showcase featured projects with filtering options.
- Added sample project data for demonstration.

feat: add skills section with skill cards

- Implemented SkillCard component to display individual skills.
- Created SkillsSection component to showcase skills with category filtering.
- Added sample skills data for demonstration.

style: update global styles and add custom scrollbar

- Imported Urbanist font and set it as the default font.
- Updated body background and text colors.
- Customized scrollbar styles for better aesthetics.

feat: add shared components and constants

- Created AnimatedSection, Button, and Footer components for reusability.
- Added COLORS and GRADIENT constants for consistent theming.
- Updated index files for shared components and hooks.

chore: update dependencies and configuration

- Added framer-motion for animations.
- Updated Tailwind CSS configuration for custom animations and colors.
- Adjusted TypeScript configuration for better path resolution.
This commit is contained in:
2026-05-10 14:34:54 +02:00
parent e85ce6a67b
commit 4ff07915b8
56 changed files with 1602 additions and 16 deletions
@@ -0,0 +1,68 @@
import React from 'react';
import { motion } from 'framer-motion';
import { useNavigation } from '../hooks/useNavigation';
import { useScrollToSection } from '../../../shared/hooks/useScrollToSection';
import Button from '../../../shared/components/Button';
const navItems = [
{ id: 'home', label: 'About' },
{ id: 'skills', label: 'Skills' },
{ id: 'projects', label: 'Projects' },
{ id: 'experience', label: 'Experience' },
{ id: 'contact', label: 'Contact' },
];
export const Navigation: React.FC = () => {
const { activeSection, isScrolled } = useNavigation();
const { scrollToSection } = useScrollToSection();
return (
<motion.nav
initial={{ y: -100 }}
animate={{ y: 0 }}
transition={{ duration: 0.5 }}
className={`fixed top-0 w-full z-50 transition-all duration-300 ${
isScrolled
? 'bg-black/80 backdrop-blur-md border-b border-green-500/20'
: 'bg-transparent'
}`}
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
{/* Logo */}
<motion.div
whileHover={{ scale: 1.05 }}
className="text-2xl font-bold text-green-500 cursor-pointer"
onClick={() => scrollToSection('home')}
>
&lt;/&gt; Alex
</motion.div>
{/* Nav Items */}
<div className="hidden md:flex gap-8">
{navItems.map((item) => (
<motion.button
key={item.id}
onClick={() => scrollToSection(item.id)}
className={`text-sm font-medium transition-colors duration-300 pb-2 border-b-2 ${
activeSection === item.id
? 'text-green-500 border-green-500'
: 'text-gray-300 border-transparent hover:text-white'
}`}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
{item.label}
</motion.button>
))}
</div>
{/* CTA Button */}
<Button variant="primary" size="sm">
Hire Me
</Button>
</div>
</div>
</motion.nav>
);
};
@@ -0,0 +1,30 @@
import { useEffect, useState } from 'react';
export const useNavigation = () => {
const [activeSection, setActiveSection] = useState<string>('home');
const [isScrolled, setIsScrolled] = useState(false);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
// Update active section based on viewport
const sections = ['home', 'skills', 'projects', 'experience', 'contact'];
for (const section of sections) {
const element = document.getElementById(section);
if (element) {
const rect = element.getBoundingClientRect();
if (rect.top < 100 && rect.bottom > 100) {
setActiveSection(section);
break;
}
}
}
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
return { activeSection, isScrolled };
};
@@ -0,0 +1 @@
export { Navigation } from './components/Navigation';