Simplify nav components

This commit is contained in:
Nicolas Mowen 2024-02-27 11:35:49 -07:00
parent 622e9741c0
commit 9e3c9651d3
7 changed files with 134 additions and 177 deletions

View File

@ -1,9 +1,8 @@
import Providers from "@/context/providers"; import Providers from "@/context/providers";
import { BrowserRouter, Routes, Route } from "react-router-dom"; import { BrowserRouter, Routes, Route } from "react-router-dom";
import { useState } from "react";
import Wrapper from "@/components/Wrapper"; import Wrapper from "@/components/Wrapper";
import Sidebar from "@/components/Sidebar"; import Sidebar from "@/components/navigation/Sidebar";
import Header from "@/components/Header"; import Header from "@/components/navigation/Header";
import Live from "@/pages/Live"; import Live from "@/pages/Live";
import Export from "@/pages/Export"; import Export from "@/pages/Export";
import Storage from "@/pages/Storage"; import Storage from "@/pages/Storage";
@ -14,27 +13,25 @@ import NoMatch from "@/pages/NoMatch";
import Settings from "@/pages/Settings"; import Settings from "@/pages/Settings";
import UIPlayground from "./pages/UIPlayground"; import UIPlayground from "./pages/UIPlayground";
import Events from "./pages/Events"; import Events from "./pages/Events";
import { isDesktop } from "react-device-detect"; import { isDesktop, isMobile } from "react-device-detect";
import Statusbar from "./components/Statusbar"; import Statusbar from "./components/Statusbar";
import Bottombar from "./components/navigation/Bottombar";
const mobileInsets = "absolute left-0 top-2 right-0 bottom-0 bottom-16"
const desktopInsets = "absolute left-16 top-16 top-2 right-0 bottom-8"
function App() { function App() {
const [sheetOpen, setSheetOpen] = useState(false);
const toggleNavbar = () => {
setSheetOpen((prev) => !prev);
};
return ( return (
<Providers> <Providers>
<BrowserRouter> <BrowserRouter>
<Wrapper> <Wrapper>
<Header onToggleNavbar={toggleNavbar} />
<div className="w-full h-full pt-2 overflow-hidden"> <div className="w-full h-full pt-2 overflow-hidden">
<Sidebar sheetOpen={sheetOpen} setSheetOpen={setSheetOpen} /> {isDesktop && <Sidebar />}
{isDesktop && <Statusbar />} {isDesktop && <Statusbar />}
{isMobile && <Bottombar />}
<div <div
id="pageRoot" id="pageRoot"
className="absolute left-0 md:left-16 top-16 md:top-2 right-0 bottom-0 md:bottom-8 overflow-hidden" className={`${isDesktop ? desktopInsets : mobileInsets} overflow-hidden`}
> >
<Routes> <Routes>
<Route path="/" element={<Live />} /> <Route path="/" element={<Live />} />

View File

@ -1,63 +0,0 @@
import { Link } from "react-router-dom";
import Logo from "@/components/Logo";
import { LuMenu } from "react-icons/lu";
import { Button } from "@/components/ui/button";
import { ENV } from "@/env";
import { NavLink } from "react-router-dom";
import { navbarLinks } from "@/pages/site-navigation";
import SettingsNavItems from "./settings/SettingsNavItems";
type HeaderProps = {
onToggleNavbar: () => void;
};
function HeaderNavigation() {
return (
<div className="hidden md:flex">
{navbarLinks.map((item) => {
let shouldRender = item.dev ? ENV !== "production" : true;
return (
shouldRender && (
<NavLink
key={item.id}
to={item.url}
className={({ isActive }) =>
`my-2 py-3 px-4 text-muted-foreground flex flex-row items-center text-center rounded-lg gap-2 hover:bg-border ${
isActive ? "font-bold bg-popover text-popover-foreground" : ""
}`
}
>
<div className="text-sm">{item.title}</div>
</NavLink>
)
);
})}
</div>
);
}
function Header({ onToggleNavbar }: HeaderProps) {
return (
<div className="flex gap-10 lg:gap-20 justify-between pt-2 mb-2 border-b-[1px] px-4 items-center md:hidden">
<div className="flex gap-4 items-center flex-shrink-0 m-1">
<Button
variant="ghost"
size="icon"
className="md:hidden"
onClick={onToggleNavbar}
>
<LuMenu />
</Button>
<Link to="/">
<div className="flex flex-row items-center">
<Logo className="w-10 mr-5" />
</div>
</Link>
<HeaderNavigation />
</div>
<SettingsNavItems className="flex flex-shrink-0 md:gap-2" />
</div>
);
}
export default Header;

View File

@ -1,95 +0,0 @@
import { IconType } from "react-icons";
import { NavLink } from "react-router-dom";
import { Sheet, SheetContent } from "@/components/ui/sheet";
import Logo from "./Logo";
import { ENV } from "@/env";
import { navbarLinks } from "@/pages/site-navigation";
import SettingsNavItems from "./settings/SettingsNavItems";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
function Sidebar({
sheetOpen,
setSheetOpen,
}: {
sheetOpen: boolean;
setSheetOpen: (open: boolean) => void;
}) {
const sidebar = (
<aside className="w-[52px] z-10 h-screen sticky top-0 overflow-y-auto scrollbar-hidden py-4 flex flex-col justify-between">
<span tabIndex={0} className="sr-only" />
<div className="w-full flex flex-col gap-0 items-center">
<Logo className="w-8 h-8 mb-6" />
{navbarLinks.map((item) => (
<SidebarItem
key={item.id}
Icon={item.icon}
title={item.title}
url={item.url}
dev={item.dev}
onClick={() => setSheetOpen(false)}
/>
))}
</div>
<SettingsNavItems className="hidden md:flex flex-col items-center mb-8" />
</aside>
);
return (
<>
<div className="hidden md:block">{sidebar}</div>
<Sheet
open={sheetOpen}
modal={false}
onOpenChange={() => setSheetOpen(false)}
>
<SheetContent side="left" className="w-[90px]">
<div className="w-full flex flex-row justify-center"></div>
{sidebar}
</SheetContent>
</Sheet>
</>
);
}
type SidebarItemProps = {
Icon: IconType;
title: string;
url: string;
dev?: boolean;
onClick?: () => void;
};
function SidebarItem({ Icon, title, url, dev, onClick }: SidebarItemProps) {
const shouldRender = dev ? ENV !== "production" : true;
return (
shouldRender && (
<Tooltip>
<NavLink
to={url}
onClick={onClick}
className={({ isActive }) =>
`mx-[10px] mb-6 flex flex-col justify-center items-center rounded-lg ${
isActive
? "font-bold text-primary-foreground bg-primary"
: "text-muted-foreground bg-muted"
}`
}
>
<TooltipTrigger>
<Icon className="w-5 h-5 m-[6px]" />
</TooltipTrigger>
</NavLink>
<TooltipContent side="right">
<p>{title}</p>
</TooltipContent>
</Tooltip>
)
);
}
export default Sidebar;

View File

@ -0,0 +1,26 @@
import { navbarLinks } from "@/pages/site-navigation";
import NavItem from "./NavItem";
import SettingsNavItems from "../settings/SettingsNavItems";
function Bottombar() {
return (
<div className="absolute h-16 left-4 bottom-0 right-4 flex flex-row items-center justify-between">
{navbarLinks.map((item) => (
<NavItem
className=""
variant="secondary"
key={item.id}
Icon={item.icon}
title={item.title}
url={item.url}
dev={item.dev}
/>
))}
<SettingsNavItems className="flex flex-shrink-0 justify-between gap-4" />
</div>
);
}
//
export default Bottombar;

View File

@ -0,0 +1,64 @@
import { IconType } from "react-icons";
import { NavLink } from "react-router-dom";
import { ENV } from "@/env";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
const variants = {
primary: {
active: "font-bold text-primary-foreground bg-primary",
inactive: "text-muted-foreground bg-muted",
},
secondary: {
active: "font-bold text-primary",
inactive: "text-muted-foreground",
},
};
type NavItemProps = {
className: string;
variant?: "primary" | "secondary";
Icon: IconType;
title: string;
url: string;
dev?: boolean;
onClick?: () => void;
};
export default function NavItem({
className,
variant = "primary",
Icon,
title,
url,
dev,
onClick,
}: NavItemProps) {
const shouldRender = dev ? ENV !== "production" : true;
return (
shouldRender && (
<Tooltip>
<NavLink
to={url}
onClick={onClick}
className={({ isActive }) =>
`${className} flex flex-col justify-center items-center rounded-lg ${
variants[variant][isActive ? "active" : "inactive"]
}`
}
>
<TooltipTrigger>
<Icon className="w-5 h-5 m-[6px]" />
</TooltipTrigger>
</NavLink>
<TooltipContent side="right">
<p>{title}</p>
</TooltipContent>
</Tooltip>
)
);
}

View File

@ -0,0 +1,28 @@
import Logo from "../Logo";
import { navbarLinks } from "@/pages/site-navigation";
import SettingsNavItems from "../settings/SettingsNavItems";
import NavItem from "./NavItem";
function Sidebar() {
return (
<aside className="w-[52px] z-10 h-screen sticky top-0 overflow-y-auto scrollbar-hidden py-4 flex flex-col justify-between">
<span tabIndex={0} className="sr-only" />
<div className="w-full flex flex-col gap-0 items-center">
<Logo className="w-8 h-8 mb-6" />
{navbarLinks.map((item) => (
<NavItem
className="mx-[10px] mb-6"
key={item.id}
Icon={item.icon}
title={item.title}
url={item.url}
dev={item.dev}
/>
))}
</div>
<SettingsNavItems className="hidden md:flex flex-col items-center mb-8" />
</aside>
);
}
export default Sidebar;

View File

@ -12,24 +12,24 @@ export default defineConfig({
server: { server: {
proxy: { proxy: {
'/api': { '/api': {
target: 'http://localhost:5000', target: 'http://192.168.50.106:5000',
ws: true, ws: true,
}, },
'/vod': { '/vod': {
target: 'http://localhost:5000' target: 'http://192.168.50.106:5000'
}, },
'/clips': { '/clips': {
target: 'http://localhost:5000' target: 'http://192.168.50.106:5000'
}, },
'/exports': { '/exports': {
target: 'http://localhost:5000' target: 'http://192.168.50.106:5000'
}, },
'/ws': { '/ws': {
target: 'ws://localhost:5000', target: 'ws://192.168.50.106:5000',
ws: true, ws: true,
}, },
'/live': { '/live': {
target: 'ws://localhost:5000', target: 'ws://192.168.50.106:5000',
changeOrigin: true, changeOrigin: true,
ws: true, ws: true,
}, },