diff --git a/package-lock.json b/package-lock.json
index 8a7ca3c..e9f20fc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,7 +23,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-ga4": "^2.1.0",
- "react-icons": "^4.8.0",
+ "react-icons": "^5.2.1",
"react-markdown": "^9.0.1",
"react-router-dom": "^6.9.0",
"styled-components": "^5.3.9",
@@ -6949,9 +6949,9 @@
"integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ=="
},
"node_modules/react-icons": {
- "version": "4.8.0",
- "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.8.0.tgz",
- "integrity": "sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==",
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz",
+ "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==",
"peerDependencies": {
"react": "*"
}
diff --git a/package.json b/package.json
index 0d28b0a..9663c49 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-ga4": "^2.1.0",
- "react-icons": "^4.8.0",
+ "react-icons": "^5.2.1",
"react-markdown": "^9.0.1",
"react-router-dom": "^6.9.0",
"styled-components": "^5.3.9",
diff --git a/public/img/temp-bg.jpg b/public/img/temp-bg.jpg
new file mode 100644
index 0000000..00c04e7
Binary files /dev/null and b/public/img/temp-bg.jpg differ
diff --git a/src/features/Navbar/NavbarPill.tsx b/src/features/Navbar/NavbarPill.tsx
new file mode 100644
index 0000000..292a85c
--- /dev/null
+++ b/src/features/Navbar/NavbarPill.tsx
@@ -0,0 +1,20 @@
+import { Link } from "react-router-dom";
+import { NavbarPillProps } from "./NavbarPillProps";
+
+const NavbarPill = ({ title, desc, Icon, image, link } : NavbarPillProps) => {
+ return (
+
+
+
+ )
+}
+
+export default NavbarPill;
\ No newline at end of file
diff --git a/src/features/Navbar/NavbarPillProps.ts b/src/features/Navbar/NavbarPillProps.ts
new file mode 100644
index 0000000..ba039c3
--- /dev/null
+++ b/src/features/Navbar/NavbarPillProps.ts
@@ -0,0 +1,10 @@
+import { IconType } from "react-icons";
+
+export interface NavbarPillProps {
+ title: string;
+ desc: string;
+ Icon: IconType;
+ image: string;
+ link: string;
+}
+
diff --git a/src/layouts/Layout.tsx b/src/layouts/Layout.tsx
index 1497c15..e4da43e 100644
--- a/src/layouts/Layout.tsx
+++ b/src/layouts/Layout.tsx
@@ -1,6 +1,18 @@
import React, { useEffect, useState } from "react";
import { Outlet, useLocation } from "react-router";
-import { FaDiscord, FaEnvelope, FaFacebook, FaInstagram, FaLinkedin, FaTiktok } from "react-icons/fa";
+import {
+ FaDiscord,
+ FaEnvelope,
+ FaFacebook,
+ FaInstagram,
+ FaLinkedin,
+ FaTiktok,
+ FaCalendar,
+ FaLink,
+ FaFlag,
+ FaPersonBooth,
+ FaUser,
+} from "react-icons/fa";
import {
DISCORD_LINK,
FACEBOOK_LINK,
@@ -14,6 +26,7 @@ import {
// Components
import Navbar from "./Navbar";
+import { NavbarPillProps } from "../features/Navbar/NavbarPillProps";
import Footer from "./Footer";
// Styles
@@ -40,11 +53,50 @@ const Layout = () => {
setIsShowFooter(!isFooterHidden);
}, [location]);
+ const homePills: NavbarPillProps[] = [];
+
+ const aboutPills: NavbarPillProps[] = [
+ {
+ title: "Events",
+ desc: "Our flagship Events!",
+ Icon: FaFlag,
+ image: "/img/temp-bg.jpg",
+ link: "/about/events",
+ },
+ {
+ title: "Meet the team",
+ desc: "See our amazing team",
+ Icon: FaUser,
+ image: "/img/temp-bg.jpg",
+ link: "/about/meettheteam",
+ },
+ ];
+
+ const calenderPills: NavbarPillProps[] = [
+ {
+ title: "Calender",
+ desc: "See what's going on!",
+ Icon: FaCalendar,
+ image: "/img/temp-bg.jpg",
+ link: "/upcoming/calendar",
+ },
+ {
+ title: "Links",
+ desc: "Signups, events and more",
+ Icon: FaLink,
+ image: "/img/temp-bg.jpg",
+ link: "/upcoming/links",
+ },
+ ];
+
+ const sponsorPills: NavbarPillProps[] = [];
+
const nav = {
clubname: "HackMelbourne",
logo: "/img/HM_White_Transparent.png",
- pages: ["Home", "Meet The Team", "Calendar", "Sponsors"],
- links: ["/", "about/meettheteam", "upcoming/calendar", "sponsors"],
+ pages: ["Home", "About", "Upcoming", "Sponsors"],
+ links: ["/", "/about/meettheteam", "/upcoming/calendar", "/sponsors"],
+ pills: [homePills, aboutPills, calenderPills, sponsorPills],
};
const footer = {
@@ -89,7 +141,9 @@ const Layout = () => {
return (
<>
- {isShowNavbar ?
: null}
+ {isShowNavbar ? (
+
+ ) : null}
{isShowFooter ?
: null}
diff --git a/src/layouts/Navbar.tsx b/src/layouts/Navbar.tsx
index c421e4d..7213695 100644
--- a/src/layouts/Navbar.tsx
+++ b/src/layouts/Navbar.tsx
@@ -1,37 +1,136 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
+import { AnimatePresence, motion } from 'framer-motion';
import MenuIcon from '@mui/icons-material/Menu';
import CloseIcon from '@mui/icons-material/Close';
+import { ArrowDropUp, ArrowDropDown } from '@mui/icons-material';
+import { NavbarPillProps } from '../features/Navbar/NavbarPillProps';
// Styles
import '../styles/gradients.css';
// Images
// Change image to remove the bottom text
-import close_button from '/img/close-button.png';
import { Link } from 'react-router-dom';
import Slide from '@mui/material/Slide';
+import { List } from '@mui/material';
+import NavbarPill from '../features/Navbar/NavbarPill';
interface Nav {
clubname: string;
logo: string;
pages: string[];
links: string[];
+ pills: NavbarPillProps[][];
}
-const Navbar = ({ clubname, logo, pages, links }: Nav) => {
+const Navbar = ({ clubname, logo, pages, links, pills }: Nav) => {
+ const [isDesktopMenuOpen, setIsDesktopMenuOpen] = useState(true);
const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const [isSubMenuOpen, setIsSubMenuOpen] = useState(true);
+ const [activePage, setActivePage] = useState
(null);
+ const [activeSubMenu, setActiveSubMenu] = useState(new Array(pages.length).fill(false));
+ const mobileNavRef = useRef(null);
+
+ const menuVars = {
+ initial: {
+ scaleY: 0.
+ },
+ animate: {
+ scaleY: 1,
+ transition: {
+ duration: 0.3
+ }
+ },
+ exit: {
+ scaleY: 0,
+ transition: {
+ duration: 0.1,
+ }
+ }
+ }
const toggleMenu = () => {
setIsMenuOpen(!isMenuOpen);
+ setIsDesktopMenuOpen(isMenuOpen);
};
const handleLinkClick = () => {
setIsMenuOpen(false);
+ setIsDesktopMenuOpen(true);
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
};
+ const revealMobileNav = (index: number | null) => {
+ setActivePage(index);
+ setIsSubMenuOpen(false);
+ };
+
+ const revealMobileNavItems = () => {
+ if (activePage == null) return
+ return (
+
+
+
{
+ revealMobileNav(null);
+ setIsSubMenuOpen(true);
+ }}>Back
+
{pages[activePage]}
+
+ {pills[activePage].map((pill) => (
+
+ ))}
+
+
+
+ );
+ };
+
+ const revealSubMenu = (index: number) => {
+ setActiveSubMenu((prev) => {
+ const newActiveSubMenu = [...prev];
+ newActiveSubMenu[index] = !newActiveSubMenu[index];
+ return newActiveSubMenu;
+ });
+ };
+
+ const navItems = ( pills : NavbarPillProps[], title : string) => {
+ if (activePage == null) return
+ return (
+
+ {/* Really bootleg solution, creates an invisible box to ensure hovered nav item doesnt
+ dissapear since the items are disconnected from the bar */}
+
+
+
+ {pills.map((pill) => (
+
+ ))}
+
+
+
+ )
+ }
+
+ const handleClickOutsideNav = (e: MouseEvent) => {
+ if (mobileNavRef.current && !mobileNavRef.current.contains(e.target as Node)) {
+ toggleMenu();
+ }
+ };
+
+ useEffect(() => {
+ if (isMenuOpen) {
+ document.addEventListener('mousedown', handleClickOutsideNav);
+ } else {
+ document.removeEventListener('mousedown', handleClickOutsideNav);
+ }
+ }, [isMenuOpen]);
+
return (
-
+
setActivePage(null)}>
+ {isDesktopMenuOpen && (
@@ -45,42 +144,84 @@ const Navbar = ({ clubname, logo, pages, links }: Nav) => {
{/* DESKTOP */}
{pages.map((page, index) => (
-
- {page}
-
- ))}
+
setActivePage(index)}
+ className="relative"
+ >
+ setActivePage(index)}
+ className="">
+ {page}
+
+
+ {pills[index].length > 0 && activePage === index && navItems(pills[index], page)}
+
+ ))}
+ )}
{/* MOBILE */}
-
);
};
-export default Navbar;
+export default Navbar;
\ No newline at end of file