59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { Divider } from "@heroui/react";
|
|
import { PanelLeftClose, PanelLeftOpen, Pin, PinOff } from "lucide-react";
|
|
import React from "react";
|
|
import UserArea from "../UserArea";
|
|
import { useSidenavStore } from "./store";
|
|
import { motion } from "framer-motion";
|
|
import IconButton from "shared/ui/primitives/IconButton";
|
|
import { ThemeSwitch } from "shared/ui/themeSwitch";
|
|
|
|
const sidenavVariants = {
|
|
open: { width: "20rem" },
|
|
closed: { width: "0rem" },
|
|
};
|
|
const sidenavTransition = { duration: 0.5, ease: [0.25, 0.1, 0.25, 1] };
|
|
|
|
export const SideNav = ({ children }: { children: React.ReactNode }) => {
|
|
const { open, pinned, togglePinned, toggleSidenav } = useSidenavStore();
|
|
|
|
return (
|
|
<motion.div
|
|
animate={open ? "open" : "closed"}
|
|
className={`${pinned ? "relative" : "fixed top-0 left-0"} h-dvh overflow-hidden z-40 shrink-0`}
|
|
initial={false}
|
|
transition={sidenavTransition}
|
|
variants={sidenavVariants}
|
|
>
|
|
<div className="flex flex-col h-dvh bg-default-50 text-default-900 p-4 gap-2 border-r border-default-200 w-80">
|
|
<div className="flex items-center justify-between h-10">
|
|
<IconButton
|
|
onClick={toggleSidenav}
|
|
icon={open ? PanelLeftClose : PanelLeftOpen}
|
|
/>
|
|
<IconButton
|
|
onClick={togglePinned}
|
|
icon={pinned ? Pin : PinOff}
|
|
/>
|
|
</div>
|
|
|
|
{/* Use theme-aware background color for divider */}
|
|
<Divider className="my-2 bg-default-200" />
|
|
|
|
{/* Content area */}
|
|
<div className={"h-full overflow-hidden py-4"}>{children}</div>
|
|
|
|
{/* Use theme-aware background color for divider */}
|
|
<Divider className="my-2 bg-default-200" />
|
|
|
|
{/* Footer with User Info and Theme Switch */}
|
|
<div className="flex justify-between items-center gap-2 shrink-0">
|
|
<UserArea />
|
|
<ThemeSwitch />
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
};
|