Commit c9f7e874 authored by Panagiotis Chnarakis's avatar Panagiotis Chnarakis
Browse files

refactor TopBar adding Responsiveness and burger mobile menu btn

parent 3eba0693
Loading
Loading
Loading
Loading
+76 −35
Original line number Diff line number Diff line
"use client";
import React, { useState } from "react";
import React, { useRef, useState } from "react";
import styles from "./topbar.module.scss";
import { Button, Nav, Toggle } from "rsuite";
import { Button, Nav } from "rsuite";
import Link from "next/link";
import { useRouter } from "next/navigation";
import buttons from "../../styles/buttons.module.scss";
import { logoIcon, userIcon } from "@/app/utils/icons";
import { logoIcon, menuCloseIcon, menuIcon, userIcon } from "@/app/utils/icons";
import { navLinks } from "@/app/utils/constants";
import { formatName } from "@/app/utils/helpers";
import { usePathname } from "next/navigation";
import useOnClickOutside from "@/app/hooks/useOnClickOutside";

const TopBar = () => {
  const route = useRouter();
  const router = useRouter();
  const [isMenuOpen, setMenuOpen] = useState(false);
  const pathname = usePathname();
  const MobileMenuRef: any = useRef(null);

  const user = { name: "Chnarakis Panagiotis", role: "Developer" }; // Example user object
  // const user = null; // No user logged in

  const toggleMenu = () => setMenuOpen((prev) => !prev);
  useOnClickOutside(MobileMenuRef, () => {
    setMenuOpen(false);
  });
  const renderNavLinks = () =>
    navLinks.map((link) => (
      <Nav.Item
        key={link.id}
        as={Link}
        href={link.path}
        eventKey={link.path}
        active={pathname === link.path}
      >
        {link.name}
      </Nav.Item>
    ));

  return (
    <div className={styles.container}>
      <header className={styles.header}>
        <Link href={"/"} className={styles.logo}>
        {/* LOGO */}
        <Link href="/" className={styles.logo}>
          {logoIcon}
        </Link>
        <Nav defaultActiveKey="Api Cataloque" className={styles.navLinks}>
          {navLinks.map((link) => (
            <Nav.Item key={link.id} eventKey={link.name} href={link.path}>
              {link.name}
            </Nav.Item>
          ))}

        {/* DESKTOP NAV */}
        <Nav activeKey={pathname} className={styles.navLinks}>
          {renderNavLinks()}
        </Nav>

        {/* <Button
          className={buttons.primary}
          onClick={() => route.push("/login")}
        >
          Login
        </Button> */}
        {/* MOBILE MENU BUTTON */}
        <div className={styles.mobileContainer}>
          {/* USER MENU */}
          {user && (
            <Nav className={styles.userBtn}>
              <Nav.Menu
                icon={userIcon}
              title={formatName(user?.name)}
                title={
                  <span className={styles.username}>
                    {formatName(user.name)}
                  </span>
                }
                placement="bottomEnd"
              >
              <Nav.Item href="/profile" as="a">
                <Nav.Item as={Link} href="/profile">
                  Profile
                </Nav.Item>
              <Nav.Item href="/settings" as="a">
                <Nav.Item as={Link} href="/settings">
                  Settings
                </Nav.Item>
              <Nav.Item>Log Out</Nav.Item>
                <Nav.Item onClick={() => router.push("/logout")}>
                  Log Out
                </Nav.Item>
              </Nav.Menu>
            </Nav>
          )}
          <Button
            ref={MobileMenuRef}
            className={styles.menuBtn}
            onClick={toggleMenu}
          >
            {isMenuOpen ? menuCloseIcon : menuIcon}
          </Button>
        </div>

        {/* MOBILE MENU */}
        {isMenuOpen && (
          <div className={styles.mobileMenuContainer}>
            <Nav activeKey={pathname} className={styles.mobileNavLinks}>
              {renderNavLinks()}
            </Nav>
          </div>
        )}
      </header>
    </div>
  );
+154 −27
Original line number Diff line number Diff line
@@ -22,10 +22,6 @@
        color: var(--text-color);
        gap: 0.4rem;

        svg {

            transform: scale(1.05);
        }
    }

    header {
@@ -37,7 +33,116 @@
        height: 100%;
    }

    .menuBtn {
        border-radius: 10px;
        background: var(--main-gradient);
        display: flex;
        align-items: center;
        width: 50px;
        height: 50px;
        justify-content: center;
        flex-direction: column;
        transition: all 0.5s;

        svg {

            fill: #fff;
        }

        &:hover {
            background: linear-gradient(360deg, #FDB913 0%, #F15A22 100%);
        }
    }

    .mobileMenuContainer,
    .menuBtn {
        display: none;
    }

    .mobileMenuContainer {
        position: absolute;
        border-radius: 10px;
        top: 85px;
        right: 30px;
        height: auto;
        background: var(--background-color);
        backdrop-filter: blur(5px);
        display: flex;
        align-items: center;
        padding: 1rem 2rem;
        font-size: 16px;
        justify-content: center;
        flex-direction: column;
        box-shadow: 4px 4px 20px rgba(0, 0, 0, 0.1);
        border-radius: 10px;
        transition: all 0.5s;
        border: none !important;


        .mobileNavLinks {
            display: flex;
            flex-direction: column;
            width: 100%;
            gap: 1rem;

            :global(.rs-nav-item) {
                &::after {
                    display: none !important;
                }
            }
            :global(.rs-nav-item[aria-selected="true"]:hover) {
                       color: var(--blue-color) !important;
                       cursor: default;
                   }
           
                   :global(.rs-nav-item[aria-selected="true"]) {
                       color: var(--blue-color) !important;
                       cursor: default;
                   }
        }

    }

    .mobileContainer {
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .mobileUserBtn {
        :global(.rs-dropdown) {
            background: var(--background-color) !important;
            box-shadow: 4px 4px 20px rgba(0, 0, 0, 0.1);
            border-radius: 10px;

            &:hover {
                background: var(--rs-navs-bg-hover) !important;
            }

            .rs-dropdown-toggle .rs-nav-item {
                width: max-content;
                height: max-content;
                padding: 0.5rem 0.7rem !important;

            }


            
        }
        svg {
            margin: 0;
        }
    }

    .mobileUserBtn {
        display: none;
    }

    .navLinks {
        flex-wrap: wrap;
        display: flex;
        align-items: center;

        :global(.rs-nav-item) {
            position: relative;
            padding: 0 1.5rem 0 1rem;
@@ -67,24 +172,17 @@
        }

        :global(.rs-nav-item[aria-selected="true"]:hover) {
            color: var(--blue-text) !important;
            color: var(--blue-color) !important;
            cursor: default;
        }
    }



    .mobileMenuIcon {
        display: none;
        cursor: pointer;

        svg {
            width: 32px;
            height: 32px;
        :global(.rs-nav-item[aria-selected="true"]) {
            color: var(--blue-color) !important;
            cursor: default;
        }

    }


    .userBtn {
        :global(.rs-dropdown) {
            background: var(--background-color) !important;
@@ -109,23 +207,31 @@

    }




.username {
  @media (max-width: 600px) {
    display: none;
  }
}



    //------------------------- Responsive -------------------------//

    @media screen and (max-width: 769px) {
    @media screen and (max-width: 1025px) {
        padding: 1rem 2rem;

        .mobileMenuIcon {
            display: block;
       

        .navLinks
         {
            display: none !important;
        }

        .navLinks {
            display: none;
        .mobileMenuContainer,
        .menuBtn {
            display: flex !important;


        }
    }
}
@@ -134,13 +240,34 @@



@media screen and (max-width:425px) {
@media screen and (max-width:768px) {
    .userBtn {
            svg {
            margin: 0;
        }
        }

}
@media screen and (max-width:426px) {
    .logo {
        gap: 0.3rem;
        svg {

            transform: scale(0.90) !important;
        }
    }
    .mobileContainer{
                transform: scale(0.90) !important;

}


}
@media screen and (max-width:380px) {
    .logo {
width:130px;
        svg {

            transform: scale(0.95) !important;
            transform: scale(0.80) !important;
        }
    }

+20 −0
Original line number Diff line number Diff line
import React, { useEffect } from 'react';

function useOnClickOutside(ref: any, handler: any) {
  useEffect(() => {
    const listener = (event: any) => {
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }
      handler(event);
    };
    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);
    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [ref, handler]);
}

export default useOnClickOutside;
 No newline at end of file
+3 −2
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ body {
  -moz-osx-font-smoothing: grayscale;
  &::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }

  &::-webkit-scrollbar-thumb {
@@ -105,8 +106,8 @@ body {

  &::-webkit-scrollbar-track {
    background: var(--background-color);
    box-shadow: inset -4px -4px 8px rgba(16, 22, 53, 0.8),
      inset 4px 4px 8px #070b2c;
    box-shadow: inset -4px -4px 8px rgba(19, 38, 134, 0.8),
      inset 4px 4px 8px #020c61;
  }
}

+104 −0
Original line number Diff line number Diff line
@@ -112,3 +112,107 @@ export const userIcon =
</linearGradient>
</defs>
</svg>

export const menuIcon = (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="32"
    height="28"
    viewBox="0 0 32 28"
  >
    <circle
      cx="2.7617"
      cy="2.76173"
      r="2.76173"
      transform="rotate(90 2.7617 2.76173)"
    />
    <circle
      cx="15.7642"
      cy="2.76173"
      r="2.76173"
      transform="rotate(90 15.7642 2.76173)"
    />
    <circle
      cx="28.7667"
      cy="2.76173"
      r="2.76173"
      transform="rotate(90 28.7667 2.76173)"
    />
    <circle cx="2.7617" cy="14" r="2.76173" transform="rotate(90 2.7617 14)" />
    <circle
      cx="2.7617"
      cy="25.2383"
      r="2.76173"
      transform="rotate(90 2.7617 25.2383)"
    />
    <circle
      cx="15.7642"
      cy="14"
      r="2.76173"
      transform="rotate(90 15.7642 14)"
    />
    <circle
      cx="15.7642"
      cy="25.2383"
      r="2.76173"
      transform="rotate(90 15.7642 25.2383)"
    />
    <circle
      cx="28.7667"
      cy="14"
      r="2.76173"
      transform="rotate(90 28.7667 14)"
    />
    <circle
      cx="28.7667"
      cy="25.2383"
      r="2.76173"
      transform="rotate(90 28.7667 25.2383)"
    />
  </svg>
);

export const menuCloseIcon = (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="31"
    height="31"
    viewBox="0 0 31 31"
    fill="none"
  >
    <circle cx="4.00002" cy="4" r="2.76173" transform="rotate(135 4.00002 4)" />
    <circle cx="10" cy="10" r="2.76173" transform="rotate(135 10 10)" />
    <circle
      cx="15.4621"
      cy="16"
      r="2.76173"
      transform="rotate(135 15.4621 16)"
    />
    <circle cx="21" cy="21" r="2.76173" transform="rotate(135 21 21)" />
    <circle cx="27" cy="27" r="2.76173" transform="rotate(135 27 27)" />
    <circle
      cx="3.9057"
      cy="26.9057"
      r="2.76173"
      transform="rotate(45 3.9057 26.9057)"
    />
    <circle
      cx="9.9057"
      cy="20.9057"
      r="2.76173"
      transform="rotate(45 9.9057 20.9057)"
    />
    <circle
      cx="20.9057"
      cy="9.90568"
      r="2.76173"
      transform="rotate(45 20.9057 9.90568)"
    />
    <circle
      cx="26.9057"
      cy="3.90568"
      r="2.76173"
      transform="rotate(45 26.9057 3.90568)"
    />
  </svg>
);