Select Git revision
MobileNav.jsx
Embruch, Gerd authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MobileNav.jsx 3.61 KiB
import React, { useEffect, useReducer } from 'react';
import MobileLink from './MobileLink';
function reducer(mobileNavState, action) {
switch (action.type) {
case 'setNode':
return { ...mobileNavState, povNode: action.payload };
case 'setParentNode':
return { ...mobileNavState, povParentNode: action.payload };
case 'setPath':
return { ...mobileNavState, povPath: action.payload };
default:
return action.payload;
}
}
function MobileNav({ filteredSitemap, showMobileNav, toggleMobileNav }) {
// #################################
// HOOKS
// #################################
const [mobileNavState, dispatchMobileNavState] = useReducer(reducer, { povNode: [], povPath: location.pathname, povParentNode: [] });
// fetch new nodes on each change of PoV
useEffect(() => {
// loop & search for new PoV's path
function sitemapSearch(array, needle, parent) {
for (let i = 0; i < array.length; i++) {
if (array[i].path === needle) {
// set node
dispatchMobileNavState({ type: 'setNode', payload: [array[i]] });
// set parent
dispatchMobileNavState({ type: 'setParentNode', payload: [parent] });
return 'found';
}
else if (array[i].children?.length) {
const result = sitemapSearch(array[i].children, needle, array[i]);
// return the result only if it's actually found otherwise keep looping
if (result) return result;
}
}
}
// search nodes for new PoV Path
sitemapSearch(filteredSitemap, mobileNavState.povPath);
// triggered on PoV path change
}, [mobileNavState.povPath, filteredSitemap]);
// #################################
// FUNCTIONS
// #################################
// #################################
// OUTPUT
// #################################
// TODO: smoothen mobile nav output
return (
<div className={`sm:hidden h-full relative flex z-[900] max-h-full transform transition-all duration-150 ease-out ${showMobileNav ? 'right-0 opacity-100' : '-right-full opacity-0'}`}>
<div className="grow bg-UhhLightBlue" onClick={() => { toggleMobileNav(); }}></div>
<div className="absolute bg-UhhBlue right-0 z-[900] inset-y-0 min-w-[300px] text-UhhWhite">
<ul className="max-h-full">
{filteredSitemap && mobileNavState.povNode.map((link, idx) =>
<li key={`link-${idx}`}>
<MobileLink
level='pov'
toggleMobileNav={toggleMobileNav}
mobileNavState={mobileNavState}
dispatchMobileNavState={dispatchMobileNavState}
to={link.path}>
{link.title}
</MobileLink>
{
link.children?.length ? (
<ul key={`${idx}-childs`}>
{link.children.map((child, cidx) => {
if (child.hidden || child.index) return false;
return <MobileLink
key={`${idx}-child-${cidx}`}
toggleMobileNav={toggleMobileNav}
mobileNavState={mobileNavState}
dispatchMobileNavState={dispatchMobileNavState}
childNode={child}
to={link.path !== '/' ? `${link.path}/${child.path}` : `${child.path}`}>
{child.title}
</MobileLink>;
}).filter(Boolean)}
</ul>
) : (null)
}
</li>
)}
</ul>
</div>
</div>
);
}
export default React.memo(MobileNav);