Mobile Navbar #75

Merged
a258wang merged 17 commits from feat/navbar-mobile into main 2021-07-07 18:13:40 -04:00
1 changed files with 26 additions and 20 deletions
Showing only changes of commit f7618a08d6 - Show all commits

View File

@ -54,7 +54,7 @@ const menu: Menu = [
},
{
name: "Resources",
route: "/resources",
route: "/resources/services",
submenu: [
{
name: "Services",
@ -72,15 +72,18 @@ const menu: Menu = [
},
];
function getMainRoute(route: string) {
if (route === "/") {
return "/";
} else if (route.startsWith("http://") || route.startsWith("https://")) {
return route;
}
return "/" + route.split("/")[1];
}
export function Navbar() {
const router = useRouter();
const [state, dispatch] = useReducer(reducer, initialState);
const parentPath =
router.pathname === "/"
? "/"
: menu.find(
(item) => item.route !== "/" && router.pathname.startsWith(item.route)
)?.route;
return (
<nav className={styles.navbar}>
@ -92,7 +95,7 @@ export function Navbar() {
</Link>
<button
className={styles.hamburger}
onClick={() => dispatch({ type: "open", route: parentPath ?? "" })}
onClick={() => dispatch({ type: "open", route: router.pathname })}
>
<Image src="/images/hamburger.svg" alt="Menu" />
</button>
@ -125,7 +128,7 @@ export function Navbar() {
route={item.route}
submenu={item.submenu}
activeSubmenus={state.activeSubmenus}
onClick={(type) => dispatch({ type, route: item.route })}
dispatch={dispatch}
/>
</li>
);
@ -158,14 +161,14 @@ function reducer(state: MobileState, action: MobileAction): MobileState {
case "open":
return {
isNavOpen: true,
activeSubmenus: new Set([action.route]),
activeSubmenus: new Set([getMainRoute(action.route)]),
};
case "toggle":
const newSet = new Set(state.activeSubmenus);
if (state.activeSubmenus.has(action.route)) {
newSet.delete(action.route);
if (state.activeSubmenus.has(getMainRoute(action.route))) {
newSet.delete(getMainRoute(action.route));
} else {
newSet.add(action.route);
newSet.add(getMainRoute(action.route));
}
return {
isNavOpen: state.isNavOpen,
@ -184,14 +187,15 @@ interface NavItemProps {
route: string;
}[];
activeSubmenus: Set<string>;
onClick: (type: MobileAction["type"]) => void;
dispatch: React.Dispatch<MobileAction>;
}
function NavItem(props: NavItemProps) {
const router = useRouter();
const isCurrentPage =
router.pathname === props.route ||
(props.submenu != null && router.pathname.startsWith(props.route));
(props.submenu != null &&
router.pathname.startsWith(getMainRoute(props.route)));
const isExternalLink =
props.route.includes("http://") || props.route.includes("https://");
@ -199,7 +203,7 @@ function NavItem(props: NavItemProps) {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
props.onClick("close");
props.dispatch({ type: "close" });
}
return (
@ -228,17 +232,19 @@ function NavItem(props: NavItemProps) {
<>
<button
className={
props.activeSubmenus.has(props.route)
props.activeSubmenus.has(getMainRoute(props.route))
? `${styles.dropdownIcon} ${styles.rotate}`
: styles.dropdownIcon
}
onClick={() => props.onClick("toggle")}
onClick={() =>
props.dispatch({ type: "toggle", route: props.route })
}
>
<Image src="/images/dropdown-icon.svg" alt="Dropdown Icon" />
</button>
<ul
className={
props.activeSubmenus.has(props.route)
props.activeSubmenus.has(getMainRoute(props.route))
? `${styles.dropdown} ${styles.show}`
: styles.dropdown
}
@ -250,7 +256,7 @@ function NavItem(props: NavItemProps) {
name={item.name}
route={item.route}
activeSubmenus={props.activeSubmenus}
onClick={props.onClick}
dispatch={props.dispatch}
/>
</li>
);