Skip to content
Snippets Groups Projects
Select Git revision
  • 9e9bd26cc216b3f0b56eaeffff34ac71c9d623f2
  • main default protected
  • userHandling
  • snuggle
4 results

MobileNav.jsx

Blame
  • 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);