feat: add hero section and navigation components
Deploy Portfolio Selfmade / deploy (push) Successful in 31s
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:
@@ -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')}
|
||||
>
|
||||
</> 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';
|
||||
Reference in New Issue
Block a user