Compare commits

..

2 commits

Author SHA1 Message Date
258d1e77c4 Merge pull request 'feat: added animations and navbar goodies' (#1) from feat-mobile-menu into main
All checks were successful
Build and Deploy Docker Image / build (push) Successful in 39s
Reviewed-on: #1
2024-10-22 07:42:24 -04:00
mike
088df9c4ee feat: added animations and navbar goodies 2024-10-22 07:40:36 -04:00
5 changed files with 195 additions and 67 deletions

View file

@ -1,18 +1,23 @@
// src/App.jsx
import React from 'react';
import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Header from './components/Header';
import Footer from './components/Footer';
import Home from './components/Home';
import About from './components/About';
import Roadmap from './components/Roadmap';
const App = () => (
const App = () => {
const [menuOpen, setMenuOpen] = useState(false);
const handleMenuToggle = (isOpen) => {
setMenuOpen(isOpen);
};
return (
<Router>
<Header />
<main>
<Header onMenuToggle={handleMenuToggle} />
<main className={`page-content ${menuOpen ? 'dropdown-active' : ''}`}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
@ -21,6 +26,7 @@ const App = () => (
</main>
<Footer />
</Router>
);
);
};
export default App;

View file

@ -22,3 +22,29 @@
transform: scaleX(1);
transform-origin: bottom left;
}
/* Header.css */
@keyframes dropdown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-dropdown {
animation: dropdown 0.5s ease-in-out;
}
.page-content {
transition: margin-top 0.5s ease-in-out;
}
.page-content.dropdown-active {
margin-top: 150px;
/* Adjust based on the height of the dropdown menu */
}

View file

@ -1,17 +1,41 @@
import { useState } from 'react';
import { Link } from 'react-router-dom';
import './Header.css'; // Import the custom CSS file
const Header = () => (
<header className="bg-gray-900 text-white p-4 flex justify-between items-center">
const Header = ({ onMenuToggle }) => {
const [isOpen, setIsOpen] = useState(false);
const toggleMenu = () => {
setIsOpen(!isOpen);
onMenuToggle(!isOpen);
};
return (
<header className="bg-gray-900 text-white p-4 flex justify-between items-center relative">
<div className="text-2xl font-bold">
<Link to="/" className="relative ">DoTechBro.org</Link>
<Link to="/" className="relative">DoTechBro.org</Link>
</div>
<nav className="space-x-4">
<Link to="/" className="relative link-underline">Home</Link>
<Link to="/about" className="relative link-underline">About</Link>
<Link to="/roadmap" className="relative link-underline">Roadmaps</Link>
<div className="md:hidden">
<button onClick={toggleMenu} className="focus:outline-none">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d={isOpen ? "M6 18L18 6M6 6l12 12" : "M4 6h16M4 12h16m-7 6h7"}></path>
</svg>
</button>
</div>
<nav className="hidden md:flex md:space-x-4">
<Link to="/" className="link-underline">Home</Link>
<Link to="/about" className="link-underline">About</Link>
<Link to="/roadmap" className="link-underline">Roadmaps</Link>
</nav>
{isOpen && (
<div className="absolute top-full left-0 w-full bg-gray-900 text-white flex flex-col items-center md:hidden animate-dropdown">
<Link to="/" className="block py-2 link-underline" onClick={toggleMenu}>Home</Link>
<Link to="/about" className="block py-2 link-underline" onClick={toggleMenu}>About</Link>
<Link to="/roadmap" className="block py-2 link-underline" onClick={toggleMenu}>Roadmaps</Link>
</div>
)}
</header>
);
);
};
export default Header;

23
src/components/Home.css Normal file
View file

@ -0,0 +1,23 @@
/* Home.css */
.page-content {
transition: margin-top 0.5s ease-in-out;
}
.page-content.dropdown-active {
margin-top: 150px;
/* Adjust based on the height of the dropdown menu */
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.animate-fade-in {
animation: fadeIn 1s ease-in-out forwards;
}

View file

@ -1,10 +1,40 @@
import { useState } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import FeaturedRoadmaps from './FeaturedRoadmaps';
import MailingListDialog from './MailingListDialog';
import roadmaps from '../roadmaps.json';
import './Home.css'; // Import the custom CSS file
const Home = () => {
const [dialogOpen, setDialogOpen] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
const sectionsRef = useRef([]);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-fade-in');
}
});
},
{ threshold: 0.1 }
);
sectionsRef.current.forEach((section) => {
if (section) {
observer.observe(section);
}
});
return () => {
sectionsRef.current.forEach((section) => {
if (section) {
observer.unobserve(section);
}
});
};
}, []);
const handleDialogOpen = () => {
setDialogOpen(true);
@ -14,10 +44,17 @@ const Home = () => {
setDialogOpen(false);
};
const handleMenuToggle = (isOpen) => {
setMenuOpen(isOpen);
};
return (
<div className={`page-content ${menuOpen ? 'dropdown-active' : ''}`}>
<div className="flex flex-col items-center justify-center w-full">
<div className="w-full p-8 flex flex-col md:flex-row items-center justify-center min-h-screen bg-gray-100">
<div
className="w-full p-8 flex flex-col md:flex-row items-center justify-center min-h-screen bg-gray-100 opacity-0"
ref={(el) => (sectionsRef.current[0] = el)}
>
<div className="md:w-1/2 flex flex-col items-center text-center">
<h2 className="text-6xl font-bold leading-tight">
Pivot into <span className="text-green-600">tech.</span>
@ -27,7 +64,10 @@ const Home = () => {
<p className="mt-4 text-lg max-w-2xl">
Empowering minorities to overcome barriers and succeed in the tech industry with confidence.
</p>
<button onClick={handleDialogOpen} className="mt-8 px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300">
<button
className="mt-8 px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300"
onClick={handleDialogOpen}
>
Start Today
</button>
</div>
@ -36,29 +76,38 @@ const Home = () => {
</div>
</div>
<div className="w-full bg-gray-900 text-white py-16">
<div
className="w-full bg-gray-900 text-white py-16 opacity-0"
ref={(el) => (sectionsRef.current[1] = el)}
>
<FeaturedRoadmaps roadmaps={roadmaps} />
</div>
<div className="w-full p-8 bg-white text-center my-16">
<div
className="w-full p-8 bg-white text-center my-16 opacity-0"
ref={(el) => (sectionsRef.current[2] = el)}
>
<h2 className="text-4xl font-bold mb-8">Testimonials</h2>
<p className="text-lg">Coming soon...</p>
</div>
<div className="w-full p-8 bg-gray-900 text-white text-center">
<div
className="w-full p-8 bg-gray-900 text-white text-center opacity-0"
ref={(el) => (sectionsRef.current[3] = el)}
>
<h2 className="text-4xl font-bold mb-8">Join Our Community</h2>
<p className="text-lg max-w-2xl mx-auto">
Connect with like-minded individuals, share your journey, and get support from our community.
</p>
<button
onClick={handleDialogOpen}
className="mt-8 px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300">
<button className="mt-8 px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300">
Join Now
</button>
</div>
<MailingListDialog open={dialogOpen} onClose={handleDialogClose} />
</div>
)
</div>
);
};
export default Home;