From b78fea0762334d0a7946346bc914101d0eb92414 Mon Sep 17 00:00:00 2001 From: Bayda77 Date: Mon, 12 Jan 2026 18:06:42 -0600 Subject: [PATCH] fix particles amount --- src/components/ParticlesBackground.tsx | 19 ++++-- src/components/floatingHeader.tsx | 85 +++++++++++++++--------- src/styles/components/header.css | 92 +++++++++++++++++++++++++- 3 files changed, 160 insertions(+), 36 deletions(-) diff --git a/src/components/ParticlesBackground.tsx b/src/components/ParticlesBackground.tsx index b5e2da6..f1ba7d1 100644 --- a/src/components/ParticlesBackground.tsx +++ b/src/components/ParticlesBackground.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react'; const ParticlesBackground: React.FC = () => { const canvasRef = useRef(null); + const prevWidth = useRef(window.innerWidth); useEffect(() => { const canvas = canvasRef.current; @@ -69,11 +70,16 @@ const ParticlesBackground: React.FC = () => { const init = () => { if (!canvas) return; canvas.width = window.innerWidth; + // Use logical height that works well with the 120vh style canvas.height = window.innerHeight; - // Reduce particle count on mobile/portrait screens - const isPortrait = canvas.height > canvas.width; - const particleCount = isPortrait ? 90 : 180; + // Calculate particle count based on screen area (resolution) + // Formula: sqrt(width * height) / factor + // Desktop (1920x1080) -> ~120 particles + // Mobile (390x844) -> ~48 particles + // Mobile Landscape (844x390) -> ~48 particles (Same as portrait!) + const area = canvas.width * canvas.height; + const particleCount = Math.floor(Math.sqrt(area) / 12); particles = []; for (let i = 0; i < particleCount; i++) { @@ -134,6 +140,11 @@ const ParticlesBackground: React.FC = () => { animate(); const handleResize = () => { + // Ignore vertical-only resizes (addressing mobile browser bar toggle issue) + if (window.innerWidth === prevWidth.current) { + return; + } + prevWidth.current = window.innerWidth; init(); } @@ -153,7 +164,7 @@ const ParticlesBackground: React.FC = () => { top: 0, left: 0, width: '100%', - height: '100%', + height: '120vh', // Extend well below viewport to cover mobile browser bar retraction zIndex: -1, // Behind everything }} /> diff --git a/src/components/floatingHeader.tsx b/src/components/floatingHeader.tsx index ea97991..224fbfd 100644 --- a/src/components/floatingHeader.tsx +++ b/src/components/floatingHeader.tsx @@ -1,44 +1,67 @@ +import { useState, useEffect } from "react"; import { Link, useLocation } from "react-router-dom"; import "../styles/components/header.css"; export default function FloatingHeader() { const location = useLocation(); + const [isMenuOpen, setIsMenuOpen] = useState(false); + + const toggleMenu = () => { + setIsMenuOpen(!isMenuOpen); + }; + + // Close menu when route changes + useEffect(() => { + setIsMenuOpen(false); + }, [location]); + return (
- + +
); } diff --git a/src/styles/components/header.css b/src/styles/components/header.css index ac11593..3ba3283 100644 --- a/src/styles/components/header.css +++ b/src/styles/components/header.css @@ -13,12 +13,13 @@ backdrop-filter: blur(10px); border-bottom: 1px solid rgba(255, 255, 255, 0.2); margin: 0; + box-sizing: border-box; } .header-nav { display: flex; justify-content: center; - gap: clamp(10px, 2vw, 40px); + gap: clamp(8px, 2vw, 32px); flex-wrap: nowrap; padding: 0 20px; } @@ -61,3 +62,92 @@ .nav-link.active::after { width: 100%; } + +/* Mobile Navigation Styles */ +.header-content { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + max-width: 1200px; + margin: 0 auto; +} + +.mobile-toggle { + display: none; + flex-direction: column; + justify-content: space-between; + width: 30px; + height: 21px; + background: transparent; + border: none; + cursor: pointer; + z-index: 1001; + padding: 0; +} + +.hamburger-line { + width: 100%; + height: 3px; + background-color: rgba(255, 255, 255, 0.9); + border-radius: 3px; + transition: all 0.3s ease; +} + +@media (max-width: 1024px) { + .floating-header { + padding: 15px 20px; + text-align: left; + } + + .header-content { + justify-content: flex-end; + /* Align hamburger to right */ + } + + .mobile-toggle { + display: flex; + } + + /* Animate Hamburger to X */ + .mobile-toggle.open .hamburger-line:nth-child(1) { + transform: translateY(9px) rotate(45deg); + } + + .mobile-toggle.open .hamburger-line:nth-child(2) { + opacity: 0; + } + + .mobile-toggle.open .hamburger-line:nth-child(3) { + transform: translateY(-9px) rotate(-45deg); + } + + .header-nav { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + height: 100vh; + background: rgba(10, 10, 30, 0.95); + backdrop-filter: blur(15px); + flex-direction: column; + justify-content: center; + align-items: center; + gap: 30px; + transform: translateX(100%); + transition: transform 0.3s ease-in-out; + z-index: 999; + /* Below toggle button */ + padding: 0; + } + + .header-nav.is-open { + transform: translateX(0); + } + + .nav-link { + font-size: 24px; + padding: 10px 0; + } +} \ No newline at end of file