Trace timeline
<scope-trace> displays span timing, hierarchy, viewport controls and pinned details. The lightweight createTrace factory accepts the same document.
Loading interactive chart…
Parallel spans with exact nanosecond timestamps.
Hover to read · Click to select
<scope-trace id="chart">
<nav slot="toolbar" class="chart-controls" aria-label="Chart controls"></nav>
</scope-trace>
<script type="module">
import '@scopedb/scopeview/register';
import chartDocument from './chart.js';
const chart = document.querySelector('#chart');
const toolbar = chart.querySelector('[slot="toolbar"]');
const labels = {
"zoom-in": "+",
"zoom-out": "−"
};
function renderToolbar() {
const controls = chart.controls;
for (const button of toolbar.querySelectorAll('[data-action]')) {
if (!controls.some((control) => control.action === button.dataset.action)) button.remove();
}
for (const control of controls) {
let button = toolbar.querySelector('[data-action="' + control.action + '"]');
if (!button) {
button = document.createElement('button');
button.type = 'button';
button.dataset.action = control.action;
button.addEventListener('click', () => chart.performAction(control.action));
toolbar.append(button);
}
button.textContent = labels[control.action] || control.label;
button.setAttribute('aria-label', control.label);
button.disabled = control.disabled;
if (control.expanded !== undefined) button.setAttribute('aria-expanded', String(control.expanded));
else button.removeAttribute('aria-expanded');
}
}
chart.addEventListener('scope-controls-change', renderToolbar);
chart.configure({
dismissOnOutside: false
});
chart.document = chartDocument;
renderToolbar();
</script>
<style>
#chart {
color-scheme: light;
--scope-chart-height: 260px;
--color-text-primary: #202b38;
--color-text-secondary: #657286;
--color-text-tertiary: #7b8798;
--color-surface: #ffffff;
--color-border: #dce3eb;
--color-border-light: #edf0f4;
}
.chart-controls[slot="toolbar"] {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 4px;
margin-top: 12px;
padding: 8px 0;
border-top: 1px solid var(--color-border-light);
font-size: var(--scope-chart-tooltip-font-size, 12px);
line-height: 1.4;
}
.chart-controls[slot="toolbar"] button {
border: 0;
border-radius: var(--radius-chart-control, 4px);
padding: 5px 8px;
font: inherit;
color: var(--color-text-secondary);
background: transparent;
cursor: pointer;
}
.chart-controls[slot="toolbar"] button:hover:not(:disabled),
.chart-controls[slot="toolbar"] button[aria-expanded="true"] {
color: var(--color-text-primary);
background: var(--color-surface-hover);
}
.chart-controls[slot="toolbar"] button:disabled {
opacity: 0.45;
cursor: default;
}
.chart-controls[slot="toolbar"] button:focus-visible {
outline: 2px solid var(--color-text-brand, #0876dd);
outline-offset: 1px;
}
</style>Copy the example
Follow Run an example for project setup and the development server. Save this example's index.html, chart.js and data.json together. Replace the span array in data.json; keep the trace document's configuration in chart.js. The mount file includes a custom toolbar. Remove its slot="toolbar" content to use the built-in controls.
Each span needs id, name, startTimeNs and endTimeNs. Nanoseconds are integer strings. Use parentId for parentage, service for color identity and status: 'error' for failures. Set coverage to describe the supplied snapshot. See trace documents for exact timing, warnings and limits.
Read and navigate
Hover for the compact duration reading; click or press Enter to pin complete details below the controls. Another span stays hoverable. Arrow keys inspect and Home/End jump; Escape dismisses. Drag pans, Ctrl/Command-wheel zooms, and the toolbar offers zoom/reset actions. The component scrolls rows when the hierarchy exceeds its height.
To reveal an initial span, register a one-time ready listener before assigning the document:
import type { ScopeTraceElement } from '@scopedb/scopeview/element';
export function revealSpan(chart: ScopeTraceElement, id: string) {
chart.addEventListener('scope-ready', () => chart.focusNode(id, { pin: true }), { once: true });
}Inspection events contain original spans in detail.sources. Uncovered time reflects supplied direct children, so partial traces cannot establish complete exclusive time. See component API for viewport/collapse methods and view state for preserving a reading across updates.