sidebar spacing and color tweaks

This commit is contained in:
Josh Hawkins 2025-10-08 09:16:44 -05:00
parent 9f05ad9ff1
commit eaa558ffc1
2 changed files with 143 additions and 127 deletions

View File

@ -66,6 +66,7 @@ import {
} from "@/components/mobile/MobilePage"; } from "@/components/mobile/MobilePage";
import { ChevronRight } from "lucide-react"; import { ChevronRight } from "lucide-react";
import { IoMdArrowRoundBack } from "react-icons/io"; import { IoMdArrowRoundBack } from "react-icons/io";
import { cn } from "@/lib/utils";
const allSettingsViews = [ const allSettingsViews = [
"ui", "ui",
@ -403,146 +404,161 @@ export default function Settings() {
} }
return ( return (
<SidebarProvider> <div className="flex h-full flex-col">
<Sidebar variant="inset" className="relative"> <div className="border-b p-4">
<SidebarContent className="bg-background"> <h1 className="text-lg font-medium">
<SidebarMenu> {t("settings", { ns: "common" })}
{settingsGroups.map((group) => { </h1>
const filteredItems = group.items.filter((item) => </div>
visibleSettingsViews.includes(item.key as SettingsType), <SidebarProvider>
); <Sidebar variant="inset" className="relative">
if (filteredItems.length === 0) return null; <SidebarContent className="bg-background">
return ( <SidebarMenu>
<SidebarGroup key={group.label}> {settingsGroups.map((group) => {
<SidebarGroupLabel>{group.label}</SidebarGroupLabel> const filteredItems = group.items.filter((item) =>
{filteredItems.length === 1 ? ( visibleSettingsViews.includes(item.key as SettingsType),
<SidebarMenu> );
<SidebarMenuItem> if (filteredItems.length === 0) return null;
<SidebarMenuButton return (
isActive={page === filteredItems[0].key} <SidebarGroup key={group.label} className="py-1">
onClick={() => { {filteredItems.length === 1 ? (
if ( <SidebarMenu>
!isAdmin && <SidebarMenuItem>
!allowedViewsForViewer.includes( <SidebarMenuButton
filteredItems[0].key as SettingsType, isActive={page === filteredItems[0].key}
)
) {
setPageToggle("ui");
} else {
setPageToggle(
filteredItems[0].key as SettingsType,
);
}
}}
>
<div className="smart-capitalize">
{t("menu." + filteredItems[0].key)}
</div>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
) : (
<SidebarMenuSub>
{filteredItems.map((item) => (
<SidebarMenuSubItem key={item.key}>
<SidebarMenuSubButton
isActive={page === item.key}
onClick={() => { onClick={() => {
if ( if (
!isAdmin && !isAdmin &&
!allowedViewsForViewer.includes( !allowedViewsForViewer.includes(
item.key as SettingsType, filteredItems[0].key as SettingsType,
) )
) { ) {
setPageToggle("ui"); setPageToggle("ui");
} else { } else {
setPageToggle(item.key as SettingsType); setPageToggle(
filteredItems[0].key as SettingsType,
);
} }
}} }}
> >
<div className="smart-capitalize"> <div className="smart-capitalize">
{t("menu." + item.key)} {t("menu." + filteredItems[0].key)}
</div> </div>
</SidebarMenuSubButton> </SidebarMenuButton>
</SidebarMenuSubItem> </SidebarMenuItem>
))} </SidebarMenu>
</SidebarMenuSub> ) : (
)} <>
</SidebarGroup> <SidebarGroupLabel
); className={cn(
})} "cursor-default text-sm",
</SidebarMenu> filteredItems.some((item) => page === item.key)
</SidebarContent> ? "text-primary"
</Sidebar> : "text-sidebar-foreground/80",
<SidebarInset> )}
<div className="flex h-full flex-col"> >
<div className="border-b p-4"> {group.label}
<h1 className="text-lg font-medium">Settings</h1> </SidebarGroupLabel>
</div> <SidebarMenuSub className="mx-1 border-0">
{[ {filteredItems.map((item) => (
"debug", <SidebarMenuSubItem key={item.key}>
"cameras", <SidebarMenuSubButton
"masksAndZones", isActive={page === item.key}
"motionTuner", onClick={() => {
"triggers", if (
].includes(page) && ( !isAdmin &&
<div className="flex items-center justify-end gap-2 border-b p-2"> !allowedViewsForViewer.includes(
{page == "masksAndZones" && ( item.key as SettingsType,
<ZoneMaskFilterButton )
selectedZoneMask={filterZoneMask} ) {
updateZoneMaskFilter={setFilterZoneMask} setPageToggle("ui");
/> } else {
)} setPageToggle(item.key as SettingsType);
<CameraSelectButton }
allCameras={cameras} }}
selectedCamera={selectedCamera} >
setSelectedCamera={setSelectedCamera} <div className="w-full cursor-pointer smart-capitalize">
cameraEnabledStates={cameraEnabledStates} {t("menu." + item.key)}
currentPage={page} </div>
/> </SidebarMenuSubButton>
</div> </SidebarMenuSubItem>
)} ))}
<div className="flex-1 overflow-auto p-2"> </SidebarMenuSub>
{(() => { </>
const CurrentComponent = getCurrentComponent(page); )}
if (!CurrentComponent) return null; </SidebarGroup>
return ( );
<CurrentComponent })}
</SidebarMenu>
</SidebarContent>
</Sidebar>
<SidebarInset>
<div className="flex h-full flex-col">
{[
"debug",
"cameras",
"masksAndZones",
"motionTuner",
"triggers",
].includes(page) && (
<div className="flex items-center justify-end gap-2 border-b p-2">
{page == "masksAndZones" && (
<ZoneMaskFilterButton
selectedZoneMask={filterZoneMask}
updateZoneMaskFilter={setFilterZoneMask}
/>
)}
<CameraSelectButton
allCameras={cameras}
selectedCamera={selectedCamera} selectedCamera={selectedCamera}
setUnsavedChanges={setUnsavedChanges} setSelectedCamera={setSelectedCamera}
selectedZoneMask={filterZoneMask} cameraEnabledStates={cameraEnabledStates}
currentPage={page}
/> />
); </div>
})()} )}
<div className="flex-1 overflow-auto p-2">
{(() => {
const CurrentComponent = getCurrentComponent(page);
if (!CurrentComponent) return null;
return (
<CurrentComponent
selectedCamera={selectedCamera}
setUnsavedChanges={setUnsavedChanges}
selectedZoneMask={filterZoneMask}
/>
);
})()}
</div>
</div> </div>
</div> </SidebarInset>
</SidebarInset> {confirmationDialogOpen && (
{confirmationDialogOpen && ( <AlertDialog
<AlertDialog open={confirmationDialogOpen}
open={confirmationDialogOpen} onOpenChange={() => setConfirmationDialogOpen(false)}
onOpenChange={() => setConfirmationDialogOpen(false)} >
> <AlertDialogContent>
<AlertDialogContent> <AlertDialogHeader>
<AlertDialogHeader> <AlertDialogTitle>
<AlertDialogTitle> {t("dialog.unsavedChanges.title")}
{t("dialog.unsavedChanges.title")} </AlertDialogTitle>
</AlertDialogTitle> <AlertDialogDescription>
<AlertDialogDescription> {t("dialog.unsavedChanges.desc")}
{t("dialog.unsavedChanges.desc")} </AlertDialogDescription>
</AlertDialogDescription> </AlertDialogHeader>
</AlertDialogHeader> <AlertDialogFooter>
<AlertDialogFooter> <AlertDialogCancel onClick={() => handleDialog(false)}>
<AlertDialogCancel onClick={() => handleDialog(false)}> {t("button.cancel", { ns: "common" })}
{t("button.cancel", { ns: "common" })} </AlertDialogCancel>
</AlertDialogCancel> <AlertDialogAction onClick={() => handleDialog(true)}>
<AlertDialogAction onClick={() => handleDialog(true)}> {t("button.save", { ns: "common" })}
{t("button.save", { ns: "common" })} </AlertDialogAction>
</AlertDialogAction> </AlertDialogFooter>
</AlertDialogFooter> </AlertDialogContent>
</AlertDialogContent> </AlertDialog>
</AlertDialog> )}
)} </SidebarProvider>
</SidebarProvider> </div>
); );
} }

View File

@ -119,12 +119,12 @@ module.exports = {
DEFAULT: "hsl(var(--neutral_variant))", DEFAULT: "hsl(var(--neutral_variant))",
}, },
sidebar: { sidebar: {
DEFAULT: "hsl(var(--secondary))", DEFAULT: "hsl(var(--background))",
foreground: "hsl(var(--secondary-foreground))", foreground: "hsl(var(--secondary-foreground))",
primary: "hsl(var(--primary))", primary: "hsl(var(--primary))",
"primary-foreground": "hsl(var(--primary-foreground))", "primary-foreground": "hsl(var(--primary-foreground))",
accent: "hsl(var(--primary-variant))", accent: "hsl(var(--background-alt))",
"accent-foreground": "hsl(var(--primary-foreground))", "accent-foreground": "hsl(var(--primary))",
border: "hsl(var(--border))", border: "hsl(var(--border))",
ring: "hsl(var(--ring))", ring: "hsl(var(--ring))",
}, },