mirror of
https://github.com/cssgunc/compass.git
synced 2025-04-09 14:00:15 -04:00
Keep Sidebar fixed + refactor Sidebar.tsx (#38)
* Refactor Sidebar.tsx (for /resource) Will look weird on other pages. * Move sidebar open button into Sidebar.tsx, apply to other pages Significantly reduces boilerplate of sidebar on pages where it is used. * Set sidebar to be open by default * Minor code formatting
This commit is contained in:
parent
354946e19e
commit
d0a315c365
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import Sidebar from "@/components/Sidebar/Sidebar";
|
import Sidebar from "@/components/Sidebar/Sidebar";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
|
|
||||||
import { createClient } from "@/utils/supabase/client";
|
import { createClient } from "@/utils/supabase/client";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
@ -14,7 +13,7 @@ export default function RootLayout({
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [user, setUser] = useState<User>();
|
const [user, setUser] = useState<User>();
|
||||||
|
|
||||||
|
@ -56,34 +55,13 @@ export default function RootLayout({
|
||||||
<div className="flex-row">
|
<div className="flex-row">
|
||||||
{user ? (
|
{user ? (
|
||||||
<div>
|
<div>
|
||||||
{/* button to open sidebar */}
|
<Sidebar
|
||||||
<button
|
setIsSidebarOpen={setIsSidebarOpen}
|
||||||
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
isSidebarOpen={isSidebarOpen}
|
||||||
className={`fixed z-20 p-2 text-gray-500 hover:text-gray-800 left-0`}
|
name={user.username}
|
||||||
aria-label={"Open sidebar"}
|
email={user.email}
|
||||||
>
|
isAdmin={user.role === Role.ADMIN}
|
||||||
{
|
/>
|
||||||
!isSidebarOpen && (
|
|
||||||
<ChevronDoubleRightIcon className="h-5 w-5" />
|
|
||||||
) // Icon for closing the sidebar
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
{/* sidebar */}
|
|
||||||
<div
|
|
||||||
className={`absolute inset-y-0 left-0 transform ${
|
|
||||||
isSidebarOpen
|
|
||||||
? "translate-x-0"
|
|
||||||
: "-translate-x-full"
|
|
||||||
} w-64 transition duration-300 ease-in-out`}
|
|
||||||
>
|
|
||||||
<Sidebar
|
|
||||||
setIsSidebarOpen={setIsSidebarOpen}
|
|
||||||
name={user.username}
|
|
||||||
email={user.email}
|
|
||||||
isAdmin={user.role === Role.ADMIN}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/* page ui */}
|
|
||||||
<div
|
<div
|
||||||
className={`flex-1 transition duration-300 ease-in-out ${
|
className={`flex-1 transition duration-300 ease-in-out ${
|
||||||
isSidebarOpen ? "ml-64" : "ml-0"
|
isSidebarOpen ? "ml-64" : "ml-0"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import Sidebar from "@/components/Sidebar/Sidebar";
|
import Sidebar from "@/components/Sidebar/Sidebar";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
|
|
||||||
import { createClient } from "@/utils/supabase/client";
|
import { createClient } from "@/utils/supabase/client";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
@ -13,7 +12,7 @@ export default function RootLayout({
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
||||||
const [user, setUser] = useState<User>();
|
const [user, setUser] = useState<User>();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
@ -45,34 +44,13 @@ export default function RootLayout({
|
||||||
<div className="flex-row">
|
<div className="flex-row">
|
||||||
{user ? (
|
{user ? (
|
||||||
<div>
|
<div>
|
||||||
{/* button to open sidebar */}
|
<Sidebar
|
||||||
<button
|
name={user.username}
|
||||||
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
email={user.email}
|
||||||
className={`fixed z-20 p-2 text-gray-500 hover:text-gray-800 left-0`}
|
setIsSidebarOpen={setIsSidebarOpen}
|
||||||
aria-label={"Open sidebar"}
|
isSidebarOpen={isSidebarOpen}
|
||||||
>
|
isAdmin={user.role === Role.ADMIN}
|
||||||
{
|
/>
|
||||||
!isSidebarOpen && (
|
|
||||||
<ChevronDoubleRightIcon className="h-5 w-5" />
|
|
||||||
) // Icon for closing the sidebar
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
{/* sidebar */}
|
|
||||||
<div
|
|
||||||
className={`absolute inset-y-0 left-0 transform ${
|
|
||||||
isSidebarOpen
|
|
||||||
? "translate-x-0"
|
|
||||||
: "-translate-x-full"
|
|
||||||
} w-64 transition duration-300 ease-in-out`}
|
|
||||||
>
|
|
||||||
<Sidebar
|
|
||||||
name={user.username}
|
|
||||||
email={user.email}
|
|
||||||
setIsSidebarOpen={setIsSidebarOpen}
|
|
||||||
isAdmin={user.role === Role.ADMIN}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/* page ui */}
|
|
||||||
<div
|
<div
|
||||||
className={`flex-1 transition duration-300 ease-in-out ${
|
className={`flex-1 transition duration-300 ease-in-out ${
|
||||||
isSidebarOpen ? "ml-64" : "ml-0"
|
isSidebarOpen ? "ml-64" : "ml-0"
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import Sidebar from "@/components/Sidebar/Sidebar";
|
import Sidebar from "@/components/Sidebar/Sidebar";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
|
|
||||||
import { createClient } from "@/utils/supabase/client";
|
import { createClient } from "@/utils/supabase/client";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
@ -14,7 +13,7 @@ export default function RootLayout({
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [user, setUser] = useState<User>();
|
const [user, setUser] = useState<User>();
|
||||||
|
|
||||||
|
@ -48,33 +47,14 @@ export default function RootLayout({
|
||||||
<div className="flex-row">
|
<div className="flex-row">
|
||||||
{user ? (
|
{user ? (
|
||||||
<div>
|
<div>
|
||||||
{/* button to open sidebar */}
|
<Sidebar
|
||||||
<button
|
setIsSidebarOpen={setIsSidebarOpen}
|
||||||
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
isSidebarOpen={isSidebarOpen}
|
||||||
className={`fixed z-20 p-2 text-gray-500 hover:text-gray-800 left-0`}
|
name={user.username}
|
||||||
aria-label={"Open sidebar"}
|
email={user.email}
|
||||||
>
|
isAdmin={user.role === Role.ADMIN}
|
||||||
{
|
/>
|
||||||
!isSidebarOpen && (
|
{/* </div>*/}
|
||||||
<ChevronDoubleRightIcon className="h-5 w-5" />
|
|
||||||
) // Icon for closing the sidebar
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
{/* sidebar */}
|
|
||||||
<div
|
|
||||||
className={`absolute inset-y-0 left-0 transform ${
|
|
||||||
isSidebarOpen
|
|
||||||
? "translate-x-0"
|
|
||||||
: "-translate-x-full"
|
|
||||||
} w-64 transition duration-300 ease-in-out`}
|
|
||||||
>
|
|
||||||
<Sidebar
|
|
||||||
setIsSidebarOpen={setIsSidebarOpen}
|
|
||||||
name={user.username}
|
|
||||||
email={user.email}
|
|
||||||
isAdmin={user.role === Role.ADMIN}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/* page ui */}
|
{/* page ui */}
|
||||||
<div
|
<div
|
||||||
className={`flex-1 transition duration-300 ease-in-out ${
|
className={`flex-1 transition duration-300 ease-in-out ${
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import Sidebar from "@/components/Sidebar/Sidebar";
|
import Sidebar from "@/components/Sidebar/Sidebar";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
|
|
||||||
import { createClient } from "@/utils/supabase/client";
|
import { createClient } from "@/utils/supabase/client";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
@ -14,7 +13,7 @@ export default function RootLayout({
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [user, setUser] = useState<User>();
|
const [user, setUser] = useState<User>();
|
||||||
|
|
||||||
|
@ -48,34 +47,13 @@ export default function RootLayout({
|
||||||
<div className="flex-row">
|
<div className="flex-row">
|
||||||
{user ? (
|
{user ? (
|
||||||
<div>
|
<div>
|
||||||
{/* button to open sidebar */}
|
<Sidebar
|
||||||
<button
|
setIsSidebarOpen={setIsSidebarOpen}
|
||||||
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
isSidebarOpen={isSidebarOpen}
|
||||||
className={`fixed z-20 p-2 text-gray-500 hover:text-gray-800 left-0`}
|
name={user.username}
|
||||||
aria-label={"Open sidebar"}
|
email={user.email}
|
||||||
>
|
isAdmin={user.role === Role.ADMIN}
|
||||||
{
|
/>
|
||||||
!isSidebarOpen && (
|
|
||||||
<ChevronDoubleRightIcon className="h-5 w-5" />
|
|
||||||
) // Icon for closing the sidebar
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
{/* sidebar */}
|
|
||||||
<div
|
|
||||||
className={`absolute inset-y-0 left-0 transform ${
|
|
||||||
isSidebarOpen
|
|
||||||
? "translate-x-0"
|
|
||||||
: "-translate-x-full"
|
|
||||||
} w-64 transition duration-300 ease-in-out`}
|
|
||||||
>
|
|
||||||
<Sidebar
|
|
||||||
setIsSidebarOpen={setIsSidebarOpen}
|
|
||||||
name={user.username}
|
|
||||||
email={user.email}
|
|
||||||
isAdmin={user.role === Role.ADMIN}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/* page ui */}
|
|
||||||
<div
|
<div
|
||||||
className={`flex-1 transition duration-300 ease-in-out ${
|
className={`flex-1 transition duration-300 ease-in-out ${
|
||||||
isSidebarOpen ? "ml-64" : "ml-0"
|
isSidebarOpen ? "ml-64" : "ml-0"
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React from "react";
|
||||||
import {
|
import {
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
ChevronDoubleLeftIcon,
|
ChevronDoubleLeftIcon,
|
||||||
|
ChevronDoubleRightIcon,
|
||||||
BookmarkIcon,
|
BookmarkIcon,
|
||||||
ClipboardIcon,
|
ClipboardIcon,
|
||||||
BookOpenIcon,
|
BookOpenIcon,
|
||||||
|
@ -12,6 +13,7 @@ import { UserProfile } from "../resource/UserProfile";
|
||||||
|
|
||||||
interface SidebarProps {
|
interface SidebarProps {
|
||||||
setIsSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
isSidebarOpen: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
|
@ -19,70 +21,96 @@ interface SidebarProps {
|
||||||
|
|
||||||
const Sidebar: React.FC<SidebarProps> = ({
|
const Sidebar: React.FC<SidebarProps> = ({
|
||||||
setIsSidebarOpen,
|
setIsSidebarOpen,
|
||||||
|
isSidebarOpen,
|
||||||
name,
|
name,
|
||||||
email,
|
email,
|
||||||
isAdmin: admin,
|
isAdmin: admin,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="w-64 h-full border border-gray-200 bg-gray-50 px-4">
|
<>
|
||||||
{/* button to close sidebar */}
|
{/* Button to open the sidebar. */}
|
||||||
<div className="flex justify-end">
|
<button
|
||||||
<button
|
onClick={() => setIsSidebarOpen(true)}
|
||||||
onClick={() => setIsSidebarOpen(false)}
|
className={
|
||||||
className="py-2 text-gray-500 hover:text-gray-800"
|
"fixed z-20 p-2 text-gray-500 hover:text-gray-800 left-0"
|
||||||
aria-label="Close sidebar"
|
}
|
||||||
>
|
aria-label={"Open sidebar"}
|
||||||
<ChevronDoubleLeftIcon className="h-5 w-5" />
|
>
|
||||||
</button>
|
{!isSidebarOpen && (
|
||||||
</div>
|
<ChevronDoubleRightIcon className="h-5 w-5" />
|
||||||
<div className="flex flex-col space-y-8">
|
)}
|
||||||
{/* user + logout button */}
|
</button>
|
||||||
<div className="flex items-center p-4 space-x-2 border border-gray-200 rounded-md ">
|
|
||||||
<UserProfile name={name} email={email} />
|
|
||||||
</div>
|
|
||||||
{/* navigation menu */}
|
|
||||||
<div className="flex flex-col space-y-2">
|
|
||||||
<h4 className="text-xs font-semibold text-gray-500">
|
|
||||||
Pages
|
|
||||||
</h4>
|
|
||||||
<nav className="flex flex-col">
|
|
||||||
{admin && (
|
|
||||||
<SidebarItem
|
|
||||||
icon={<LockClosedIcon />}
|
|
||||||
text="Admin"
|
|
||||||
active={true}
|
|
||||||
redirect="/admin"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<SidebarItem
|
{/* The sidebar itself. */}
|
||||||
icon={<HomeIcon />}
|
<div
|
||||||
text="Home"
|
className={
|
||||||
active={true}
|
"fixed left-0 w-64 h-full border border-gray-200 bg-gray-50 px-4 " +
|
||||||
redirect="/home"
|
(isSidebarOpen
|
||||||
/>
|
? "translate-x-0" // Open
|
||||||
<SidebarItem
|
: "-translate-x-full opacity-25") + // Closed
|
||||||
icon={<BookmarkIcon />}
|
" transition duration-300 ease-out" // More animation properties
|
||||||
text="Resources"
|
}
|
||||||
active={true}
|
>
|
||||||
redirect="/resource"
|
{/* Button to close sidebar */}
|
||||||
/>
|
<div className="flex justify-end">
|
||||||
<SidebarItem
|
<button
|
||||||
icon={<ClipboardIcon />}
|
onClick={() => setIsSidebarOpen(false)}
|
||||||
text="Services"
|
className="py-2 text-gray-500 hover:text-gray-800"
|
||||||
active={true}
|
aria-label="Close sidebar"
|
||||||
redirect="/service"
|
>
|
||||||
/>
|
<ChevronDoubleLeftIcon className="h-5 w-5" />
|
||||||
<SidebarItem
|
</button>
|
||||||
icon={<BookOpenIcon />}
|
</div>
|
||||||
text="Training Manuals"
|
|
||||||
active={true}
|
<div className="flex flex-col space-y-8">
|
||||||
redirect="/training-manuals"
|
{/* user + logout button */}
|
||||||
/>
|
<div className="flex items-center p-4 space-x-2 border border-gray-200 rounded-md ">
|
||||||
</nav>
|
<UserProfile name={name} email={email} />
|
||||||
|
</div>
|
||||||
|
{/* navigation menu */}
|
||||||
|
<div className="flex flex-col space-y-2">
|
||||||
|
<h4 className="text-xs font-semibold text-gray-500">
|
||||||
|
Pages
|
||||||
|
</h4>
|
||||||
|
<nav className="flex flex-col">
|
||||||
|
{admin && (
|
||||||
|
<SidebarItem
|
||||||
|
icon={<LockClosedIcon />}
|
||||||
|
text="Admin"
|
||||||
|
active={true}
|
||||||
|
redirect="/admin"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<SidebarItem
|
||||||
|
icon={<HomeIcon />}
|
||||||
|
text="Home"
|
||||||
|
active={true}
|
||||||
|
redirect="/home"
|
||||||
|
/>
|
||||||
|
<SidebarItem
|
||||||
|
icon={<BookmarkIcon />}
|
||||||
|
text="Resources"
|
||||||
|
active={true}
|
||||||
|
redirect="/resource"
|
||||||
|
/>
|
||||||
|
<SidebarItem
|
||||||
|
icon={<ClipboardIcon />}
|
||||||
|
text="Services"
|
||||||
|
active={true}
|
||||||
|
redirect="/service"
|
||||||
|
/>
|
||||||
|
<SidebarItem
|
||||||
|
icon={<BookOpenIcon />}
|
||||||
|
text="Training Manuals"
|
||||||
|
active={true}
|
||||||
|
redirect="/training-manuals"
|
||||||
|
/>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user