Skip to content

Commit

Permalink
refactor: Sidebar & Auth Layout -> Table Scroll fix
Browse files Browse the repository at this point in the history
  • Loading branch information
pantheredeye committed Dec 10, 2024
1 parent d1669ff commit 28d9c5a
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 163 deletions.
176 changes: 82 additions & 94 deletions web/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
import { useState } from 'react'

import {

Check failure on line 1 in web/src/components/Sidebar/Sidebar.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

There should be at least one empty line between import groups
HomeIcon,
UsersIcon,
FolderIcon,
DocumentDuplicateIcon,
ChevronLeftIcon,
ChevronRightIcon,
ArrowLeftOnRectangleIcon, // Logout icon
ArrowUturnLeftIcon, // Back icon
ArrowLeftOnRectangleIcon,
ArrowUturnLeftIcon,
UserIcon,
} from '@heroicons/react/24/outline'

import { Link } from '@redwoodjs/router'

Check failure on line 10 in web/src/components/Sidebar/Sidebar.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

There should be at least one empty line between import groups

import { useAuth } from 'src/auth'

function classNames(...classes) {
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(' ')
}

const actions = [
{ name: 'Back', action: 'back', icon: ArrowUturnLeftIcon },
{ name: 'Logout', action: 'logout', icon: ArrowLeftOnRectangleIcon },
]

const Sidebar = () => {
const [isCollapsed, setIsCollapsed] = useState(false)
const Sidebar = ({
isCollapsed = false,
setIsCollapsed,

Check failure on line 19 in web/src/components/Sidebar/Sidebar.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

'setIsCollapsed' is defined but never used. Allowed unused args must match /^_/u
setSidebarOpen, // Optional
}: {
isCollapsed: boolean
setIsCollapsed: (collapsed: boolean) => void
setSidebarOpen?: (open: boolean) => void // Mark as optional
}) => {
const { logOut } = useAuth()
const { currentUser } = useAuth()

Expand All @@ -41,98 +37,90 @@ const Sidebar = () => {
icon: UserIcon,
},
]
return (
<div
className={classNames(
'flex flex-col transition-all duration-300',
isCollapsed ? 'w-20' : 'w-64',
'bg-gray-900 text-gray-300',
'shadow-inner'
)}
>
{/* Header with Title and Collapse Button */}
<div className="flex h-16 items-center justify-between px-4">
{!isCollapsed && (
<span className="text-2xl font-bold text-gray-200">SWPPP-TOP</span>

const actions = [
{
name: 'Back',
action: () => window.history.back(),
icon: ArrowUturnLeftIcon,
},
{ name: 'Logout', action: logOut, icon: ArrowLeftOnRectangleIcon },
]

const NavigationItem = ({ name, href, Icon }) => (
<li>
<Link
to={href}
className={classNames(
'group relative flex items-center rounded-xl px-2 py-2 text-sm font-medium',
'bg-gray-800 hover:bg-gray-700',
'shadow-lg',
isCollapsed ? 'justify-center' : 'justify-start'
)}
<button
onClick={() => setIsCollapsed(!isCollapsed)}
className="text-gray-300 hover:text-gray-400 focus:outline-none"
>
{isCollapsed ? (
<ChevronRightIcon className="h-6 w-6" aria-hidden="true" />
) : (
<ChevronLeftIcon className="h-6 w-6" aria-hidden="true" />
)}
</button>
onClick={() => {
if (setSidebarOpen) setSidebarOpen(false) // Close sidebar if the function exists
}}
>
<Icon
className="h-6 w-6 text-gray-400 group-hover:text-gray-200"
aria-hidden="true"
aria-label={name}
/>
{!isCollapsed && <span className="ml-3 text-gray-200">{name}</span>}
{isCollapsed && (
<span className="absolute left-full ml-3 w-auto min-w-max whitespace-nowrap rounded-md bg-gray-800 px-2 py-1 text-xs text-gray-200 opacity-0 group-hover:opacity-100">
{name}
</span>
)}
</Link>
</li>
)

const ActionItem = ({ name, action, Icon }) => (
<li>
<button
onClick={action}
className="group flex w-full items-center rounded-xl px-2 py-2 text-sm font-medium bg-gray-800 hover:bg-gray-700 shadow-lg"
>
<Icon
className="h-6 w-6 text-gray-400 group-hover:text-gray-200"
aria-hidden="true"
/>
<span className="ml-3 text-gray-200">{name}</span>
</button>
</li>
)

return (
<div className="flex flex-col w-64 bg-gray-900 text-gray-300 shadow-inner">
<div className="flex h-16 items-center px-4">
<span className="text-2xl font-bold text-gray-200">SWPPP-TOP</span>
</div>

{/* Navigation */}
<nav className="flex-1 px-2">
<ul className="space-y-2">
{navigation.map((item) => (
<li key={item.name}>
<Link
to={item.href}
className={classNames(
'group relative flex items-center rounded-xl px-2 py-2 text-sm font-medium',
'bg-gray-800 hover:bg-gray-700',
'shadow-lg',
isCollapsed ? 'justify-center' : 'justify-start'
)}
>
<item.icon
className="h-6 w-6 text-gray-400 group-hover:text-gray-200"
aria-hidden="true"
/>
{!isCollapsed && (
<span className="ml-3 text-gray-200">{item.name}</span>
)}
{isCollapsed && (
<span className="absolute left-full ml-3 w-auto min-w-max whitespace-nowrap rounded-md bg-gray-800 px-2 py-1 text-xs text-gray-200 opacity-0 group-hover:opacity-100">
{item.name}
</span>
)}
</Link>
</li>
<NavigationItem
key={item.name}
name={item.name}
href={item.href}
Icon={item.icon}
/>
))}
</ul>
</nav>

{/* Actions at the Bottom */}
{/* Actions */}
<div className="px-2 py-2 pb-4">
<ul className="space-y-2">
{actions.map((action) => (
<li key={action.name}>
<button
onClick={() => {
if (action.action === 'back') {
window.history.back()
} else if (action.action === 'logout') {
logOut()
}
}}
className={classNames(
'group relative flex w-full items-center rounded-xl px-2 py-2 text-sm font-medium',
'bg-gray-800 hover:bg-gray-700',
'shadow-lg',
isCollapsed ? 'justify-center' : 'justify-start'
)}
>
<action.icon
className="h-6 w-6 text-gray-400 group-hover:text-gray-200"
aria-hidden="true"
/>
{!isCollapsed && (
<span className="ml-3 text-gray-200">{action.name}</span>
)}
{isCollapsed && (
<span className="absolute left-full ml-3 w-auto min-w-max whitespace-nowrap rounded-md bg-gray-800 px-2 py-1 text-xs text-gray-200 opacity-0 group-hover:opacity-100">
{action.name}
</span>
)}
</button>
</li>
<ActionItem
key={action.name}
name={action.name}
action={action.action}
Icon={action.icon}
/>
))}
</ul>
</div>
Expand Down
112 changes: 43 additions & 69 deletions web/src/layouts/AuthenticatedLayout/AuthenticatedLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { useState, Fragment, ReactNode } from 'react'

Check failure on line 1 in web/src/layouts/AuthenticatedLayout/AuthenticatedLayout.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

There should be at least one empty line between import groups

import {
Dialog,
DialogPanel,
Transition,
TransitionChild,
} from '@headlessui/react'
import { Dialog, Transition } from '@headlessui/react'
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'

Check failure on line 3 in web/src/layouts/AuthenticatedLayout/AuthenticatedLayout.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

There should be at least one empty line between import groups

import Sidebar from 'src/components/Sidebar'

interface AuthenticatedLayoutProps {
Expand All @@ -16,97 +9,78 @@ interface AuthenticatedLayoutProps {

const AuthenticatedLayout = ({ children }: AuthenticatedLayoutProps) => {
const [sidebarOpen, setSidebarOpen] = useState(false)
const [isCollapsed, setIsCollapsed] = useState(false);

Check warning on line 12 in web/src/layouts/AuthenticatedLayout/AuthenticatedLayout.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

Delete `;`

return (
<div className="flex min-h-screen bg-gray-900 font-sans text-gray-300">
<div className="min-h-screen bg-gray-900 font-sans text-gray-300">
{/* Mobile Sidebar */}
<Transition show={sidebarOpen} as={Fragment}>
<Dialog
as="div"
className="relative z-50 lg:hidden"
onClose={() => setSidebarOpen(false)}
onClose={setSidebarOpen}
>
<TransitionChild
<Transition.Child
as={Fragment}
enter="transition-opacity ease-linear duration-300"
enter="transition-opacity duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leave="transition-opacity duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-900 bg-opacity-80" />
</TransitionChild>
<div className="fixed inset-0 bg-gray-800 bg-opacity-75" />
</Transition.Child>

<div className="fixed inset-0 flex">
<TransitionChild
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"
>
<DialogPanel className="relative flex w-full max-w-xs flex-1 bg-gray-900 shadow-lg">
<TransitionChild
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="text-gray-300 hover:text-gray-200 focus:outline-none"
onClick={() => setSidebarOpen(false)}
>
<span className="sr-only">Close sidebar</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
</TransitionChild>
<Sidebar />
</DialogPanel>
</TransitionChild>
</div>
<Transition.Child
as={Fragment}
enter="transition-transform duration-300"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="transition-transform duration-300"
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
<Dialog.Panel className="fixed inset-y-0 left-0 w-64 bg-gray-900 p-4 shadow-lg">
{/* Close Button */}
<button
className="text-gray-300 hover:text-white"
onClick={() => setSidebarOpen(false)}
>
<XMarkIcon className="h-6 w-6" />
</button>
<Sidebar
isCollapsed={isCollapsed}
setIsCollapsed={setIsCollapsed}
setSidebarOpen={setSidebarOpen} // Pass the function
/>{' '}
</Dialog.Panel>
</Transition.Child>
</Dialog>
</Transition>

{/* Desktop Sidebar */}
<div className="hidden lg:flex lg:w-64 lg:flex-col lg:shadow-lg">
<Sidebar />
<div className="hidden lg:flex lg:w-64 lg:flex-shrink-0">
<Sidebar isCollapsed={isCollapsed} setIsCollapsed={setIsCollapsed} />{' '}
</div>

{/* Main Content */}
<div className="flex flex-1 flex-col border-l border-gray-700">
{/* Mobile Sidebar Toggle */}
<div className="px-4 py-2 lg:hidden">
<div className="flex flex-1 flex-col lg:ml-64">
{/* Mobile Menu Toggle */}
<header className="p-4 lg:hidden">
<button
type="button"
className="text-gray-300 hover:text-gray-200 focus:outline-none"
className="text-gray-300 hover:text-white"
onClick={() => setSidebarOpen(true)}
>
<span className="sr-only">Open sidebar</span>
<Bars3Icon className="h-6 w-6" aria-hidden="true" />
<Bars3Icon className="h-6 w-6" />
</button>
</div>
</header>

{/* Main Section */}
<main className="flex-grow py-10">
<div className="px-4 sm:px-6 lg:px-8">
{/* Example of a card/container following the style guide */}
<div className="rounded-xl bg-gray-800 p-3 shadow-lg">
{children}
</div>
</div>
</main>
<main className="flex-grow p-6">{children}</main>

{/* Footer */}
<footer className="bg-gray-900 py-4 text-center">
<footer className="bg-gray-900 p-4 text-center">
<p className="text-sm text-gray-500">
&copy; 2024 SWPPP-TOP. All rights reserved.
</p>
Expand Down

0 comments on commit 28d9c5a

Please sign in to comment.