LiveLog
StableA streaming, monospaced log of what an agent is doing, with pause and follow.
Also known as log viewer, console, terminal output, logs
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Lines arriving, with pause
Test run
- 10:42:00$ npm test
function Example() {
const [lines, setLines] = useState<LiveLogLine[]>([]);
const [paused, setPaused] = useState(false);
const [run, setRun] = useState(0);
useEffect(() => {
let i = 0;
const t = window.setInterval(() => {
if (i >= script.length) { window.clearInterval(t); return; }
const s = script[i];
const sec = String(i).padStart(2, "0");
setLines((prev) => [...prev, { ...s, id: `${run}-${i}`, time: `10:42:${sec}` }]);
i += 1;
}, 900);
return () => window.clearInterval(t);
}, [run]);
return (
<div className="flex w-full max-w-lg flex-col gap-3">
<LiveLog label="Test run" lines={lines} paused={paused} onPauseChange={setPaused} maxHeight={48} />
<Button variant="secondary" size="sm" className="self-start" onClick={() => { setLines([]); setPaused(false); setRun((r) => r + 1); }}>
Run again
</Button>
</div>
);
}A new line arrives every 0.9 seconds. Press Pause to hold them; new ones wait behind the "N new lines" button. Scroll up to stop following.
When to use it
Lets people watch a running agent's raw output, stop it from moving to read it, and catch up when they are ready.
Made of: Header with name · Paused note · Pause or Resume button · Scrolling log · Line: time, level mark, text · Jump to latest or N new lines button
Use it for
- Command and test output while a coding agent runs.
- A browser or data agent's step-by-step log.
- Any stream of short lines that people may want to stop and read.
Not for
- A lasting record of what the agent changed, with undo: use ActionLog.
- A readable summary of the agent's steps: use ActivityTrace.
- A finished block of code or output to copy: use CodeBlock.
Do and avoid
Agent output
- 10:42:01Opened orders.csv
- 10:42:02Read 120 rows
- 10:42:03WarningRow 87 has no date, skipped
- 10:42:04Wrote summary.csv
10:42:01 Opened orders.csv
10:42:02 Read 120 rows
10:42:03 Row 87 has no date, skipped
10:42:04 Wrote summary.csv
Do
- Keep the log for raw, fast output. Summarise the same work elsewhere for people who will not read it.
- Give warnings and errors a level so they are marked with a word.
- Turn on wrap where lines are long and the screen is narrow.
Avoid
- Do not use it as the only record of what an agent changed.
- Do not edit or remove earlier lines; only append.
- Do not colour whole lines to show status.
On a phone
- It fills the width of its container in one column. Long lines scroll sideways inside the log unless wrap is on, so the page never scrolls sideways.
- The Pause button and the N new lines button keep their size and have a 44px tap area on a touch screen.
- Dragging the log up stops following, and the Jump to latest button appears near the bottom.
- Turn on wrap on narrow screens when lines are long and reading matters more than lining up.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| linesrequired | { id: string; text: string; time?: string; level?: "info" | "warn" | "error" }[] | none | Every line so far, oldest first. Append new lines to the end. |
| follow | boolean | true | Keep the newest line in view. Scrolling up turns it off and scrolling back to the bottom turns it on. Works without onFollowChange. |
| onFollowChange | (follow: boolean) => void | none | Called when following stops or starts, from scrolling or the Jump to latest button. |
| paused | boolean | false | Hold new lines back. They are counted on an "N new lines" button that resumes. Works without onPauseChange. |
| onPauseChange | (paused: boolean) => void | none | Called when the Pause, Resume or N new lines button is pressed. |
| maxHeight | number | string | 64 | Tallest the log grows before it scrolls. A number is spacing steps (64 is 16rem); a string is any CSS length, such as a token in var(). |
| labelrequired | string | none | Shown as the heading and used as the log's name and in the Pause button's name. |
| wrap | boolean | false | Wrap long lines. When off, long lines keep their spacing and the log scrolls sideways. |
| className | string | none | Classes for the outer box. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one LiveLog switches all of this from its properties panel, across 2 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Paused | paused | On or off |
| Label | label | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- empty
- With no lines the log says "Nothing yet."
- following
- The log stays scrolled to the newest line and is polite to screen readers. This is the default.
- scrolled up
- Scrolling away from the bottom stops following, silences announcements and shows a Jump to latest button with a count of lines that arrived since.
- paused with held lines
- New lines are held back, a Paused note shows in the header, and an "N new lines" button resumes and jumps to the newest line.
- burst
- When several lines arrive within 2 seconds, the log stops reading each one and a hidden status reads one count summary instead.
- focus
- The scrolling area shows the focus ring and scrolls with the arrow keys, Page Up, Page Down, Home and End.
Tokens
Change one of these and every part that uses it follows.
--font-mono--text-small--fg--fg-muted--fg-subtle--danger-fg--sunken--raised--line--line-strong--hover--spacing--stagger--blur-arrive--dur-base--ease-arrive--radius-control--radius-card
Built in
- The scrolling area has role="log", is named by the visible heading, and can be focused with Tab. Arrow keys, Page Up, Page Down, Home and End then scroll it.
- While following and not paused, the log is polite, so a single new line is read out. When several lines arrive within 2 seconds of the last one read, the log goes quiet and a hidden status line reads one summary, such as "4 new lines. Latest: Error: Expected status 200", at most every 2 seconds.
- Nothing is read out while paused or while the person has scrolled up.
- Warning and error lines show an icon and the word Warning or Error. Errors also use the danger text colour. Info lines have no mark.
- The Pause button's name includes the log's name, such as "Pause Test run", and changes to Resume. A visible Paused note appears while paused.
- New lines fade in from a slight blur, the first four of a burst a little apart. Under reduced motion they just appear.
- Numbers use tabular figures in a monospaced font, so columns of times line up.
What you need to do
- Give it a label that says what is being logged, such as "Test run".
- Only append lines. The component holds paused lines by count, so changing earlier lines while paused shows the wrong ones.
- Keep each line short and give warnings and errors a level, so they get their icon and word.
- Format time before passing it in.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide