Răsfoiți Sursa

simplify sidebar

Matthew Trejo 2 luni în urmă
părinte
comite
9db52d06e2

+ 1 - 2
src/components/AuthenticatedLayout.tsx

@@ -44,8 +44,7 @@ export default function AuthenticatedLayout({ children }: AuthenticatedLayoutPro
         onToggleCollapse={() => setIsSidebarCollapsed(!isSidebarCollapsed)} 
       />
       <div 
-        className="min-h-screen flex flex-col transition-all duration-300"
-        style={{ marginLeft: isSidebarCollapsed ? '4rem' : '16rem' }}
+        className={`min-h-screen flex flex-col transition-all duration-300 ${isSidebarCollapsed ? 'lg:ml-16' : 'lg:ml-64'}`}
       >
         <main className="flex-1 lg:pt-0 pt-16">
           {children}

+ 105 - 39
src/components/Sidebar.tsx

@@ -1,12 +1,12 @@
 "use client"
 
-import { useState } from "react"
+import { useState, useEffect, Fragment } from "react"
 import { Menu, ChevronLeft, ChevronRight } from "lucide-react"
+import { Dialog, Transition } from "@headlessui/react"
 import SidebarHeader from "@/components/sidebar/SidebarHeader"
 import SidebarUserInfo from "@/components/sidebar/SidebarUserInfo"
 import SidebarNavigation from "@/components/sidebar/SidebarNavigation"
 import SidebarFooter from "@/components/sidebar/SidebarFooter"
-import MobileSidebar from "@/components/sidebar/MobileSidebar"
 
 interface SidebarProps {
   isCollapsed?: boolean
@@ -16,62 +16,128 @@ interface SidebarProps {
 export default function Sidebar({ isCollapsed: externalIsCollapsed, onToggleCollapse }: SidebarProps) {
   const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
   const [internalIsCollapsed, setInternalIsCollapsed] = useState(false)
+  const [isDesktop, setIsDesktop] = useState(false)
   
   const isCollapsed = externalIsCollapsed !== undefined ? externalIsCollapsed : internalIsCollapsed
   const toggleCollapse = onToggleCollapse || (() => setInternalIsCollapsed(!internalIsCollapsed))
 
+  useEffect(() => {
+    const checkDesktop = () => setIsDesktop(window.innerWidth >= 1024)
+    checkDesktop()
+    window.addEventListener('resize', checkDesktop)
+    return () => window.removeEventListener('resize', checkDesktop)
+  }, [])
 
+  const handleButtonClick = () => {
+    if (isDesktop) {
+      toggleCollapse()
+    } else {
+      setIsMobileMenuOpen(true)
+    }
+  }
 
   return (
     <>
-      {/* Botón del menú móvil */}
+      {/* Botón flotante unificado */}
       <button
         type="button"
-        className="lg:hidden fixed top-4 left-4 z-50 p-2 rounded-md shadow-lg border border-gray-200 bg-white"
-        onClick={() => setIsMobileMenuOpen(true)}
+        className="fixed top-4 left-4 z-50 p-2 rounded-md shadow-lg border border-gray-200 bg-white"
+        onClick={handleButtonClick}
       >
-        <Menu className="h-6 w-6 text-gray-600" />
+        {isDesktop ? (
+          isCollapsed ? (
+            <ChevronRight className="h-6 w-6 text-gray-600" />
+          ) : (
+            <ChevronLeft className="h-6 w-6 text-gray-600" />
+          )
+        ) : (
+          <Menu className="h-6 w-6 text-gray-600" />
+        )}
       </button>
 
-      {/* Sidebar móvil */}
-      <MobileSidebar 
-        isOpen={isMobileMenuOpen} 
-        onClose={() => setIsMobileMenuOpen(false)} 
-      />
-
       {/* Sidebar de escritorio */}
-      <div 
-        className="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:flex-col transition-all duration-300"
-        style={{ width: isCollapsed ? '4rem' : '18rem' }}
-      >
+      {isDesktop && (
         <div 
-          className="flex grow flex-col overflow-y-auto border-r border-gray-200 bg-white shadow-sm"
+          className="fixed inset-y-0 left-0 z-50 flex flex-col transition-all duration-300"
+          style={{ width: isCollapsed ? '4rem' : '18rem' }}
         >
-          {/* Botón de toggle */}
-          <div className={`flex ${isCollapsed ? 'justify-center' : 'justify-end'} p-4 border-b border-gray-200`}>
-            <button
-              onClick={toggleCollapse}
-              className="p-1.5 rounded-md hover:bg-gray-100 transition-colors"
-              title={isCollapsed ? 'Expandir sidebar' : 'Colapsar sidebar'}
-            >
-              {isCollapsed ? (
-                <ChevronRight className="h-4 w-4 text-gray-600" />
-              ) : (
-                <ChevronLeft className="h-4 w-4 text-gray-600" />
-              )}
-            </button>
+          <div 
+            className="flex grow flex-col overflow-y-auto border-r border-gray-200 bg-white shadow-sm"
+          >
+            {/* Botón de toggle removido, ahora flotante */}
+            
+            <SidebarHeader isCollapsed={isCollapsed} />
+            <SidebarNavigation isCollapsed={isCollapsed} />
+            
+            {/* User info y footer al final */}
+            <div className="mt-auto">
+              <SidebarUserInfo isCollapsed={isCollapsed} />
+              <SidebarFooter isCollapsed={isCollapsed} />
+            </div>
           </div>
+        </div>
+      )}
 
-          <SidebarHeader isCollapsed={isCollapsed} />
-          <SidebarNavigation isCollapsed={isCollapsed} />
-          
-          {/* User info y footer al final */}
-          <div className="mt-auto">
-            <SidebarUserInfo isCollapsed={isCollapsed} />
-            <SidebarFooter isCollapsed={isCollapsed} />
+      {/* Sidebar móvil */}
+      <Transition.Root show={!isDesktop && isMobileMenuOpen} as={Fragment}>
+        <Dialog as="div" className="relative z-50 lg:hidden" onClose={() => setIsMobileMenuOpen(false)}>
+          <Transition.Child
+            as={Fragment}
+            enter="transition-opacity ease-linear duration-300"
+            enterFrom="opacity-0"
+            enterTo="opacity-100"
+            leave="transition-opacity ease-linear duration-300"
+            leaveFrom="opacity-100"
+            leaveTo="opacity-0"
+          >
+            <div 
+              className="fixed inset-0"
+              style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
+            />
+          </Transition.Child>
+
+          <div className="fixed inset-0 flex">
+            <Transition.Child
+              as={Fragment}
+              enter="transition ease-in-out duration-300 transform"
+              enterFrom="-translate-x-full"
+              enterTo="translate-x-0"
+              leave="transition ease-in-out duration-300 transform"
+              leaveFrom="translate-x-0"
+              leaveTo="-translate-x-full"
+            >
+              <Dialog.Panel className="relative mr-16 flex w-full max-w-xs flex-1">
+                <Transition.Child
+                  as={Fragment}
+                  enter="ease-in-out duration-300"
+                  enterFrom="opacity-0"
+                  enterTo="opacity-100"
+                  leave="ease-in-out duration-300"
+                  leaveFrom="opacity-100"
+                  leaveTo="opacity-0"
+                >
+                  <div className="absolute left-full top-0 flex w-16 justify-center pt-5">
+                    {/* Botón de cerrar removido, ahora en header */}
+                  </div>
+                </Transition.Child>
+                
+                <div 
+                  className="flex grow flex-col overflow-y-auto ring-1 ring-white/10"
+                  style={{ backgroundColor: 'white' }}
+                >
+                  <SidebarHeader isCollapsed={false} onClose={() => setIsMobileMenuOpen(false)} />
+                  <SidebarNavigation onItemClick={() => setIsMobileMenuOpen(false)} isCollapsed={false} />
+                  
+                  <div className="mt-auto">
+                    <SidebarUserInfo isCollapsed={false} />
+                    <SidebarFooter onItemClick={() => setIsMobileMenuOpen(false)} isCollapsed={false} />
+                  </div>
+                </div>
+              </Dialog.Panel>
+            </Transition.Child>
           </div>
-        </div>
-      </div>
+        </Dialog>
+      </Transition.Root>
     </>
   )
 }

+ 0 - 82
src/components/sidebar/MobileSidebar.tsx

@@ -1,82 +0,0 @@
-"use client"
-
-import { Fragment } from "react"
-import { Dialog, Transition } from "@headlessui/react"
-import { X } from "lucide-react"
-import SidebarHeader from "./SidebarHeader"
-import SidebarUserInfo from "./SidebarUserInfo"
-import SidebarNavigation from "./SidebarNavigation"
-import SidebarFooter from "./SidebarFooter"
-
-interface MobileSidebarProps {
-  isOpen: boolean
-  onClose: () => void
-}
-
-export default function MobileSidebar({ isOpen, onClose }: MobileSidebarProps) {
-  return (
-    <Transition.Root show={isOpen} as={Fragment}>
-      <Dialog as="div" className="relative z-50 lg:hidden" onClose={onClose}>
-        <Transition.Child
-          as={Fragment}
-          enter="transition-opacity ease-linear duration-300"
-          enterFrom="opacity-0"
-          enterTo="opacity-100"
-          leave="transition-opacity ease-linear duration-300"
-          leaveFrom="opacity-100"
-          leaveTo="opacity-0"
-        >
-          <div 
-            className="fixed inset-0"
-            style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
-          />
-        </Transition.Child>
-
-        <div className="fixed inset-0 flex">
-          <Transition.Child
-            as={Fragment}
-            enter="transition ease-in-out duration-300 transform"
-            enterFrom="-translate-x-full"
-            enterTo="translate-x-0"
-            leave="transition ease-in-out duration-300 transform"
-            leaveFrom="translate-x-0"
-            leaveTo="-translate-x-full"
-          >
-            <Dialog.Panel className="relative mr-16 flex w-full max-w-xs flex-1">
-              <Transition.Child
-                as={Fragment}
-                enter="ease-in-out duration-300"
-                enterFrom="opacity-0"
-                enterTo="opacity-100"
-                leave="ease-in-out duration-300"
-                leaveFrom="opacity-100"
-                leaveTo="opacity-0"
-              >
-                <div className="absolute left-full top-0 flex w-16 justify-center pt-5">
-                  <button
-                    type="button"
-                    className="-m-2.5 p-2.5"
-                    onClick={onClose}
-                  >
-                    <span className="sr-only">Cerrar sidebar</span>
-                    <X className="h-6 w-6" style={{ color: 'white' } as React.CSSProperties} aria-hidden="true" />
-                  </button>
-                </div>
-              </Transition.Child>
-              
-              <div 
-                className="flex grow flex-col overflow-y-auto ring-1 ring-white/10"
-                style={{ backgroundColor: 'white' }}
-              >
-                <SidebarHeader isCollapsed={false} />
-                <SidebarUserInfo isCollapsed={false} />
-                <SidebarNavigation onItemClick={onClose} isCollapsed={false} />
-                <SidebarFooter onItemClick={onClose} isCollapsed={false} />
-              </div>
-            </Dialog.Panel>
-          </Transition.Child>
-        </div>
-      </Dialog>
-    </Transition.Root>
-  )
-}

+ 13 - 4
src/components/sidebar/SidebarHeader.tsx

@@ -1,14 +1,23 @@
 "use client"
 
 import Link from "next/link"
-import { Stethoscope } from "lucide-react"
+import { Stethoscope, ChevronLeft } from "lucide-react"
 
-export default function SidebarHeader({ isCollapsed }: { isCollapsed: boolean }) {
+export default function SidebarHeader({ isCollapsed, onClose }: { isCollapsed: boolean, onClose?: () => void }) {
   return (
     <div 
-      className={`${isCollapsed ? 'p-4 flex justify-center' : 'p-6'} border-b border-gray-200 bg-white`}
+      className={`${isCollapsed ? 'p-4 flex justify-center' : 'p-6'} border-b border-gray-200 bg-white relative`}
     >
-      <Link href="/dashboard" className="flex items-center space-x-3">
+      {onClose && (
+        <button
+          onClick={onClose}
+          className="absolute top-4 right-4 p-1 rounded-md hover:bg-gray-100"
+          title="Cerrar sidebar"
+        >
+          <ChevronLeft className="h-5 w-5 text-gray-600" />
+        </button>
+      )}
+      <Link href="/dashboard" className={`flex items-center space-x-3 ${onClose ? 'pr-12' : ''}`}>
         <div 
           className="w-10 h-10 rounded-xl flex items-center justify-center bg-primary"
         >