diff --git a/ui/src/components/Layout.tsx b/ui/src/components/Layout.tsx
index 73b4d05..7f93f50 100644
--- a/ui/src/components/Layout.tsx
+++ b/ui/src/components/Layout.tsx
@@ -1,4 +1,6 @@
-import { Outlet, useNavigate } from 'react-router';
+import { useState, useMemo } from 'react';
+import { Outlet, useNavigate, useLocation } from 'react-router';
+import { LayoutDashboard, ShieldCheck, Building, Activity } from 'lucide-react';
import {
AppShell,
Sidebar,
@@ -21,54 +23,23 @@ function CameleerLogo() {
);
}
-// Nav icon helpers
-function DashboardIcon() {
- return (
-
- );
-}
-
-function LicenseIcon() {
- return (
-
- );
-}
-
-function ObsIcon() {
- return (
-
- );
-}
-
-function PlatformIcon() {
- return (
-
- );
-}
-
export function Layout() {
const navigate = useNavigate();
+ const location = useLocation();
const { logout } = useAuth();
const scopes = useScopes();
const { username } = useOrgStore();
+ const [collapsed, setCollapsed] = useState(false);
+
+ const breadcrumb = useMemo(() => {
+ if (location.pathname.startsWith('/admin')) return [{ label: 'Admin' }, { label: 'Tenants' }];
+ if (location.pathname.startsWith('/license')) return [{ label: 'License' }];
+ return [{ label: 'Dashboard' }];
+ }, [location.pathname]);
+
const sidebar = (
- {}}>
+ setCollapsed(c => !c)}>
}
title="Cameleer SaaS"
@@ -77,9 +48,10 @@ export function Layout() {
{/* Dashboard */}
}
+ icon={}
label="Dashboard"
open={false}
+ active={location.pathname === '/' || location.pathname === ''}
onToggle={() => navigate('/')}
>
{null}
@@ -87,9 +59,10 @@ export function Layout() {
{/* License */}
}
+ icon={}
label="License"
open={false}
+ active={location.pathname.startsWith('/license')}
onToggle={() => navigate('/license')}
>
{null}
@@ -98,9 +71,10 @@ export function Layout() {
{/* Platform Admin section */}
{scopes.has('platform:admin') && (
}
+ icon={}
label="Platform"
open={false}
+ active={location.pathname.startsWith('/admin')}
onToggle={() => navigate('/admin/tenants')}
>
{null}
@@ -110,7 +84,7 @@ export function Layout() {
{/* Link to the server observability dashboard */}
}
+ icon={}
label="Open Server Dashboard"
onClick={() => window.open('/server/', '_blank', 'noopener')}
/>
@@ -120,9 +94,17 @@ export function Layout() {
return (
+ {/*
+ * TopBar always renders status filters, time range pills, auto-refresh, and
+ * command palette search via useGlobalFilters() / useCommandPalette(). Both
+ * hooks throw if their providers are absent, so GlobalFilterProvider and
+ * CommandPaletteProvider cannot be removed from main.tsx without crashing the
+ * app. The TopBar API has no props to suppress these server-oriented controls.
+ * Hiding them on platform pages would require a DS change.
+ */}