# 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