# Revised Smooth Scrolling Implementation Plan for React Portfolio ## Overview Based on the issues encountered with the previous implementation, this revised plan takes a simpler but more reliable approach to create a smooth scrolling portfolio with perfectly contained full-page sections. We'll implement a fullpage.js-inspired solution with proper section sizing, positioning, and transitions. ## Technologies - **React Fullpage**: A simplified custom implementation inspired by fullpage.js - **React Intersection Observer**: To detect when sections enter/exit the viewport - **Framer Motion**: For smooth animations and transitions ## Implementation Steps ### 1. Setup Dependencies ```bash npm install framer-motion react-intersection-observer ``` ### 2. Create FullPage Component #### Create `src/components/FullPage.js` ```javascript import React, { useState, useEffect, useRef } from 'react'; import { motion } from 'framer-motion'; const FullPage = ({ children }) => { const [currentPage, setCurrentPage] = useState(0); const [isScrolling, setIsScrolling] = useState(false); const containerRef = useRef(null); const pagesCount = React.Children.count(children); // Handle page change const goToPage = (pageIndex) => { if (pageIndex >= 0 && pageIndex < pagesCount && !isScrolling) { setIsScrolling(true); setCurrentPage(pageIndex); // Get the corresponding section ID to update URL const sectionId = React.Children.toArray(children)[pageIndex].props.id; window.history.replaceState(null, null, `#${sectionId}`); setTimeout(() => { setIsScrolling(false); }, 1000); // Match this with your transition duration } }; // Handle wheel events const handleWheel = (e) => { if (isScrolling) return; if (e.deltaY > 0) { // Scrolling down goToPage(currentPage + 1); } else { // Scrolling up goToPage(currentPage - 1); } }; // Handle key events const handleKeyDown = (e) => { if (isScrolling) return; if (e.key === 'ArrowDown' || e.key === 'PageDown') { goToPage(currentPage + 1); } else if (e.key === 'ArrowUp' || e.key === 'PageUp') { goToPage(currentPage - 1); } }; // Initialize event listeners useEffect(() => { const container = containerRef.current; if (container) { container.addEventListener('wheel', handleWheel, { passive: false }); window.addEventListener('keydown', handleKeyDown); return () => { container.removeEventListener('wheel', handleWheel); window.removeEventListener('keydown', handleKeyDown); }; } }, [currentPage, isScrolling]); // Check for hash in URL on initial load useEffect(() => { const hash = window.location.hash.substring(1); if (hash) { const childrenArray = React.Children.toArray(children); const initialPageIndex = childrenArray.findIndex(child => child.props.id === hash); if (initialPageIndex !== -1) { setCurrentPage(initialPageIndex); } } }, []); return (
{React.Children.map(children, (child, index) => (
{child}
))}
{/* Pagination Dots */}
{Array.from({ length: pagesCount }).map((_, index) => ( goToPage(index)} /> ))}
); }; export default FullPage; ``` ### 3. Create Section Component #### Create `src/components/Section.js` ```javascript import React from 'react'; import { motion } from 'framer-motion'; const Section = ({ children, id, className = '' }) => { return ( {children} ); }; export default Section; ``` ### 4. Update Navigation Component #### Enhance Header Component Update the header to work with our new FullPage component by handling section navigation. ```javascript // In src/header/index.js import React, { useState, useContext } from 'react'; import "./style.css"; import { RiMenuLine, RiCloseLine } from "react-icons/ri"; import { logotext } from "../content_option"; import Themetoggle from "../components/themetoggle"; import { Socialicons } from "../components/socialicons"; const Headermain = () => { const [isActive, setActive] = useState("false"); const handleToggle = () => { setActive(!isActive); document.body.classList.toggle("ovhidden"); }; const handleNavClick = (e, targetId) => { e.preventDefault(); handleToggle(); // Find all section elements const sections = document.querySelectorAll('.fullpage-section'); const targetSection = Array.from(sections).findIndex( section => section.querySelector(`#${targetId}`) !== null ); // Trigger a custom event that FullPage component will listen for if (targetSection !== -1) { const customEvent = new CustomEvent('navigateTo', { detail: { index: targetSection } }); document.dispatchEvent(customEvent); } }; // The rest of the component remains the same } ``` ### 5. Update App.js Rewrite App.js to use our new FullPage and Section components. ```javascript import React from "react"; import "bootstrap/dist/css/bootstrap.min.css"; import AnimatedCursor from "../hooks/AnimatedCursor"; import Headermain from "../header"; import { Home } from "../pages/home"; import { About } from "../pages/about"; import { Portfolio } from "../pages/portfolio"; import { ContactUs } from "../pages/contact"; import { Socialicons } from "../components/socialicons"; import FullPage from "../components/FullPage"; import Section from "../components/Section"; import "./App.css"; export default function App() { return (
); } ``` ### 6. Add Necessary CSS Styles #### Update `src/app/App.css` ```css /* Reset styles */ * { margin: 0; padding: 0; box-sizing: border-box; } html, body { overflow: hidden; position: fixed; height: 100%; width: 100%; } /* Full page styles */ .app-container { position: relative; width: 100%; height: 100vh; overflow: hidden; } .fullpage-container { position: absolute; top: 0; left: 0; width: 100%; height: 100vh; overflow: hidden; } .fullpage-section { position: relative; width: 100%; height: 100vh; overflow: hidden; } .fullpage-section-content { padding-top: 60px; /* Account for header */ width: 100%; height: 100%; } /* Navigation dots */ .fullpage-pagination { position: fixed; right: 20px; top: 50%; transform: translateY(-50%); z-index: 100; display: flex; flex-direction: column; gap: 15px; } .pagination-dot { width: 10px; height: 10px; border-radius: 50%; background-color: var(--text-color, #fff); cursor: pointer; transition: all 0.3s ease; } .pagination-dot.active { transform: scale(1.2); } /* Make sure header is above fullpage */ .site__header { z-index: 1000; } /* Social icons positioning */ .stick_follow_icon { position: fixed; bottom: 0; left: 0; z-index: 1000; } /* Responsive styles */ @media (max-width: 768px) { .fullpage-pagination { right: 10px; gap: 10px; } .pagination-dot { width: 8px; height: 8px; } .fullpage-section-content { padding-top: 50px; } } ``` ### 7. Modify FullPage Component to Listen for Navigation Events Update the FullPage component to listen for custom navigation events from the header. ```javascript // Add this useEffect in the FullPage component useEffect(() => { const handleNavigation = (e) => { const { index } = e.detail; goToPage(index); }; document.addEventListener('navigateTo', handleNavigation); return () => { document.removeEventListener('navigateTo', handleNavigation); }; }, []); ``` ## Implementation Timeline 1. **Setup (30 minutes)**: - Install dependencies - Create necessary files 2. **Core Components (2 hours)**: - Implement FullPage component - Implement Section component - Setup basic navigation 3. **Styling and Refinement (1.5 hours)**: - Implement CSS styles - Add pagination dots - Ensure responsive behavior 4. **Navigation Integration (1 hour)**: - Connect header navigation with fullpage scrolling - Implement URL hash updates 5. **Testing and Debugging (1 hour)**: - Test on different browsers - Ensure smooth scrolling on different devices ## Expected Results - Clean, full-viewport sections that are perfectly contained - Smooth transitions between sections - Navigation dots for quick section access - Header links that correctly navigate to sections - URL hash updates for direct section access - Keyboard navigation support - Responsive design that works on all devices ## Future Enhancements - Add touch swipe support for mobile devices - Implement section-specific animations - Add scroll progress indicator - Create horizontal sliding sections for portfolio items - Implement background parallax effects