xlibs-components
Version:
Modern React component library with Aceternity, MagicUI, and ShadCN components for building beautiful web applications
47 lines (46 loc) • 3.61 kB
JavaScript
"use client";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { cn } from '../../lib/utils.js';
import { useState, createContext, useContext } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { IconMenu2, IconX } from "@tabler/icons-react";
const SidebarContext = createContext(undefined);
export const useSidebar = () => {
const context = useContext(SidebarContext);
if (!context) {
throw new Error("useSidebar must be used within a SidebarProvider");
}
return context;
};
export const SidebarProvider = ({ children, open: openProp, setOpen: setOpenProp, animate = true, }) => {
const [openState, setOpenState] = useState(false);
const open = openProp !== undefined ? openProp : openState;
const setOpen = setOpenProp !== undefined ? setOpenProp : setOpenState;
return (_jsx(SidebarContext.Provider, { value: { open, setOpen, animate: animate }, children: children }));
};
export const Sidebar = ({ children, open, setOpen, animate, }) => {
return (_jsx(SidebarProvider, { open: open, setOpen: setOpen, animate: animate, children: children }));
};
export const SidebarBody = (props) => {
return (_jsxs(_Fragment, { children: [_jsx(DesktopSidebar, { ...props }), _jsx(MobileSidebar, { ...props })] }));
};
export const DesktopSidebar = ({ className, children, ...props }) => {
const { open, setOpen, animate } = useSidebar();
return (_jsx(_Fragment, { children: _jsx(motion.div, { className: cn("h-full hidden md:flex md:flex-col bg-gray-50 dark:bg-neutral-800 w-[300px] shrink-0", className), animate: {
width: animate ? (open ? "300px" : "80px") : "300px",
}, onMouseEnter: () => setOpen(true), onMouseLeave: () => setOpen(false), ...props, children: children }) }));
};
export const MobileSidebar = ({ className, children, ...props }) => {
const { open, setOpen } = useSidebar();
return (_jsx(_Fragment, { children: _jsxs("div", { className: cn("h-10 px-4 py-4 flex flex-row md:hidden items-center justify-between bg-neutral-100 dark:bg-neutral-800 w-full"), ...props, children: [_jsx("div", { className: "flex justify-end z-20 w-full", children: _jsx(IconMenu2, { className: "text-neutral-800 dark:text-neutral-200", onClick: () => setOpen(!open) }) }), _jsx(AnimatePresence, { children: open && (_jsxs(motion.div, { initial: { x: "-100%", opacity: 0 }, animate: { x: 0, opacity: 1 }, exit: { x: "-100%", opacity: 0 }, transition: {
duration: 0.3,
ease: "easeInOut",
}, className: cn("fixed h-full w-full inset-0 bg-white dark:bg-neutral-900 p-10 z-[100] flex flex-col justify-between", className), children: [_jsx("div", { className: "absolute right-10 top-10 z-50 text-neutral-800 dark:text-neutral-200", onClick: () => setOpen(!open), children: _jsx(IconX, {}) }), children] })) })] }) }));
};
export const SidebarLink = ({ link, className, ...props }) => {
const { open, animate } = useSidebar();
return (_jsxs("a", { href: link.href, className: cn("flex items-center justify-start gap-2 group/sidebar py-2", className), ...props, children: [link.icon, _jsx(motion.span, { animate: {
display: animate ? (open ? "inline-block" : "none") : "inline-block",
opacity: animate ? (open ? 1 : 0) : 1,
}, className: "text-neutral-700 dark:text-neutral-200 text-sm group-hover/sidebar:translate-x-1 transition duration-150 whitespace-pre inline-block !p-0 !m-0", children: link.label })] }));
};