diff --git a/AGENTS.md b/AGENTS.md
index c40611d..9a0d9d9 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -153,7 +153,7 @@ Lessons from getting here:
`SearchAndWatcher`, `TrendsVisualizer`, `SetupPanel`. They use `ds-*`
colors via a mechanical token swap but keep their old layout/type scale, use
`onClick` on non-buttons in places, and `CommandAndQueryBar` /
- `WaveformHistogram` still sit above every non-Issues/RUM tab. Restructure
+ `WaveformHistogram` still sit above every tab except Issues and RUM sessions (`isTriageOverview` in `App.tsx`). Restructure
them onto `FilterBar` + the card/aside pattern when touching them.
### Finding old-pattern usages
@@ -164,3 +164,10 @@ grep -rnE "(bg|text|border|ring|from|to|via)-(slate|zinc|gray|sky|cyan|blue|viol
```
Both must print nothing.
+
+### Working order from here
+
+Initial pass is done. Take **one view at a time** to the full screen pattern
+(FilterBar + card/aside layout, real buttons, fold or restyle the shared
+chrome for that screen), verify it in the browser in both themes, commit, then
+move to the next. Suggested order: Traces, Logs, Metrics, Search, Trends, Setup.
diff --git a/otel-ui/src/App.tsx b/otel-ui/src/App.tsx
index 3205344..0abab6a 100644
--- a/otel-ui/src/App.tsx
+++ b/otel-ui/src/App.tsx
@@ -73,7 +73,7 @@ function App() {
// The Issues tab is the redesigned triage overview: it owns its own filter
// bar and cards, so the legacy anomaly banner and volume waveform above it
// would just duplicate that UI in a different visual language.
- const isTriageOverview = activeTab === "tab0";
+ const isTriageOverview = activeTab === "tab0" || activeTab === "tab7";
if (isCallback) {
return ;
diff --git a/otel-ui/src/components/CommandAndQueryBar.tsx b/otel-ui/src/components/CommandAndQueryBar.tsx
index 37278b8..3d4e722 100644
--- a/otel-ui/src/components/CommandAndQueryBar.tsx
+++ b/otel-ui/src/components/CommandAndQueryBar.tsx
@@ -102,7 +102,7 @@ export const CommandAndQueryBar: React.FC = () => {
{/* Real Anomaly Radar Banner */}
{(errorStats.errorCount > 0 || topOpenIssue) && (
-
+
@@ -130,7 +130,7 @@ export const CommandAndQueryBar: React.FC = () => {
setActiveTab("tab0")}
- className="px-3 py-1 rounded-lg bg-ds-critical hover:bg-ds-critical text-ds-text font-mono text-xs font-bold transition-colors shadow-sm"
+ className="px-3 py-1 rounded-lg bg-ds-critical hover:bg-ds-critical text-ds-text font-mono text-xs font-bold transition-colors"
>
Triage Issues
@@ -148,7 +148,7 @@ export const CommandAndQueryBar: React.FC = () => {
)}
{/* Filter and Telemetry Status Bar */}
-
+
Active Context:
@@ -237,7 +237,7 @@ export const CommandAndQueryBar: React.FC = () => {
diff --git a/otel-ui/src/components/GaugeMeter.tsx b/otel-ui/src/components/GaugeMeter.tsx
index f33c1f5..93c92b6 100644
--- a/otel-ui/src/components/GaugeMeter.tsx
+++ b/otel-ui/src/components/GaugeMeter.tsx
@@ -185,7 +185,7 @@ export const GaugeMeter = ({
);
return (
-
+
@@ -203,7 +203,7 @@ export const GaugeMeter = ({
className="inline-flex items-center gap-1 rounded bg-ds-accent-bg px-1.5 py-0.5 text-[9px] font-mono font-bold text-ds-accent border border-ds-accent/30"
title={`Sum of values across ${podCount} pods`}
>
-
∑
+
∑
{podCount} pods
)}
@@ -287,15 +287,15 @@ export const GaugeMeter = ({
{/* Center Readout */}
{soloPod ? (
-
+
{soloPod}
) : aggLabel ? (
-
+
{aggLabel}
) : podCount !== undefined && podCount > 1 ? (
-
+
{isSum ? "Sum (∑)" : "Avg (μ)"}
) : null}
diff --git a/otel-ui/src/components/MetricsVisualizer.tsx b/otel-ui/src/components/MetricsVisualizer.tsx
index 5d91848..f9e7873 100644
--- a/otel-ui/src/components/MetricsVisualizer.tsx
+++ b/otel-ui/src/components/MetricsVisualizer.tsx
@@ -303,7 +303,7 @@ const MetricCard = ({ name, service, type, points, unit, pods = [], index }: Met
if (active && payload && payload.length) {
const data = payload[0].payload;
return (
-
+
{new Date(data.time).toLocaleTimeString([], {
@@ -394,11 +394,11 @@ const MetricCard = ({ name, service, type, points, unit, pods = [], index }: Met
};
return (
-
+
{currentDisplay.label}
-
+
{valueFormatter.format(currentDisplay.value)}
{unit && {unit} }
@@ -804,7 +804,7 @@ const MetricCard = ({ name, service, type, points, unit, pods = [], index }: Met
{valueFormatter.format(ps.value)}
- {isSelected &&
SOLO }
+ {isSelected &&
SOLO }
);
})}
@@ -939,7 +939,7 @@ export const MetricsVisualizer = () => {
-
+
Live Gauge Dashboard
diff --git a/otel-ui/src/components/NeedleTestModal.tsx b/otel-ui/src/components/NeedleTestModal.tsx
index bee473b..1980e42 100644
--- a/otel-ui/src/components/NeedleTestModal.tsx
+++ b/otel-ui/src/components/NeedleTestModal.tsx
@@ -73,8 +73,8 @@ export const NeedleTestModal: React.FC
= ({ isOpen, onClos
}
return (
-
-
+
+
{/* Header */}
@@ -148,7 +148,7 @@ export const NeedleTestModal: React.FC
= ({ isOpen, onClos
type="button"
onClick={handleClassify}
disabled={loading || !inputText.trim()}
- className="inline-flex items-center gap-2 rounded-xl bg-ds-surface-2 px-4 py-2 text-xs font-bold text-ds-on-accent transition-all hover:opacity-95 active:scale-95 disabled:opacity-50 shadow-lg "
+ className="inline-flex items-center gap-2 rounded-xl bg-ds-surface-2 px-4 py-2 text-xs font-bold text-ds-on-accent transition-all hover:opacity-95 active:scale-95 disabled:opacity-50"
>
{loading ? (
<>
diff --git a/otel-ui/src/components/PatternsVisualizer.tsx b/otel-ui/src/components/PatternsVisualizer.tsx
index 598f873..5269b25 100644
--- a/otel-ui/src/components/PatternsVisualizer.tsx
+++ b/otel-ui/src/components/PatternsVisualizer.tsx
@@ -62,7 +62,7 @@ export function PatternsVisualizer() {
if (loading && patterns.length === 0) return Loading deterministic patterns…
return
-
Similarity Patterns
Exact issues stay separate; broader deterministic patterns are reviewable.
+
Similarity Patterns
Exact issues stay separate; broader deterministic patterns are reviewable.
setQuery(event.target.value)} placeholder="Filter patterns…" className="ml-auto rounded-lg border border-ds-line bg-ds-surface-2 px-3 py-2 text-xs text-ds-text outline-none placeholder:text-ds-text-3 focus:border-ds-accent/40" />
void refresh()} className="inline-flex items-center gap-2 rounded-lg border border-ds-line px-3 py-2 text-[10px] font-bold uppercase tracking-wider text-ds-text-2 hover:text-ds-text"> Refresh
diff --git a/otel-ui/src/components/RolloutsVisualizer.tsx b/otel-ui/src/components/RolloutsVisualizer.tsx
index 885fe99..1abb2fe 100644
--- a/otel-ui/src/components/RolloutsVisualizer.tsx
+++ b/otel-ui/src/components/RolloutsVisualizer.tsx
@@ -30,7 +30,7 @@ export function RolloutsVisualizer() {
if (loading && rollouts.length === 0) return
Loading cluster rollouts…
return
-
Cluster Rollouts
Read-only Kubernetes deployment state with optional Prometheus impact data.
+
Cluster Rollouts
Read-only Kubernetes deployment state with optional Prometheus impact data.
void refresh()} className="ml-auto inline-flex items-center gap-2 rounded-lg border border-ds-line px-3 py-2 text-[10px] font-bold uppercase tracking-wider text-ds-text-2 hover:text-ds-text"> Refresh
{error &&
Rollout watcher unavailable: {String(error)}
}
diff --git a/otel-ui/src/components/SearchAndWatcher.tsx b/otel-ui/src/components/SearchAndWatcher.tsx
index 5bcfeaa..254d3e4 100644
--- a/otel-ui/src/components/SearchAndWatcher.tsx
+++ b/otel-ui/src/components/SearchAndWatcher.tsx
@@ -143,7 +143,7 @@ export const SearchAndWatcher: React.FC = () => {
return (
{/* Top Banner */}
-
+
@@ -162,11 +162,11 @@ export const SearchAndWatcher: React.FC = () => {
{/* SECTION 1: Live Signal Trap */}
-
+
-
+
Live Signal Trap (/api/history/wait)
@@ -230,7 +230,7 @@ export const SearchAndWatcher: React.FC = () => {
Cancel
@@ -239,7 +239,7 @@ export const SearchAndWatcher: React.FC = () => {
Arm Trap
@@ -308,11 +308,11 @@ export const SearchAndWatcher: React.FC = () => {
{/* SECTION 2: Persistent Storage Search */}
-
+
-
+
Query Persistent Telemetry Store (/api/history/search)
@@ -389,7 +389,7 @@ export const SearchAndWatcher: React.FC = () => {
{searchLoading ? "Searching..." : "Search"}
diff --git a/otel-ui/src/components/ServiceGraph.tsx b/otel-ui/src/components/ServiceGraph.tsx
index fece4ee..d042b03 100644
--- a/otel-ui/src/components/ServiceGraph.tsx
+++ b/otel-ui/src/components/ServiceGraph.tsx
@@ -220,7 +220,7 @@ export const ServiceGraph = ({
const nodeMap = new Map(nodes.map((n) => [n.id, n]));
return (
-
+
diff --git a/otel-ui/src/components/SetupPanel.tsx b/otel-ui/src/components/SetupPanel.tsx
index bbf274b..8be3a35 100644
--- a/otel-ui/src/components/SetupPanel.tsx
+++ b/otel-ui/src/components/SetupPanel.tsx
@@ -48,7 +48,7 @@ export const SetupPanel = () => {
-
+
Browser instrumentation (otel-rum.js)
@@ -87,7 +87,7 @@ export const SetupPanel = () => {
-
+
Agent instructions
diff --git a/otel-ui/src/components/StructuredLogTerminal.tsx b/otel-ui/src/components/StructuredLogTerminal.tsx
index 2050712..4edaee9 100644
--- a/otel-ui/src/components/StructuredLogTerminal.tsx
+++ b/otel-ui/src/components/StructuredLogTerminal.tsx
@@ -165,7 +165,7 @@ export const StructuredLogTerminal: React.FC<{ logs: LogEntry[] }> = ({ logs })
{/* LEFT PANEL: Faceted Filter Breakdown (3 Cols) */}
{/* Severity Breakdown Card */}
-
+
Severity Breakdown
@@ -263,7 +263,7 @@ export const StructuredLogTerminal: React.FC<{ logs: LogEntry[] }> = ({ logs })
{/* Service Facet Card */}
-
+
Service Name
@@ -303,7 +303,7 @@ export const StructuredLogTerminal: React.FC<{ logs: LogEntry[] }> = ({ logs })
{/* AI Root Cause Diagnostic Hint Box */}
-
+
@@ -328,7 +328,7 @@ export const StructuredLogTerminal: React.FC<{ logs: LogEntry[] }> = ({ logs })
{/* RIGHT PANEL: High-Density Structured Live Log Stream (9 Cols) */}
-
+
{/* Stream Controls Bar */}
diff --git a/otel-ui/src/components/Tabs.tsx b/otel-ui/src/components/Tabs.tsx
index 476ba33..25d3ade 100644
--- a/otel-ui/src/components/Tabs.tsx
+++ b/otel-ui/src/components/Tabs.tsx
@@ -250,7 +250,7 @@ export const LogEntryView = ({ log }: { log: LogEntry }) => {
{record.traceId && (
navigateToSpan(record.traceId!, record.spanId)}
- className="inline-flex items-center gap-2 rounded-xl bg-ds-accent px-4 py-2 text-[10px] font-black uppercase tracking-widest text-ds-on-accent transition-all hover:bg-ds-accent hover:scale-[1.02] active:scale-[0.98] shadow-lg "
+ className="inline-flex items-center gap-2 rounded-xl bg-ds-accent px-4 py-2 text-[10px] font-bold uppercase tracking-widest text-ds-on-accent transition-all hover:bg-ds-accent hover:scale-[1.02] active:scale-[0.98]"
>
Jump to Span in Trace
diff --git a/otel-ui/src/components/TraceVisualization.tsx b/otel-ui/src/components/TraceVisualization.tsx
index d84df33..f7a1ff1 100644
--- a/otel-ui/src/components/TraceVisualization.tsx
+++ b/otel-ui/src/components/TraceVisualization.tsx
@@ -191,7 +191,7 @@ const SpanInspector = ({
traceTotalRange > 0 ? ((span.duration / traceTotalRange) * 100).toFixed(1) : "100";
return (
-
+
{/* Header */}
@@ -278,7 +278,7 @@ const SpanInspector = ({
-
+
Duration
@@ -287,7 +287,7 @@ const SpanInspector = ({
{percentageOfTrace}% of total trace
-
+
Start Time
@@ -305,7 +305,7 @@ const SpanInspector = ({
-
+
Identifiers
@@ -584,7 +584,7 @@ const VirtualizedSpanWaterfall = ({
const rulerTicks = [0, 0.25, 0.5, 0.75, 1];
return (
-
+
{/* Waterfall Toolbar */}
@@ -656,7 +656,7 @@ const VirtualizedSpanWaterfall = ({
{/* Synchronized Time Ruler Header */}
-
+
Hierarchy & Operation
Duration
@@ -914,13 +914,13 @@ const SingleTraceView = ({
-
+
Total Spans
{trace.spans.length}
-
+
Duration
{/* Visual Service Distribution Timeline Bar */}
-
+
Service Time Distribution
@@ -1084,7 +1084,7 @@ const TracePickerDropdown = ({
setIsOpen((prev) => !prev)}
- className="flex items-center gap-2 rounded-xl bg-ds-surface-2 border border-ds-line-strong px-3 py-1.5 text-xs font-bold text-ds-text hover:border-ds-line-strong hover:bg-ds-surface transition-all shadow-sm"
+ className="flex items-center gap-2 rounded-xl bg-ds-surface-2 border border-ds-line-strong px-3 py-1.5 text-xs font-bold text-ds-text hover:border-ds-line-strong hover:bg-ds-surface transition-all"
title="Switch trace"
>
{isOpen && (
-
+
+
{/* Directory Header & Toolbar */}
@@ -1262,7 +1262,7 @@ const TraceDirectoryTable = ({
Open Waterfall Detail
@@ -1270,7 +1270,7 @@ const TraceDirectoryTable = ({
{/* Filter and Search Controls */}
-
+
@@ -1386,10 +1386,10 @@ const TraceDirectoryTable = ({
No traces match your filter or search criteria.
) : (
-
+
-
+
Status
Trace / Operation
Services
@@ -1710,7 +1710,7 @@ export const TraceVisualization = ({ traces }: TraceVisualizationProps) => {
if (orderedTraces.length === 0) {
return (
-
+
No traces match your filters
@@ -1744,7 +1744,7 @@ export const TraceVisualization = ({ traces }: TraceVisualizationProps) => {
{/* Waveform Focus Notification Banner if Active */}
{selectedTimeRange && (
-
+
diff --git a/otel-ui/src/components/TrendsVisualizer.tsx b/otel-ui/src/components/TrendsVisualizer.tsx
index 2daa60b..3ab6fc1 100644
--- a/otel-ui/src/components/TrendsVisualizer.tsx
+++ b/otel-ui/src/components/TrendsVisualizer.tsx
@@ -36,7 +36,7 @@ const ChartTooltip = ({ active, payload, granularity }: any) => {
const p = payload[0].payload
const d = new Date(String(p.bucket).replace(" ", "T") + "Z")
return (
-
+
{d.toLocaleString([], {
month: "short",
@@ -116,9 +116,9 @@ export const TrendsVisualizer = () => {
return (
{/* Toolbar */}
-
+
-
+
Historical Trends
@@ -178,7 +178,7 @@ export const TrendsVisualizer = () => {
)}
{/* Error trend */}
-
+
@@ -253,7 +253,7 @@ export const TrendsVisualizer = () => {
{/* Release comparison */}
-
+
diff --git a/otel-ui/src/components/ViewErrorBoundary.tsx b/otel-ui/src/components/ViewErrorBoundary.tsx
index 0b24d36..c2cc33c 100644
--- a/otel-ui/src/components/ViewErrorBoundary.tsx
+++ b/otel-ui/src/components/ViewErrorBoundary.tsx
@@ -35,7 +35,7 @@ export class ViewErrorBoundary extends Component {
render() {
if (this.state.error) {
return (
-
+
@@ -48,7 +48,7 @@ export class ViewErrorBoundary extends Component {
this.setState({ error: null })}
- className="inline-flex items-center gap-2 rounded-xl border border-ds-critical/30 bg-ds-critical-bg px-4 py-2 text-[10px] font-black uppercase tracking-[0.2em] text-ds-critical transition-all hover:bg-ds-critical-bg"
+ className="inline-flex items-center gap-2 rounded-xl border border-ds-critical/30 bg-ds-critical-bg px-4 py-2 text-[10px] font-bold uppercase tracking-[0.2em] text-ds-critical transition-all hover:bg-ds-critical-bg"
>
Retry
diff --git a/otel-ui/src/components/WaveformHistogram.tsx b/otel-ui/src/components/WaveformHistogram.tsx
index 3d00af9..affa245 100644
--- a/otel-ui/src/components/WaveformHistogram.tsx
+++ b/otel-ui/src/components/WaveformHistogram.tsx
@@ -168,7 +168,7 @@ export const WaveformHistogram = () => {
if (buckets.length === 0) {
return (
-
+
@@ -183,7 +183,7 @@ export const WaveformHistogram = () => {
}
return (
-
+
{
{/* Active Selection Focus Pin Indicator */}
{isSelected && (
-
+
FOCUS