Navbar
This commit is contained in:
parent
b4d4a15212
commit
4393037e94
|
@ -0,0 +1,147 @@
|
|||
.navbar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
background-color: var(--white);
|
||||
}
|
||||
|
||||
.navContent {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: none;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
width: stretch;
|
||||
max-width: 1440px;
|
||||
height: auto;
|
||||
padding: 1.75rem 8.5rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navMenu {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: none;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
width: 32rem;
|
||||
}
|
||||
|
||||
.navMenu li {
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.navMenu a {
|
||||
color: var(--purple-2);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.navMenu a.currentPage {
|
||||
color: var(--blue-2);
|
||||
}
|
||||
|
||||
.navMenu > li:hover > a {
|
||||
color: var(--blue-2);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Prevents the menu items from shifting when made bold on hover */
|
||||
.navMenu > li > a::before {
|
||||
display: block;
|
||||
content: attr(title);
|
||||
font-weight: 600;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.navMenu > li > a {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.dropdownWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
visibility: visible;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
|
||||
position: absolute;
|
||||
|
||||
margin: 0;
|
||||
margin-top: 3rem;
|
||||
padding: 0;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
background-color: var(--white);
|
||||
box-shadow: 0 0.5rem 1rem var(--blue-1-20);
|
||||
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.dropdown > li {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dropdown > li > a {
|
||||
padding: 0.5rem;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.dropdown > li:hover > a,
|
||||
.dropdown > li > a:focus {
|
||||
background-color: var(--blue-1-20);
|
||||
}
|
||||
|
||||
.dropdown > li:first-child > a {
|
||||
padding-top: 1rem;
|
||||
border-radius: 0.5rem 0.5rem 0 0;
|
||||
}
|
||||
|
||||
.dropdown > li:last-child > a {
|
||||
padding-bottom: 1rem;
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
}
|
||||
|
||||
.navMenu > li .dropdown {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.navMenu > li:hover .dropdown,
|
||||
.navMenu > li:focus-within .dropdown {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* On a smaller desktop screen, keep the same navbar layout but decrease the
|
||||
* horizontal padding so it still fits
|
||||
*/
|
||||
@media screen and (max-width: 960px) {
|
||||
.navContent {
|
||||
padding: 1.75rem 4rem;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import styles from "./Navbar.module.css";
|
||||
|
||||
interface NavLink {
|
||||
name: string;
|
||||
route: string;
|
||||
submenu?: {
|
||||
name: string;
|
||||
route: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
const menu: NavLink[] = [
|
||||
{
|
||||
name: "Home",
|
||||
route: "/",
|
||||
},
|
||||
{
|
||||
name: "About",
|
||||
route: "/about",
|
||||
submenu: [
|
||||
{
|
||||
name: "About Us",
|
||||
route: "/about",
|
||||
},
|
||||
{
|
||||
name: "Meet the Team",
|
||||
route: "/about/team",
|
||||
},
|
||||
{
|
||||
name: "Constitution",
|
||||
route: "/about/constitution",
|
||||
},
|
||||
{
|
||||
name: "Code of Conduct",
|
||||
route: "/about/code-of-conduct",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Get Involved",
|
||||
route: "/get-involved",
|
||||
},
|
||||
{
|
||||
name: "Events",
|
||||
route: "/events",
|
||||
},
|
||||
{
|
||||
name: "Resources",
|
||||
route: "/resources",
|
||||
},
|
||||
];
|
||||
|
||||
function NavItem(props: NavLink) {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<Link href={props.route}>
|
||||
<a
|
||||
title={props.name}
|
||||
className={
|
||||
router.pathname === props.route ||
|
||||
((props.submenu?.length ?? 0) > 0 &&
|
||||
router.pathname.startsWith(props.route))
|
||||
? styles.currentPage
|
||||
: ""
|
||||
}
|
||||
onClick={() => {
|
||||
if (document.activeElement instanceof HTMLElement) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{props.name}
|
||||
</a>
|
||||
</Link>
|
||||
{(props.submenu?.length ?? 0) > 0 ? (
|
||||
<ul className={styles.dropdown}>
|
||||
{props.submenu?.map((item) => {
|
||||
return (
|
||||
<li className={styles.dropdownWrapper} key={item.name}>
|
||||
<NavItem name={item.name} route={item.route} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function Navbar() {
|
||||
return (
|
||||
<nav className={styles.navbar}>
|
||||
<div className={styles.navContent}>
|
||||
<Link href="/">
|
||||
<a className={styles.logo}>
|
||||
<Image
|
||||
src="/images/logo-icon.png"
|
||||
width={96}
|
||||
height={42}
|
||||
alt="CSC Logo"
|
||||
/>
|
||||
</a>
|
||||
</Link>
|
||||
<ul className={styles.navMenu}>
|
||||
{menu.map((item) => {
|
||||
return (
|
||||
<li className={styles.dropdownWrapper} key={item.name}>
|
||||
<NavItem
|
||||
name={item.name}
|
||||
route={item.route}
|
||||
submenu={item.submenu}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
|
@ -8,11 +8,13 @@ code, pre {
|
|||
|
||||
/* Default is light theme */
|
||||
body {
|
||||
--white: #ffffff;
|
||||
--off-white: #fdf8f5;
|
||||
--teal-1: #76ffdc;
|
||||
--teal-2: #4ed4b2;
|
||||
--blue-1: #5caff9;
|
||||
--blue-2: #5caff9;
|
||||
--blue-1-20: #5caff934;
|
||||
--blue-2: #1482e3;
|
||||
--purple-1: #525284;
|
||||
--purple-2: #2a2a62;
|
||||
--gradient-blue-green: linear-gradient(
|
||||
|
@ -20,14 +22,17 @@ body {
|
|||
#1481e3 -17.95%,
|
||||
#4ed4b2 172.82%
|
||||
);
|
||||
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--white: #ffffff;
|
||||
--off-white: #fdf8f5;
|
||||
--teal-1: #76ffdc;
|
||||
--teal-2: #4ed4b2;
|
||||
--blue-1: #5caff9;
|
||||
--blue-2: #5caff9;
|
||||
--blue-2: #1482e3;
|
||||
--purple-1: #525284;
|
||||
--purple-2: #2a2a62;
|
||||
--gradient-blue-green: linear-gradient(
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from "react";
|
|||
import { AppProps } from "next/app";
|
||||
import { MDXProvider } from "@mdx-js/react";
|
||||
import { ThemeProvider } from "../components/theme";
|
||||
import { Navbar } from "../components/Navbar";
|
||||
import "./_app.css";
|
||||
import "./font.css";
|
||||
|
||||
|
@ -9,6 +10,7 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
|
|||
return (
|
||||
<ThemeProvider theme="light">
|
||||
<MDXProvider components={{}}>
|
||||
<Navbar />
|
||||
<Component {...pageProps} />
|
||||
</MDXProvider>
|
||||
</ThemeProvider>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# Code of Conduct page
|
|
@ -0,0 +1 @@
|
|||
# Constitution page
|
|
@ -0,0 +1 @@
|
|||
# About Us page
|
|
@ -0,0 +1 @@
|
|||
# Meet the Team page
|
|
@ -0,0 +1 @@
|
|||
# Events page
|
|
@ -0,0 +1 @@
|
|||
# Get Involved page
|
|
@ -0,0 +1 @@
|
|||
# Resources page
|
Binary file not shown.
After Width: | Height: | Size: 208 KiB |
Loading…
Reference in New Issue