# react-o11y URL: /docs/utilities/react-o11y Headless primitives for visualizing observability spans (traces, waterfalls). `@assistant-ui/react-o11y` is currently v0.0.11 and experimental. The API may change without notice. `@assistant-ui/react-o11y` provides headless, Radix-style primitives for rendering observability spans as collapsible, indented hierarchical UIs. Use it to build trace inspectors, waterfall debug panels, or LLM call timelines on top of your own span data source. * **Headless** — Zero styling opinions, bring your own CSS / Tailwind. * **Composable** — Radix-style primitive parts you fully control. * **Tree-aware** — Automatic depth, parent / child collapse, time range computation. * **Tap-powered** — Built on the same `@assistant-ui/tap` reactive primitives as the runtimes. ## Installation \[#installation] ## Quick start \[#quick-start] Mount `SpanResource` with your span data, then render primitives that read from the resource's state: ```tsx title="components/trace-view.tsx" "use client"; import { SpanPrimitive, SpanResource, type SpanData, } from "@assistant-ui/react-o11y"; import { useAui, AuiProvider } from "@assistant-ui/store"; function SpanRow() { return ( ); } export function TraceView({ spans }: { spans: SpanData[] }) { const aui = useAui({ resource: SpanResource({ spans }) }); return ( ); } ``` `SpanData` is the input shape your code produces (see [SpanData](#spandata)). `SpanResource` enriches it with depth, child counts, time range, and collapse state. ## Anatomy \[#anatomy] ```tsx import { SpanPrimitive, SpanResource, SpanByIndexProvider, } from "@assistant-ui/react-o11y"; // Top-level: mount SpanResource via useAui const aui = useAui({ resource: SpanResource({ spans }) }); {/* Render visible spans (flat-list output respecting collapsed state) */} ; // Each sits inside its own SpanByIndexProvider context and reads via primitives function SpanRow() { return ( ); } ``` `SpanPrimitive.Children` produces a flat list of visible spans (collapsed subtrees are excluded). Each rendered child is wrapped in a `SpanByIndexProvider` so its primitives resolve to that specific span's state. ## API reference \[#api-reference] ### SpanResource \[#spanresource] Tap resource that ingests raw span data and exposes a tree-aware reactive state to primitives. ```ts SpanResource({ spans }: { spans: SpanData[] }): ClientOutput<"span">; ``` Mount through `useAui({ resource: SpanResource({ spans }) })`. The resource computes: * **depth** of each span based on parent chain. * **hasChildren** flag. * **timeRange** (`min` / `max` across all spans). * **collapse state** managed internally; toggles through primitives. ### SpanData \[#spandata] Input shape you provide to `SpanResource`: | Field | Type | Description | | -------------- | --------------------------------------------------- | ---------------------------------------------------------------- | | `id` | `string` | Unique span identifier. | | `parentSpanId` | `string \| null` | Parent span id, or `null` for root spans. | | `name` | `string` | Display name. | | `type` | `string` | Span category (e.g. `llm`, `tool`, `http`). Used by `TypeBadge`. | | `status` | `"running" \| "completed" \| "failed" \| "skipped"` | Lifecycle state. Used by `StatusIndicator`. | | `startedAt` | `number` | Start timestamp (ms). | | `endedAt` | `number \| null` | End timestamp (ms), or `null` if still running. | | `latencyMs` | `number \| null` | Pre-computed latency, or `null` if running. | ### SpanState \[#spanstate] Returned by `useAuiState((s) => s.span)` inside any span-scoped subtree: ```ts type SpanState = { id: string; parentSpanId: string | null; name: string; type: string; status: "running" | "completed" | "failed" | "skipped"; startedAt: number; endedAt: number | null; latencyMs: number | null; depth: number; hasChildren: boolean; isCollapsed: boolean; children: SpanItemState[]; timeRange: { min: number; max: number }; }; ``` ### SpanPrimitive.Root \[#spanprimitiveroot] Container `
` exposing span state via data attributes for styling: | Attribute | Source | | ------------------ | ------------------ | | `data-span-id` | `span.id` | | `data-span-status` | `span.status` | | `data-span-type` | `span.type` | | `data-span-depth` | `span.depth` | | `data-collapsed` | `span.isCollapsed` | Accepts all standard `
` props. ### SpanPrimitive.Indent \[#spanprimitiveindent] A `
` that adds horizontal padding proportional to span depth. | Prop | Type | Default | Description | | ---------------- | -------- | ------- | ----------------------------------- | | `baseIndent` | `number` | `8` | Base padding in pixels. | | `indentPerLevel` | `number` | `12` | Additional padding per depth level. | Final `paddingLeft = baseIndent + depth * indentPerLevel`. ### SpanPrimitive.CollapseToggle \[#spanprimitivecollapsetoggle] A `