Fix navbar highlight for Organized Content sections (#182)

Also fixes the navbar highlight for the different Advice sections.

Closes #181

Co-authored-by: Amy <a258wang@uwaterloo.ca>
Reviewed-on: #182
Reviewed-by: Aditya Thakral <a3thakra@csclub.uwaterloo.ca>
Co-authored-by: Amy <a258wang@csclub.uwaterloo.ca>
Co-committed-by: Amy <a258wang@csclub.uwaterloo.ca>
pull/263/head
Amy Wang 2 years ago
parent 485230c95a
commit 0bb8049db3
  1. 81
      components/Navbar.tsx
  2. 6
      components/ShapesBackground.tsx
  3. 2
      content/advice/co-op-advice.mdx
  4. 2
      pages/resources/advice/academic.tsx
  5. 0
      pages/resources/advice/co-op.module.css
  6. 10
      pages/resources/advice/co-op.tsx
  7. 10
      pages/resources/advice/index.tsx
  8. 2
      pages/resources/advice/misc.tsx
  9. 2
      pages/resources/index.tsx

@ -9,16 +9,15 @@ import styles from "./Navbar.module.css";
type Menu = {
name: string;
route: string;
submenu?: {
name: string;
route: string;
}[];
exact?: boolean;
submenu?: Menu;
}[];
const menu: Menu = [
{
name: "Home",
route: "/",
exact: true,
},
{
name: "About",
@ -27,6 +26,7 @@ const menu: Menu = [
{
name: "About Us",
route: "/about",
exact: true,
},
{
name: "Meet the Team",
@ -76,7 +76,21 @@ const menu: Menu = [
},
{
name: "Advice",
route: "/resources/advice/coop",
route: "/resources/advice/co-op",
submenu: [
{
name: "Co-op Advice",
route: "/resources/advice/co-op",
},
{
name: "Academic Advice",
route: "/resources/advice/academic",
},
{
name: "Additional Resources",
route: "/resources/advice/misc",
},
],
},
{
name: "Internships",
@ -198,10 +212,11 @@ interface NavItemProps {
function NavItem(props: NavItemProps) {
const router = useRouter();
const isCurrentPage =
router.pathname === props.route ||
(props.submenu != null &&
router.pathname.startsWith(getMainRoute(props.route)));
const isCurrentPage = shouldHighlight(
router.pathname,
props.name,
props.route
);
const isExternalLink =
props.route.includes("http://") || props.route.includes("https://");
@ -273,6 +288,54 @@ function NavItem(props: NavItemProps) {
);
}
interface Leaf {
name: string;
route: string;
exact?: boolean;
ancestors: { name: string; route: string }[];
}
function collectLeaves(
accumulator: Leaf[],
entry: {
name: string;
route: string;
exact?: boolean;
submenu?: Menu;
}
): Leaf[] {
if (entry.submenu == null) {
return [...accumulator, { ...entry, ancestors: [] }];
}
const subleaves = entry.submenu.reduce(collectLeaves, [] as Leaf[]);
return [
...accumulator,
...subleaves.map((leaf) => ({
...leaf,
ancestors: [...leaf.ancestors, { name: entry.name, route: entry.route }],
})),
];
}
const leaves: Leaf[] = menu.reduce(collectLeaves, [] as Leaf[]);
function shouldHighlight(
pathname: string,
name: string,
route: string
): boolean {
const match = leaves.find((leaf) =>
leaf.exact ? leaf.route === pathname : pathname.startsWith(leaf.route)
);
return match
? (match.name === name && match.route === route) ||
match.ancestors.find(
(ancestor) => ancestor.name === name && ancestor.route === route
) != null
: false;
}
function getMainRoute(route: string) {
if (route === "/") {
return "/";

@ -45,7 +45,11 @@ export function ShapesBackground({ getConfig }: Props) {
}, [getConfig, width, height, prevWidth, prevRoute, router.asPath]);
return (
<div className={styles.shapesContainer} ref={shapesContainerRef}>
<div
className={styles.shapesContainer}
ref={shapesContainerRef}
aria-hidden
>
{Object.entries(config).map(([type, instances]) =>
instances.map((attributes, idx) => (
<Shape

@ -1,4 +1,4 @@
## Coop Advice
## Co-op Advice
Although WaterlooWorks is quite reliable, there are many more opportunities outside of the job board.
Being able to apply for jobs externally not only prepares you to look for jobs full time but it also

@ -4,7 +4,7 @@ import { Title } from "@/components/Title";
import Content from "../../../content/advice/academic-advice.mdx";
import { Advice } from "./coop";
import { Advice } from "./co-op";
export default function AcademicAdvice() {
return (

@ -5,9 +5,9 @@ import React, { ReactNode } from "react";
import { Image } from "@/components/Image";
import { Title } from "@/components/Title";
import Content from "../../../content/advice/coop-advice.mdx";
import Content from "../../../content/advice/co-op-advice.mdx";
import styles from "./coop.module.css";
import styles from "./co-op.module.css";
export default function CoopAdvice() {
return (
@ -30,13 +30,13 @@ export function Advice(props: { children: ReactNode }) {
<Image src="/images/advice.svg" className={styles.codey} />
</div>
<div className={styles.adviceBarContainer}>
<Link href="/resources/advice/coop">
<Link href="/resources/advice/co-op">
<a
className={
path == "/resources/advice/coop" ? styles.currentAdvice : ""
path == "/resources/advice/co-op" ? styles.currentAdvice : ""
}
>
Coop Advice
Co-op Advice
</a>
</Link>
<Link href="/resources/advice/academic">

@ -0,0 +1,10 @@
import Head from "next/head";
import React from "react";
export default function AdviceRedirect() {
return (
<Head>
<meta httpEquiv="refresh" content="0;url=/resources/advice/co-op" />
</Head>
);
}

@ -4,7 +4,7 @@ import { Title } from "@/components/Title";
import Content from "../../../content/advice/misc-advice.mdx";
import { Advice } from "./coop";
import { Advice } from "./co-op";
export default function MiscAdvice() {
return (

@ -1,7 +1,7 @@
import Head from "next/head";
import React from "react";
export default function Resources() {
export default function ResourcesRedirect() {
return (
<Head>
<meta httpEquiv="refresh" content="0;url=/resources/services" />

Loading…
Cancel
Save