# Log viewer

A React component in [Beamline](https://beamline.io/)'s [Data & tables](https://beamline.io/components/data) category. Live demo: https://beamline.io/components/log-viewer

Log lines as they stream: it follows the newest line until you scroll up, then counts what arrived and brings you back in one click; filter by level with counts, search with every match marked and stepped through, wrap long lines, open a line's fields; only the lines in view are drawn, so a hundred thousand stay smooth.

## Use it for

- Output people read and search while it arrives: deploys, builds, jobs, a service's logs, an agent's tool output.
- Large logs (thousands to hundreds of thousands of lines) that must stay smooth.

## Not for

- A history of who did what ([timeline](https://beamline.io/components/timeline)).
- A short command's output shown once ([code-block](https://beamline.io/components/code-block)).
- Structured records people sort and filter by column ([data-grid](https://beamline.io/components/data-grid)).

## Anatomy

- toolbar: search with match count and previous / next, level chips with counts, Only matches, Wrap and Follow toggles, your actions
- body: virtualised rows of line number, time, level (word and colour), source, message with marked matches
- a line's fields opened under it
- “N new lines” pill while you read above the tail
- live mark while streaming

## Variants

- **0**: levels shown (chips; all by default)
- **1**: wrap: one line each, or wrapped
- **2**: only matches: search filters instead of marking
- **3**: columns: line numbers and time on or off
- **4**: height: px or fill

## States

- loading (skeleton lines)
- empty (says so, in your words)
- streaming and following
- reading above the tail (follow off, new lines counted)
- searching (matches marked, current match outlined)
- no matches
- line opened (fields)

## Keyboard

- / focuses search; Enter and Shift+Enter step to the next and previous match; Escape clears it
- In the log: ↑ ↓ move the current line, Page Up / Page Down by a screen, Home / End to the first and the newest (End follows again)
- Enter opens or closes the current line's fields
- Tab reaches line copy buttons; Enter copies the focused line without opening its fields or moving the active line.

## Motion

New lines never animate (a feed that moves is unreadable); the view keeps pace with them only while following. The new-lines pill rises in once and its count rolls; a jump to a match glides the scroll (instant under reduced motion); an opened line's fields ease open. Nothing runs at rest.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `lines` (required) | `LogLine[]` | — | { id?, time?, level?, source?, message, fields? } in arrival order; append to stream. |
| `follow / defaultFollow / onFollowChange` | `boolean` | — | Keep the newest line in view. Default true; scrolling up turns it off. |
| `wrap / defaultWrap / onWrapChange` | `boolean` | — | Wrap long lines. Default false. |
| `query / defaultQuery / onQueryChange` | `string` | — | The search. |
| `levels / defaultLevels / onLevelsChange` | `LogLevel[]` | — | Levels shown; every level by default. |
| `live` | `boolean` | — | Marks the log as streaming. |
| `height` | `number \| "fill"` | — | Default 360. |
| `lineNumbers / time` | `boolean` | — | Columns. Default true. |
| `formatTime` | `(time: Date) => string` | — | Default HH:MM:SS.mmm. |
| `actions` | `ReactNode` | — | Your controls at the toolbar's end (download, clear). |
| `loading` | `boolean` | — | Skeleton lines. |
| `emptyLabel` | `string` | — | Default "No log lines yet". |
| `aria-label` (required) | `string` | — | The log's name: "Deploy #4821". |
| `className / classNames / style / ref` | `string / LogViewerClassNames / CSSProperties / Ref<HTMLDivElement>` | — | The root and its parts (toolbar, body, row, level, message, fields, pill). |

## Dependencies

`@tanstack/react-virtual`, `lucide-react`

## Import

```tsx
import { LogViewer } from "@/components/log-viewer/log-viewer";
```

## Get it

Log viewer is part of Beamline: 200+ components and 50+ complete screens for React that your coding agent (Claude Code, Codex, Cursor or any MCP client) installs into your app through Beamline's MCP server, as a ready-built package or as plain React source you can change. $49 launch price, one payment, no subscription, lifetime updates, one licence for your whole team. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in Data & tables

- [Event calendar](https://beamline.io/components/event-calendar): A schedule of events by day, week or month: events that overlap sit side by side, drag one to another time or day or pull its bottom edge to change its…
- [Kanban board](https://beamline.io/components/kanban-board): Work as cards in columns by stage: drag a card (or lift it with Space and walk it with the arrows) to another column or place, the cards around it make…
- [Data grid](https://beamline.io/components/data-grid): Virtualised grid for thousands of rows: multi-sort, search and value filters, resizable and pinnable columns, range selection, inline edit, footer…
- [Pivot table](https://beamline.io/components/pivot-table): Records summed up by the fields people choose: rows grouped by one or more fields that fold open level by level, columns split by another, one or more…
- [Query builder](https://beamline.io/components/query-builder): Conditions people build by hand to pick out records: each rule is a field, an operator that fits the field (contains, between, in the last N days, is any…
- [JSON viewer](https://beamline.io/components/json-viewer): A JSON value as a tree you can read and walk: branches open and close (one level, or all at once), closed ones preview what they hold, every value reads…
- [JSON diff viewer](https://beamline.io/components/json-diff-viewer): Two versions of a JSON value compared as one tree: added keys marked +, removed ones struck through with −, changed values read old → new, unchanged keys…
- [Import mapping](https://beamline.io/components/import-mapping): Map the columns of a file to the fields of one record type, see what every value becomes, then run the import and get an outcome for each row…
- [Diff table](https://beamline.io/components/diff-table): Proposed edits to a table before they happen: new rows green, removals struck through, changed cells old → new; each change can be left out and Apply…
- [Filter toolbar](https://beamline.io/components/filter-toolbar): The filters on a list kept in view: chips that remove themselves, Add filter with fields and their values, Clear all, and room for search or view controls.
- [Table](https://beamline.io/components/table): A plain, styled HTML table for small static data: header, body, footer, caption, numeric cells, three densities and a sticky header.
