mirror of
https://github.com/harivansh-afk/React-Portfolio.git
synced 2026-04-15 08:03:45 +00:00
chore: Enhance app structure by removing routing and social icons components. Implement full-page scrolling with section navigation. Update package dependencies and add new project details to content options.
This commit is contained in:
parent
c73262065d
commit
4ffb2ffc07
20 changed files with 19963 additions and 1775 deletions
448
smooth-scroll-implementation-plan.md
Normal file
448
smooth-scroll-implementation-plan.md
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
# 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 (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="fullpage-container"
|
||||
style={{ overflow: 'hidden', height: '100vh', position: 'relative' }}
|
||||
>
|
||||
<div
|
||||
className="fullpage-sections"
|
||||
style={{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
transition: 'transform 1s cubic-bezier(0.645, 0.045, 0.355, 1.000)',
|
||||
transform: `translateY(-${currentPage * 100}vh)`
|
||||
}}
|
||||
>
|
||||
{React.Children.map(children, (child, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="fullpage-section"
|
||||
style={{ height: '100vh', width: '100%' }}
|
||||
>
|
||||
{child}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Pagination Dots */}
|
||||
<div className="fullpage-pagination">
|
||||
{Array.from({ length: pagesCount }).map((_, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
className={`pagination-dot ${currentPage === index ? 'active' : ''}`}
|
||||
initial={{ opacity: 0.5, scale: 0.8 }}
|
||||
animate={{
|
||||
opacity: currentPage === index ? 1 : 0.5,
|
||||
scale: currentPage === index ? 1 : 0.8
|
||||
}}
|
||||
onClick={() => goToPage(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<motion.section
|
||||
id={id}
|
||||
className={`fullpage-section-content ${className}`}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
style={{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
position: 'relative'
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</motion.section>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<div className="app-container">
|
||||
<div className="cursor__dot">
|
||||
<AnimatedCursor
|
||||
innerSize={15}
|
||||
outerSize={15}
|
||||
color="255, 255 ,255"
|
||||
outerAlpha={0.4}
|
||||
innerScale={0.7}
|
||||
outerScale={5}
|
||||
/>
|
||||
</div>
|
||||
<Headermain />
|
||||
<FullPage>
|
||||
<Section id="home">
|
||||
<Home />
|
||||
</Section>
|
||||
<Section id="about">
|
||||
<About />
|
||||
</Section>
|
||||
<Section id="portfolio">
|
||||
<Portfolio />
|
||||
</Section>
|
||||
<Section id="contact">
|
||||
<ContactUs />
|
||||
</Section>
|
||||
</FullPage>
|
||||
<Socialicons />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue