Add this component

npx zentauri-ui add request-timeline-viewer

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Check Installation for shared peers. This component keeps styling in Tailwind classes and the --zui-* token contract.

Data display

Request Timeline Viewer for visualizing request timing

Use the request timeline viewer to render a browser-style network waterfall. Each request phase becomes a labeled, color-coded bar whose width is proportional to its duration, with the elapsed time shown alongside, an optional legend mapping each phase color, and a total-duration summary.

Blocked4ms
DNS11ms
Connect28ms
TLS42ms
Send3ms
Wait186ms
Receive47ms
BlockedDNSConnectTLSSendWaitReceive
Total321ms

Request timeline playground

Pick a timing breakdown, chrome appearance, and size to preview the request timeline viewer live. Toggle the legend, switch on an enter motion preset, and use Show output / Show code to copy the matching snippet.


Blocked14ms
DNS22ms
Connect38ms
TLS61ms
Send4ms
Wait842ms
Receive96ms
BlockedDNSConnectTLSSendWaitReceive
Total1077ms

All appearances

Every shipped chrome appearance over the same timeline. Click any card to load it into the playground above.

default
Blocked2ms
DNS1ms
Connect6ms
TLS9ms
Send1ms
Wait18ms
Receive7ms
Total44ms
subtle
Blocked2ms
DNS1ms
Connect6ms
TLS9ms
Send1ms
Wait18ms
Receive7ms
Total44ms
contrast
Blocked2ms
DNS1ms
Connect6ms
TLS9ms
Send1ms
Wait18ms
Receive7ms
Total44ms
glass
Blocked2ms
DNS1ms
Connect6ms
TLS9ms
Send1ms
Wait18ms
Receive7ms
Total44ms

Request Timeline Viewer API

Generated from the package prop types and variant definitions.

RequestTimelineViewer

RequestTimelineViewerProps

Variants

PropTypeDefault
appearance
contrastdefaultglasssubtle
default
size
lgmdsm
md

Behavior

PropTypeDefault
labelsOverride default copy.RequestTimelineViewerLabels | undefinednone
phases*The ordered request phases to render as a waterfall.TimelinePhase[]none
showLegendShow the legend mapping each tone to its label and color.boolean | undefinednone
showTotalShow the total-duration summary row.boolean | undefinednone
totalDenominator for bar widths; defaults to the sum of phase durations.number | undefinednone
unitUnit suffix appended to each duration.string | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

RequestTimelineViewerVariant

RequestTimelineViewerVariantProps

Behavior

PropTypeDefault
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone

RequestTimelineViewerAnimated

RequestTimelineViewerAnimatedProps

animated

Behavior

PropTypeDefault
animationEnter-motion preset for the bars and rows.RequestTimelineViewerAnimation | undefinednone
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
labelsOverride default copy.RequestTimelineViewerLabels | undefinednone
phases*The ordered request phases to render as a waterfall.TimelinePhase[]none
refAllows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).Ref<HTMLDivElement> | undefinednone
showLegendShow the legend mapping each tone to its label and color.boolean | undefinednone
showTotalShow the total-duration summary row.boolean | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone
totalDenominator for bar widths; defaults to the sum of phase durations.number | undefinednone
unitUnit suffix appended to each duration.string | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone
CSS variable overrides

Request Timeline Viewer CSS variables

Override these request timeline viewer variables on :root, a theme selector, or a component wrapper.

38 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-request-timeline-viewer-border: #0000001a;
  --zui-request-timeline-viewer-bg: oklch(98.4% 0.003 247.858);
  --zui-request-timeline-viewer-fg: oklch(20.8% 0.042 265.755);
  --zui-request-timeline-viewer-subtle-bg: oklch(92.9% 0.013 255.508);
  --zui-request-timeline-viewer-contrast-bg: #ffffff;
  --zui-request-timeline-viewer-glass-bg: #ffffffcc;
  --zui-request-timeline-viewer-glass-border: #ffffff66;
  --zui-request-timeline-viewer-label-fg: oklch(44.6% 0.043 257.281);
  --zui-request-timeline-viewer-track-bg: #0000000d;
  --zui-request-timeline-viewer-duration-fg: oklch(44.6% 0.043 257.281);
  --zui-request-timeline-viewer-legend-fg: oklch(44.6% 0.043 257.281);
  --zui-request-timeline-viewer-total-fg: oklch(20.8% 0.042 265.755);
  --zui-request-timeline-viewer-blocked: #94a3b8;
  --zui-request-timeline-viewer-dns: #0ea5e9;
  --zui-request-timeline-viewer-connect: #f59e0b;
  --zui-request-timeline-viewer-tls: #8b5cf6;
  --zui-request-timeline-viewer-send: #ec4899;
  --zui-request-timeline-viewer-wait: #22c55e;
  --zui-request-timeline-viewer-receive: #2563eb;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-request-timeline-viewer-border-dark: #ffffff1a;
  --zui-request-timeline-viewer-bg-dark: oklch(12.9% 0.042 264.695);
}

Composition and API

Pass an ordered phases array, where each entry has a label, a numeric duration, and an optional tone (blocked, dns, connect, tls, send, wait, or receive). Bar widths are proportional to total — the sum of every duration by default, or a value you supply to compare against a fixed budget. unit sets the duration suffix (ms by default). When a phase omits its tone the viewer cycles through the tone list by index. showLegend toggles the tone legend and showTotal toggles the summary row. The separate animated entry adds grow (bars expand from zero with a small stagger) and fade (rows fade in) enter presets.

Accessibility

The root and every row, label, bar, legend, and total carry data-slot attributes for styling and testing, and each bar exposes a data-tone attribute identifying its phase. Color is paired with a text label and duration so the timing is never conveyed by color alone, and the legend swatches are decorative (aria-hidden). The animated entry's motion is short and easing-based; pair it with prefers-reduced-motion handling in your app where needed.

Next.js integration notes

The static RequestTimelineViewer entry ships no framer-motion and is safe in any Server or Client Component tree. The animated RequestTimelineViewerAnimated entry imports framer-motion, which is an optional peer dependency — install it only if you use the animated entry. Both render deterministically from the same phases, so server and client output match and there is no hydration mismatch.

FAQ

How are the bar widths calculated?

Each bar's width is its duration divided by the total, expressed as a percentage. By default total is the sum of all phase durations, so the bars fill the track. Pass a fixed total to size every timeline against the same budget for side-by-side comparison.

What if I don't set a tone on a phase?

The viewer cycles through the built-in tone list (blocked, dns, connect, tls, send, wait, receive) by index, so phases stay visually distinct even without explicit tones. Set tone explicitly to map a phase to a specific color.

Do I need framer-motion?

Only for the animated entry. The default import from @zentauri-ui/zentauri-components/ui/request-timeline-viewer is framer-motion-free. Import RequestTimelineViewerAnimated from the /animated subpath when you want grow or fade transitions, and install framer-motion as a peer dependency.

How do I theme the phase colors?

Override the --zui-request-timeline-viewer-* CSS variables (blocked, dns, connect, tls, send, wait, receive, plus bg, border, label, duration, and track tokens) on :root, a theme selector, or a wrapper. Each variable ships a light fallback and a paired -dark variant for dark mode.