feat(frontend): add SystemSheet primitive and migrate mesh sheets to §9.11 chrome (#960)

DESIGN.md §9.11 codifies one canonical right-side detail-sheet shell (cyan
rail, mono crumb, italic serif name, mono meta, ESC chip + close glyph,
fixed three-slot toolbar, cyan-underline tabs, ScrollArea body, footer
freshness band). Today the 16 sheet consumers each render their own
header chrome with stock shadcn SheetHeader/SheetTitle.

Introduce <SystemSheet> + <SheetSection> in
frontend/src/components/ui/system-sheet.tsx, composing the existing
<Sheet>/<SheetContent> primitive. Add a backward-compatible showClose
prop to SheetContent so SystemSheet can render its own ESC chip + close
glyph instead of the stock cyan square close.

Migrate the four mesh sheets as the first batch:
* MeshActivitySheet: crumb Fleet › Mesh › Activity, footer freshness from
  most-recent event timestamp.
* MeshOptInSheet: crumb Fleet › Mesh › {nodeName}, meta of opted-in
  count, drops the redundant bottom Close button (ESC chip dismisses).
* MeshDiagnosticsSheet: removes the icon-prefixed title (forbidden by
  §9.11), lifts Refresh/Restart buttons from the body into the toolbar
  band, three SheetSection blocks for sidecar status, streams, cache.
* MeshRouteDetailSheet: adds Overview/Events/Raw tabs, lifts Test probe
  into the toolbar primary slot, footer surfaces last probe latency.
This commit is contained in:
Anso
2026-05-06 23:18:40 -04:00
committed by GitHub
parent fac753a808
commit 4d9617a5c6
6 changed files with 570 additions and 202 deletions
@@ -1,8 +1,9 @@
import { useEffect, useState } from 'react';
import { apiFetch } from '@/lib/api';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { SystemSheet } from '@/components/ui/system-sheet';
import { Input } from '@/components/ui/input';
import { Loader2 } from 'lucide-react';
import { formatTimeAgo } from '@/lib/relativeTime';
import type { MeshActivityEvent } from '@/types/mesh';
interface Props {
@@ -42,45 +43,55 @@ export function MeshActivitySheet({ open, onOpenChange }: Props) {
);
});
const mostRecentTs = events.length > 0 ? Math.max(...events.map((e) => e.ts)) : null;
const meta = events.length === 0
? '0 events'
: filter
? `${visible.length} of ${events.length} events`
: `${events.length} events`;
const footerContext = mostRecentTs ? `Last event ${formatTimeAgo(mostRecentTs)}` : 'No events yet';
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent side="right" className="w-[600px] sm:max-w-[600px]">
<SheetHeader>
<SheetTitle>Mesh activity</SheetTitle>
</SheetHeader>
<SystemSheet
open={open}
onOpenChange={onOpenChange}
crumb={['Fleet', 'Mesh', 'Activity']}
name="Mesh activity"
meta={meta}
footerContext={footerContext}
size="lg"
>
<div className="space-y-4">
<Input
placeholder="Filter by alias, type, or message"
value={filter}
onChange={(e) => setFilter(e.target.value)}
className="text-xs font-mono"
/>
<div className="mt-4 space-y-3">
<Input
placeholder="Filter by alias, type, or message"
value={filter}
onChange={(e) => setFilter(e.target.value)}
className="text-xs font-mono"
/>
<div className="max-h-[70vh] overflow-auto space-y-1">
{loading && (
<div className="flex items-center gap-2 text-stat-subtitle text-sm">
<Loader2 className="w-4 h-4 animate-spin" /> Loading
</div>
)}
{!loading && visible.length === 0 && (
<div className="text-xs text-stat-subtitle">No events.</div>
)}
{visible.slice().reverse().map((e, i) => (
<div key={i} className="grid grid-cols-[80px_70px_120px_1fr] gap-2 text-[11px] font-mono py-1 border-b border-card-border/50">
<span className="text-stat-subtitle tabular-nums">{new Date(e.ts).toLocaleTimeString()}</span>
<span className={
e.level === 'error' ? 'text-destructive uppercase tracking-[0.18em]' :
<div className="space-y-1">
{loading && (
<div className="flex items-center gap-2 text-stat-subtitle text-sm">
<Loader2 className="w-4 h-4 animate-spin" /> Loading
</div>
)}
{!loading && visible.length === 0 && (
<div className="text-xs text-stat-subtitle">No events.</div>
)}
{visible.slice().reverse().map((e, i) => (
<div key={i} className="grid grid-cols-[80px_70px_120px_1fr] gap-2 text-[11px] font-mono py-1 border-b border-card-border/50">
<span className="text-stat-subtitle tabular-nums">{new Date(e.ts).toLocaleTimeString()}</span>
<span className={
e.level === 'error' ? 'text-destructive uppercase tracking-[0.18em]' :
e.level === 'warn' ? 'text-warning uppercase tracking-[0.18em]' :
'text-stat-subtitle uppercase tracking-[0.18em]'
}>{e.source}</span>
<span className="text-stat-value">{e.type}</span>
<span className="text-stat-value truncate" title={e.message}>{e.alias ? `[${e.alias}] ` : ''}{e.message}</span>
</div>
))}
</div>
'text-stat-subtitle uppercase tracking-[0.18em]'
}>{e.source}</span>
<span className="text-stat-value">{e.type}</span>
<span className="text-stat-value truncate" title={e.message}>{e.alias ? `[${e.alias}] ` : ''}{e.message}</span>
</div>
))}
</div>
</SheetContent>
</Sheet>
</div>
</SystemSheet>
);
}
@@ -1,9 +1,9 @@
import { useEffect, useState } from 'react';
import { apiFetch } from '@/lib/api';
import { toast } from '@/components/ui/toast-store';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { Button } from '@/components/ui/button';
import { Loader2, RefreshCw, ServerCog } from 'lucide-react';
import { SystemSheet, SheetSection } from '@/components/ui/system-sheet';
import { RefreshCw, ServerCog } from 'lucide-react';
import { formatTimeAgo } from '@/lib/relativeTime';
import type { MeshNodeDiagnostic } from '@/types/mesh';
interface Props {
@@ -29,13 +29,17 @@ export function MeshDiagnosticsSheet({ open, onOpenChange, nodeId, nodeName }: P
const [diag, setDiag] = useState<MeshNodeDiagnostic | null>(null);
const [loading, setLoading] = useState(false);
const [restarting, setRestarting] = useState(false);
const [updatedAt, setUpdatedAt] = useState<number | null>(null);
const refresh = async () => {
if (nodeId == null) return;
setLoading(true);
try {
const res = await apiFetch(`/mesh/nodes/${nodeId}/diagnostic`, { localOnly: true });
if (res.ok) setDiag(await res.json());
if (res.ok) {
setDiag(await res.json());
setUpdatedAt(Date.now());
}
} finally {
setLoading(false);
}
@@ -64,69 +68,78 @@ export function MeshDiagnosticsSheet({ open, onOpenChange, nodeId, nodeName }: P
}
};
const sidecarLabel = diag ? (diag.sidecar.running ? 'sidecar running' : 'sidecar off') : 'sidecar ?';
const pilotLabel = diag ? (diag.pilot.connected ? 'pilot connected' : 'pilot disconnected') : 'pilot ?';
const streamsLabel = `${diag?.activeStreams.length ?? 0} streams`;
const aliasesLabel = `${diag?.aliasCache.length ?? 0} aliases`;
const meta = `${sidecarLabel} · ${pilotLabel} · ${streamsLabel} · ${aliasesLabel}`;
const footerContext = updatedAt ? `Updated ${formatTimeAgo(updatedAt)}` : (loading ? 'Loading…' : 'Never updated');
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent side="right" className="w-[520px] sm:max-w-[520px]">
<SheetHeader>
<SheetTitle className="flex items-center gap-2">
<ServerCog className="w-4 h-4" /> Diagnostics{nodeName ? ` · ${nodeName}` : ''}
</SheetTitle>
</SheetHeader>
<div className="mt-4 space-y-4">
<div className="flex items-center gap-2">
<Button variant="outline" size="sm" onClick={() => { void refresh(); }} disabled={loading}>
{loading ? <Loader2 className="w-3 h-3 mr-1 animate-spin" /> : <RefreshCw className="w-3 h-3 mr-1" />}
Refresh
</Button>
<Button variant="outline" size="sm" onClick={() => { void restart(); }} disabled={restarting}>
{restarting ? <Loader2 className="w-3 h-3 mr-1 animate-spin" /> : null}
Restart sidecar
</Button>
</div>
<div className="grid grid-cols-2 gap-2 rounded border border-card-border bg-card p-3 text-xs">
<div className="text-stat-subtitle">Sidecar</div>
<div className="font-mono text-stat-value">{diag?.sidecar.running ? 'running' : 'off'}</div>
<div className="text-stat-subtitle">Pilot tunnel</div>
<div className="font-mono text-stat-value">{diag?.pilot.connected ? 'connected' : 'disconnected'}</div>
<div className="text-stat-subtitle">Buffered</div>
<div className="font-mono text-stat-value">{diag ? bytesFmt(diag.pilot.bufferedAmount) : '-'}</div>
<div className="text-stat-subtitle">Last seen</div>
<div className="font-mono text-stat-value">{diag?.pilot.lastSeen ? new Date(diag.pilot.lastSeen).toLocaleTimeString() : '-'}</div>
</div>
<div>
<div className="text-[10px] tracking-[0.18em] uppercase text-stat-subtitle font-mono mb-2">Active streams</div>
{(!diag || diag.activeStreams.length === 0) && (
<div className="text-xs text-stat-subtitle">No active streams.</div>
)}
<div className="space-y-1">
{diag?.activeStreams.map((s) => (
<div key={s.streamId} className="flex justify-between rounded border border-card-border bg-card px-2 py-1 text-[11px] font-mono">
<span>#{s.streamId} {s.alias ?? '<no-alias>'}</span>
<span className="text-stat-subtitle">in {bytesFmt(s.bytesIn)} / out {bytesFmt(s.bytesOut)} · {ageFmt(s.ageMs)}</span>
</div>
))}
</div>
</div>
<div>
<div className="text-[10px] tracking-[0.18em] uppercase text-stat-subtitle font-mono mb-2">Resolver cache</div>
{(!diag || diag.aliasCache.length === 0) && (
<div className="text-xs text-stat-subtitle">No aliases registered.</div>
)}
<div className="space-y-1">
{diag?.aliasCache.map((a) => (
<div key={a.host} className="flex justify-between rounded border border-card-border bg-card px-2 py-1 text-[11px] font-mono">
<span>{a.host}</span>
<span className="text-stat-subtitle">node #{a.targetNodeId}:{a.port}</span>
</div>
))}
</div>
</div>
<SystemSheet
open={open}
onOpenChange={onOpenChange}
crumb={['Fleet', 'Mesh', 'Diagnostics']}
name={nodeName ?? 'Diagnostics'}
meta={meta}
primaryAction={{
label: 'Refresh',
icon: RefreshCw,
onClick: () => { void refresh(); },
disabled: loading,
}}
secondaryActions={[
{
label: 'Restart sidecar',
icon: ServerCog,
onClick: () => { void restart(); },
disabled: restarting,
},
]}
footerContext={footerContext}
size="md"
>
<SheetSection title="Pilot · sidecar · transport">
<div className="grid grid-cols-2 gap-x-4 gap-y-1.5 text-xs">
<div className="text-stat-subtitle">Sidecar</div>
<div className="font-mono text-stat-value">{diag?.sidecar.running ? 'running' : 'off'}</div>
<div className="text-stat-subtitle">Pilot tunnel</div>
<div className="font-mono text-stat-value">{diag?.pilot.connected ? 'connected' : 'disconnected'}</div>
<div className="text-stat-subtitle">Buffered</div>
<div className="font-mono text-stat-value">{diag ? bytesFmt(diag.pilot.bufferedAmount) : '-'}</div>
<div className="text-stat-subtitle">Last seen</div>
<div className="font-mono text-stat-value">{diag?.pilot.lastSeen ? new Date(diag.pilot.lastSeen).toLocaleTimeString() : '-'}</div>
</div>
</SheetContent>
</Sheet>
</SheetSection>
<SheetSection title="Active streams">
{(!diag || diag.activeStreams.length === 0) && (
<div className="text-xs text-stat-subtitle">No active streams.</div>
)}
<div className="divide-y divide-card-border/40">
{diag?.activeStreams.map((s) => (
<div key={s.streamId} className="flex justify-between py-1.5 text-[11px] font-mono">
<span>#{s.streamId} {s.alias ?? '<no-alias>'}</span>
<span className="text-stat-subtitle">in {bytesFmt(s.bytesIn)} / out {bytesFmt(s.bytesOut)} · {ageFmt(s.ageMs)}</span>
</div>
))}
</div>
</SheetSection>
<SheetSection title="Resolver cache">
{(!diag || diag.aliasCache.length === 0) && (
<div className="text-xs text-stat-subtitle">No aliases registered.</div>
)}
<div className="divide-y divide-card-border/40">
{diag?.aliasCache.map((a) => (
<div key={a.host} className="flex justify-between py-1.5 text-[11px] font-mono">
<span>{a.host}</span>
<span className="text-stat-subtitle">node #{a.targetNodeId}:{a.port}</span>
</div>
))}
</div>
</SheetSection>
</SystemSheet>
);
}
@@ -1,8 +1,7 @@
import { useEffect, useState } from 'react';
import { apiFetch } from '@/lib/api';
import { toast } from '@/components/ui/toast-store';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from '@/components/ui/sheet';
import { Button } from '@/components/ui/button';
import { SystemSheet } from '@/components/ui/system-sheet';
import { Checkbox } from '@/components/ui/checkbox';
import type { MeshStackEntry } from '@/types/mesh';
import { Loader2 } from 'lucide-react';
@@ -67,30 +66,39 @@ export function MeshOptInSheet({ open, onOpenChange, nodeId, nodeName, onChanged
}
};
const inMeshCount = stacks.filter((s) => s.optedIn).length;
const meta = `${inMeshCount} of ${stacks.length} in mesh`;
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent side="right" className="w-[420px] sm:max-w-[420px]">
<SheetHeader>
<SheetTitle>Mesh stacks on {nodeName}</SheetTitle>
<SheetDescription>
Adding a stack lets its services be reached from other meshed stacks by hostname.
Toggling a stack redeploys it to refresh hostnames.
</SheetDescription>
</SheetHeader>
<div className="mt-4 space-y-2">
{loading && (
<div className="flex items-center gap-2 text-stat-subtitle text-sm">
<Loader2 className="w-4 h-4 animate-spin" /> Loading stacks
</div>
)}
{error && (
<div className="rounded border border-destructive/30 bg-destructive/10 p-2 text-xs text-destructive">
{error}
</div>
)}
{!loading && stacks.length === 0 && (
<div className="text-sm text-stat-subtitle">No stacks deployed on this node yet.</div>
)}
<SystemSheet
open={open}
onOpenChange={onOpenChange}
crumb={['Fleet', 'Mesh', nodeName]}
name={nodeName}
meta={meta}
size="sm"
>
<div className="space-y-4">
<p className="text-sm text-stat-subtitle leading-snug">
Adding a stack lets its services be reached from other meshed stacks by hostname.
Toggling a stack redeploys it to refresh hostnames.
</p>
{loading && (
<div className="flex items-center gap-2 text-stat-subtitle text-sm">
<Loader2 className="w-4 h-4 animate-spin" /> Loading stacks
</div>
)}
{error && (
<div className="rounded border border-destructive/30 bg-destructive/10 p-2 text-xs text-destructive">
{error}
</div>
)}
{!loading && stacks.length === 0 && (
<div className="text-sm text-stat-subtitle">No stacks deployed on this node yet.</div>
)}
<div className="space-y-2">
{stacks.map((stack) => (
<div key={stack.name} className="flex items-center justify-between rounded border border-card-border bg-card px-3 py-2">
<div className="flex items-center gap-3">
@@ -109,10 +117,7 @@ export function MeshOptInSheet({ open, onOpenChange, nodeId, nodeName, onChanged
</div>
))}
</div>
<div className="mt-6 flex justify-end">
<Button variant="outline" size="sm" onClick={() => onOpenChange(false)}>Close</Button>
</div>
</SheetContent>
</Sheet>
</div>
</SystemSheet>
);
}
@@ -1,7 +1,6 @@
import { useEffect, useState } from 'react';
import { apiFetch } from '@/lib/api';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { Button } from '@/components/ui/button';
import { SystemSheet, SheetSection } from '@/components/ui/system-sheet';
import { Badge } from '@/components/ui/badge';
import { Loader2, Activity, ServerCog, Hash } from 'lucide-react';
import type { MeshRouteDiagnostic, MeshActivityEvent, MeshProbeResult } from '@/types/mesh';
@@ -13,12 +12,15 @@ interface Props {
alias: string | null;
}
type RouteTab = 'overview' | 'events' | 'raw';
export function MeshRouteDetailSheet({ open, onOpenChange, alias }: Props) {
const [diag, setDiag] = useState<MeshRouteDiagnostic | null>(null);
const [events, setEvents] = useState<MeshActivityEvent[]>([]);
const [probe, setProbe] = useState<MeshProbeResult | null>(null);
const [probing, setProbing] = useState(false);
const [loading, setLoading] = useState(false);
const [activeTab, setActiveTab] = useState<RouteTab>('overview');
useEffect(() => {
if (!open || !alias) return;
@@ -63,77 +65,106 @@ export function MeshRouteDetailSheet({ open, onOpenChange, alias }: Props) {
const pillState = diag ? meshRouteStateFromBackend(diag.state) : 'not-authorized';
const pill = meshRouteStateTokens(pillState);
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent side="right" className="w-[480px] sm:max-w-[480px]">
<SheetHeader>
<SheetTitle className="font-mono text-sm">{alias}</SheetTitle>
</SheetHeader>
const meta = diag?.target
? `${diag.target.stack}/${diag.target.service}:${diag.target.port} · node #${diag.target.nodeId}`
: (loading ? 'Loading…' : 'No target resolved');
<div className="mt-4 space-y-4">
<div className="flex items-center gap-2">
<span className={`inline-flex items-center px-2 py-0.5 rounded-sm border text-[10px] leading-3 font-mono uppercase tracking-[0.18em] ${pill.toneClass}`}>
{pill.label}
</span>
{diag?.lastProbeMs != null && (
<span className="text-[11px] font-mono text-stat-subtitle">{diag.lastProbeMs}ms</span>
)}
</div>
const footerContext = probe
? (probe.ok ? `Last probe ok · ${probe.latencyMs}ms` : `Last probe failed · ${probe.where ?? 'unknown'}`)
: (diag?.lastProbeMs != null ? `Last probe ${diag.lastProbeMs}ms` : 'No probe run yet');
return (
<SystemSheet
open={open}
onOpenChange={onOpenChange}
crumb={['Fleet', 'Mesh', 'Routes', alias]}
name={alias}
meta={meta}
primaryAction={{
label: probing ? 'Probing…' : 'Test probe',
icon: probing ? Loader2 : Activity,
onClick: () => { void runProbe(); },
disabled: probing,
}}
tabs={[
{ id: 'overview', label: 'Overview' },
{ id: 'events', label: 'Events', count: events.length },
{ id: 'raw', label: 'Raw' },
]}
activeTab={activeTab}
onTabChange={(id) => setActiveTab(id as RouteTab)}
footerContext={footerContext}
size="md"
>
{activeTab === 'overview' && (
<>
<SheetSection title="State" hideHeader>
<div className="flex items-center gap-2">
<span className={`inline-flex items-center px-2 py-0.5 rounded-sm border text-[10px] leading-3 font-mono uppercase tracking-[0.18em] ${pill.toneClass}`}>
{pill.label}
</span>
{probe && (
<Badge variant={probe.ok ? 'default' : 'destructive'} className="text-[10px] font-mono">
{probe.ok ? `ok ${probe.latencyMs}ms` : `${probe.where ?? 'fail'}: ${probe.code ?? 'error'}`}
</Badge>
)}
</div>
</SheetSection>
{diag?.target && (
<div className="grid grid-cols-2 gap-2 rounded border border-card-border bg-card p-3 text-xs">
<div className="text-stat-subtitle">Target node</div>
<div className="font-mono text-stat-value">#{diag.target.nodeId}</div>
<div className="text-stat-subtitle">Stack / service</div>
<div className="font-mono text-stat-value">{diag.target.stack}/{diag.target.service}</div>
<div className="text-stat-subtitle">Port</div>
<div className="font-mono text-stat-value">{diag.target.port}</div>
<div className="text-stat-subtitle">Pilot tunnel</div>
<div className="font-mono text-stat-value">{diag.pilot.connected ? 'connected' : 'disconnected'}</div>
</div>
<SheetSection title="Target">
<div className="grid grid-cols-2 gap-x-4 gap-y-1.5 text-xs">
<div className="text-stat-subtitle">Target node</div>
<div className="font-mono text-stat-value">#{diag.target.nodeId}</div>
<div className="text-stat-subtitle">Stack / service</div>
<div className="font-mono text-stat-value">{diag.target.stack}/{diag.target.service}</div>
<div className="text-stat-subtitle">Port</div>
<div className="font-mono text-stat-value">{diag.target.port}</div>
<div className="text-stat-subtitle">Pilot tunnel</div>
<div className="font-mono text-stat-value">{diag.pilot.connected ? 'connected' : 'disconnected'}</div>
</div>
</SheetSection>
)}
{diag?.lastError && (
<div className="rounded border border-destructive/30 bg-destructive/10 p-3 text-xs">
<div className="text-destructive font-mono uppercase tracking-[0.18em] leading-3 text-[10px] mb-1">last error</div>
<div className="text-stat-value">{diag.lastError.message}</div>
<div className="text-[10px] text-stat-subtitle mt-1">{new Date(diag.lastError.ts).toLocaleString()}</div>
</div>
<SheetSection title="Last error">
<div className="rounded border border-destructive/30 bg-destructive/10 p-3 text-xs">
<div className="text-stat-value">{diag.lastError.message}</div>
<div className="text-[10px] text-stat-subtitle mt-1">{new Date(diag.lastError.ts).toLocaleString()}</div>
</div>
</SheetSection>
)}
</>
)}
<div className="flex items-center gap-2">
<Button size="sm" onClick={() => { void runProbe(); }} disabled={probing}>
{probing ? <Loader2 className="w-3 h-3 mr-1 animate-spin" /> : <Activity className="w-3 h-3 mr-1" />}
Test upstream
</Button>
{probe && (
<Badge variant={probe.ok ? 'default' : 'destructive'} className="text-[10px] font-mono">
{probe.ok ? `ok ${probe.latencyMs}ms` : `${probe.where ?? 'fail'}: ${probe.code ?? 'error'}`}
</Badge>
{activeTab === 'events' && (
<SheetSection title="Recent activity" hideHeader>
<div className="space-y-1">
{loading && <Loader2 className="w-4 h-4 animate-spin text-stat-subtitle" />}
{!loading && events.length === 0 && (
<div className="text-xs text-stat-subtitle">No events yet for this alias.</div>
)}
{events.map((e, i) => (
<div key={i} className="flex items-start gap-2 text-[11px] font-mono">
{e.source === 'sidecar' && <ServerCog className="w-3 h-3 mt-0.5 text-stat-subtitle" />}
{e.source === 'pilot' && <Hash className="w-3 h-3 mt-0.5 text-stat-subtitle" />}
{e.source === 'mesh' && <Activity className="w-3 h-3 mt-0.5 text-stat-subtitle" />}
<span className={`tabular-nums ${e.level === 'error' ? 'text-destructive' : e.level === 'warn' ? 'text-warning' : 'text-stat-value'}`}>
{new Date(e.ts).toLocaleTimeString()} {e.type} {e.message}
</span>
</div>
))}
</div>
</SheetSection>
)}
<div>
<div className="text-[10px] leading-3 tracking-[0.18em] uppercase text-stat-subtitle font-mono mb-2">Recent activity</div>
<div className="space-y-1 max-h-72 overflow-auto">
{loading && <Loader2 className="w-4 h-4 animate-spin text-stat-subtitle" />}
{!loading && events.length === 0 && (
<div className="text-xs text-stat-subtitle">No events yet for this alias.</div>
)}
{events.map((e, i) => (
<div key={i} className="flex items-start gap-2 text-[11px] font-mono">
{e.source === 'sidecar' && <ServerCog className="w-3 h-3 mt-0.5 text-stat-subtitle" />}
{e.source === 'pilot' && <Hash className="w-3 h-3 mt-0.5 text-stat-subtitle" />}
{e.source === 'mesh' && <Activity className="w-3 h-3 mt-0.5 text-stat-subtitle" />}
<span className={`tabular-nums ${e.level === 'error' ? 'text-destructive' : e.level === 'warn' ? 'text-warning' : 'text-stat-value'}`}>
{new Date(e.ts).toLocaleTimeString()} {e.type} {e.message}
</span>
</div>
))}
</div>
</div>
</div>
</SheetContent>
</Sheet>
{activeTab === 'raw' && (
<SheetSection title="Diagnostic JSON" hideHeader>
<pre className="text-[11px] font-mono text-stat-value bg-card border border-card-border rounded p-3 overflow-x-auto whitespace-pre-wrap break-all">
{diag ? JSON.stringify(diag, null, 2) : 'No diagnostic data loaded.'}
</pre>
</SheetSection>
)}
</SystemSheet>
);
}