sidebar DONE

This commit is contained in:
Tejas Panchal
2025-07-27 15:00:35 +05:30
parent 7166ff2cb7
commit 3bd074bfd8
3 changed files with 121 additions and 90 deletions

View File

@@ -4,6 +4,7 @@ import {
faBars, faBars,
faRandom, faRandom,
faMagnifyingGlass, faMagnifyingGlass,
faXmark,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { useLanguage } from "@/src/context/LanguageContext"; import { useLanguage } from "@/src/context/LanguageContext";
import { Link, useLocation } from "react-router-dom"; import { Link, useLocation } from "react-router-dom";
@@ -109,10 +110,14 @@ function Navbar() {
<div className="md:hidden flex items-center"> <div className="md:hidden flex items-center">
<button <button
onClick={() => setIsMobileSearchOpen(!isMobileSearchOpen)} onClick={() => setIsMobileSearchOpen(!isMobileSearchOpen)}
className="p-[10px] aspect-square bg-[#2a2a2a]/75 text-white/50 hover:text-white rounded-lg transition-colors flex items-center justify-center" className="p-[10px] aspect-square bg-[#2a2a2a]/75 text-white/50 hover:text-white rounded-lg transition-colors flex items-center justify-center w-[38px] h-[38px]"
title="Search Anime" title={isMobileSearchOpen ? "Close Search" : "Search Anime"}
> >
<FontAwesomeIcon icon={faMagnifyingGlass} className="text-lg" /> <FontAwesomeIcon
icon={isMobileSearchOpen ? faXmark : faMagnifyingGlass}
className="w-[18px] h-[18px] transition-transform duration-200"
style={{ transform: isMobileSearchOpen ? 'rotate(90deg)' : 'rotate(0deg)' }}
/>
</button> </button>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,33 @@
.sidebar {
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
}
.sidebar::-webkit-scrollbar {
width: 5px;
}
.sidebar::-webkit-scrollbar-track {
background: transparent;
}
.sidebar::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 20px;
}
body.sidebar-open {
overflow: hidden;
padding-right: 5px; /* Prevent layout shift when scrollbar disappears */
height: 100%;
position: fixed;
width: 100%;
}
/* Wrapper to maintain scroll position when sidebar is opened */
.sidebar-scroll-wrapper {
position: absolute;
width: 100%;
height: 100%;
overflow-y: auto;
}

View File

@@ -1,22 +1,42 @@
import { FaChevronLeft } from "react-icons/fa"; import { FaChevronLeft } from "react-icons/fa";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faFilm, faRandom } from "@fortawesome/free-solid-svg-icons"; import { faFilm, faRandom, faHome, faClock, faFire, faTv, faPlay, faCirclePlay, faFilePen, faPaperPlane } from "@fortawesome/free-solid-svg-icons";
import { useLanguage } from "@/src/context/LanguageContext"; import { useLanguage } from "@/src/context/LanguageContext";
import { useEffect } from "react"; import { useEffect, useRef } from "react";
import { Link, useLocation } from "react-router-dom"; import { Link, useLocation } from "react-router-dom";
import { import "./Sidebar.css";
cleanupScrollbar,
toggleScrollbar, const MENU_ITEMS = [
} from "@/src/helper/toggleScrollbar"; { name: "Home", path: "/home", icon: faHome },
{ name: "Subbed Anime", path: "/subbed-anime", icon: faFilePen },
{ name: "Dubbed Anime", path: "/dubbed-anime", icon: faPlay },
{ name: "Most Popular", path: "/most-popular", icon: faFire },
{ name: "Movies", path: "/movie", icon: faFilm },
{ name: "TV Series", path: "/tv", icon: faTv },
{ name: "OVAs", path: "/ova", icon: faCirclePlay },
{ name: "ONAs", path: "/ona", icon: faPlay },
{ name: "Specials", path: "/special", icon: faClock },
{ name: "Join Telegram", path: "https://t.me/zenime_discussion", icon: faPaperPlane },
];
const Sidebar = ({ isOpen, onClose }) => { const Sidebar = ({ isOpen, onClose }) => {
const { language, toggleLanguage } = useLanguage(); const { language, toggleLanguage } = useLanguage();
const location = useLocation(); const location = useLocation();
const scrollPosition = useRef(0);
useEffect(() => { useEffect(() => {
toggleScrollbar(isOpen); if (isOpen) {
scrollPosition.current = window.pageYOffset;
document.body.classList.add('sidebar-open');
document.body.style.top = `-${scrollPosition.current}px`;
} else {
document.body.classList.remove('sidebar-open');
document.body.style.top = '';
window.scrollTo(0, scrollPosition.current);
}
return () => { return () => {
cleanupScrollbar(); document.body.classList.remove('sidebar-open');
document.body.style.top = '';
}; };
}, [isOpen]); }, [isOpen]);
@@ -28,110 +48,83 @@ const Sidebar = ({ isOpen, onClose }) => {
<> <>
{isOpen && ( {isOpen && (
<div <div
className={`fixed top-0 left-0 bottom-0 right-0 w-screen h-screen transform transition-all duration-400 ease-in-out ${ className="fixed inset-0 transform transition-all duration-400 ease-in-out backdrop-blur-lg bg-black/50"
isOpen ? "backdrop-blur-lg" : "backdrop-blur-none"
}`}
onClick={onClose} onClick={onClose}
style={{ zIndex: 1000000, background: "rgba(32, 31, 49, .8)" }} style={{ zIndex: 1000000 }}
/> />
)} )}
<div <div
className={`fixed h-full top-0 left-0 z-50 flex transition-transform duration-300 ease-in-out ${ className={`fixed h-[100dvh] w-[280px] max-[575px]:w-[260px] top-0 left-0 transform transition-transform duration-300 ease-in-out ${
isOpen ? "translate-x-0" : "-translate-x-full" isOpen ? "translate-x-0" : "-translate-x-full"
}`} }`}
style={{ zIndex: 1000200 }} style={{ zIndex: 1000200 }}
> >
<div <div
className="bg-white/10 w-[260px] py-8 h-full flex flex-col items-start max-[575px]:w-56 overflow-y-auto sidebar" className="bg-[#0a0a0a] w-full h-full flex flex-col items-start overflow-y-auto sidebar"
style={{
zIndex: 300,
borderRight: "1px solid rgba(0, 0, 0, .1)",
}}
> >
<div className="px-4 w-full"> {/* Header */}
<div className="w-full p-6 border-b border-white/5">
<button <button
onClick={onClose} onClick={onClose}
className="w-full text-white flex items-baseline h-fit gap-x-1 z-[100] px-3 py-2 bg-[#4f4d6e] rounded-3xl" className="w-full flex items-center justify-center gap-2 py-2.5 px-4 bg-white/10 hover:bg-white/15 rounded-lg transition-colors"
> >
<FaChevronLeft className="text-sm font-bold" /> <FaChevronLeft className="text-sm" />
<p>Close menu</p> <span className="text-sm font-medium">Close Menu</span>
</button> </button>
</div> </div>
<div className="flex gap-x-7 w-full py-3 justify-center px-auto mt-8 bg-black/10 max-[575px]:gap-x-4 lg:hidden">
{[ {/* Quick Actions */}
{ icon: faRandom, label: "Random" }, <div className="w-full p-4 border-b border-white/5 lg:hidden">
{ icon: faFilm, label: "Movie" }, <div className="grid grid-cols-3 gap-2">
].map((item, index) => (
<Link <Link
to={`/${item.label}`} to="/random"
key={index} className="flex flex-col items-center gap-2 p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-colors"
className="flex flex-col gap-y-1 items-center"
> >
<FontAwesomeIcon <FontAwesomeIcon icon={faRandom} className="text-lg" />
icon={item.icon} <span className="text-xs font-medium">Random</span>
className="text-[#ffbade] text-xl font-bold max-[575px]:text-[15px]"
/>
<p className="text-[15px] max-[575px]:text-[13px]">
{item.label}
</p>
</Link> </Link>
))} <Link
<div className="flex flex-col gap-y-1 items-center w-auto justify-center"> to="/movie"
<div className="flex"> className="flex flex-col items-center gap-2 p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-colors"
>
<FontAwesomeIcon icon={faFilm} className="text-lg" />
<span className="text-xs font-medium">Movie</span>
</Link>
<div className="flex flex-col items-center gap-2 p-3 rounded-lg bg-white/5">
<div className="flex bg-white/10 rounded">
{["EN", "JP"].map((lang, index) => ( {["EN", "JP"].map((lang, index) => (
<button <button
key={lang} key={lang}
onClick={() => toggleLanguage(lang)} onClick={() => toggleLanguage(lang)}
className={`px-1 py-[1px] text-xs font-bold ${ className={`px-2 py-1 text-xs font-medium transition-colors ${
index === 0 ? "rounded-l-[3px]" : "rounded-r-[3px]"
} ${
language === lang language === lang
? "bg-[#ffbade] text-black" ? "bg-white/15 text-white"
: "bg-gray-600 text-white" : "text-white/60 hover:text-white"
} max-[575px]:text-[9px] max-[575px]:py-0`} }`}
> >
{lang} {lang}
</button> </button>
))} ))}
</div> </div>
<div className="w-full"> <span className="text-xs font-medium text-white/60">Language</span>
<p className="whitespace-nowrap text-[15px] max-[575px]:text-[13px]">
Anime name
</p>
</div> </div>
</div> </div>
</div> </div>
<ul className="text-white mt-8 w-full">
{[ {/* Menu Items */}
{ name: "Home", path: "/home" }, <div className="w-full p-2">
{ name: "Subbed Anime", path: "/subbed-anime" }, {MENU_ITEMS.map((item, index) => (
{ name: "Dubbed Anime", path: "/dubbed-anime" },
{ name: "Most Popular", path: "/most-popular" },
{ name: "Movies", path: "/movie" },
{ name: "TV Series", path: "/tv" },
{ name: "OVAs", path: "/ova" },
{ name: "ONAs", path: "/ona" },
{ name: "Specials", path: "/special" },
{
name: "Join Telegram",
path: "https://t.me/zenime_discussion",
},
].map((item, index) => (
<li
key={index}
className="py-4 w-full font-semibold"
style={{ borderBottom: "1px solid rgba(255, 255, 255, .08)" }}
>
<Link <Link
key={index}
to={item.path} to={item.path}
className="px-4 hover:text-[#ffbade] hover:cursor-pointer w-fit line-clamp-1" className="flex items-center gap-3 px-4 py-3 rounded-lg text-white/60 hover:text-white hover:bg-white/5 transition-colors"
> >
{item.name} <FontAwesomeIcon icon={item.icon} className="text-lg w-5" />
<span className="font-medium">{item.name}</span>
</Link> </Link>
</li>
))} ))}
</ul> </div>
</div> </div>
</div> </div>
</> </>