shadcn.io is not affiliated with official shadcn/ui
Log Stream Text plays a log as if it were live, like tail -f: a line arrives at the bottom of the box every so often, the lines above glide up a row, and the oldest fades out at the top. The box holds the same number of rows from the start, already full, so the page around it never moves. Tags such as [INFO], [WARN] and [ERROR] take the theme's colours, and each line can carry a time that counts on from the first.
Use it for a developer tool's hero, an observability or hosting landing page, or a status screen that should feel switched on. For a terminal session with typed commands, use Terminal Text; for a single line typed out, Typing Text. A small timer counts the arrivals and a CSS keyframe animation the install adds to your stylesheet glides the lines, with no animation library; with reduced motion the lines arrive without moving.
Installation
Usage
import { LogStreamText } from "@/components/ui/log-stream-text";<LogStreamText
start="09:41:00"
texts={["[INFO] Compiling routes…", "[OK] Build succeeded in 1.2s"]}
/>Demos
Rows
rows is how many lines the box shows, and so its height, from the first render; interval the time between one line and the next. Lines without a tag or a start time are shown as they are, and a line too long for the box ends in an ellipsis.
Once
loop={false} stops after the last line, for a log that tells one story, such as a deployment. Without it, the lines start over after the last, and the times keep counting on.
Accessibility
The log is a real role="log" region, named by label, with aria-live="off": screen readers can read its lines whenever they reach it, but aren't interrupted every time one arrives. It stops while the pointer is over it or it has focus, so anyone can read a line before it moves on, and its lines are real text, so they can be selected and copied. With reduced motion the lines arrive without gliding or fading.
- Tab
- Move focus to the log, which stops it until focus moves on.
FAQ
Why doesn't the box grow as lines arrive?
It holds rows lines from the start, already filled with the first lines, so its height is set before anything moves. Each line stays on one line, cut short with an ellipsis if it's too long, so a long message never pushes the others down.
Which tags are coloured?
A tag in square brackets at the start of a line: [INFO] takes the theme's info colour, [OK] and [SUCCESS] the success colour, [WARN] and [WARNING] the warning colour, [ERROR] and [FATAL] the destructive colour; [DEBUG] and any other tag are muted. Case doesn't matter.
Where do the times come from?
From start: the first line has that time, and each line after it is interval later, counting on through every loop. Worked out from the line's place in the stream rather than the clock, they're the same on the server and in the browser. Leave start out for lines without a time.
Does it pause?
Yes, while the pointer is over it and while it has focus, which a click or the Tab key gives it. It carries on from the next line once the pointer leaves or focus moves on.
Can I feed it real log lines?
Yes: with loop={false} it waits at the last line, and lines you add to texts arrive one every interval. It starts with the box full, so begin with at least rows lines.
Why aren't new lines announced?
A stream that spoke every line would talk over everything else on the page, so the log is aria-live="off": its lines are there to read whenever someone goes to them. When one event matters as it happens, such as a failed deployment, say it in a role="status" message of its own.
API Reference
LogStreamText
<div> data-slot="log-stream-text"
textsstring[]
The lines, arriving in turn. A tag at the start of a line, such as
[INFO], [WARN] or [ERROR], takes the theme's colour for it.
interval?number
The time between one line arriving and the next, in milliseconds. @default 1200.
- Default
1200
label?string
The log's name for screen readers, such as Build output.
loop?boolean
Whether the lines start over after the last; otherwise the log stops there. @default true.
- Default
true
rows?number
How many lines the box shows; it holds their height from the start. @default 6.
- Default
6
start?string
The first line's time, HH:MM:SS; each line after it is interval
later. Leave it out for lines without a time.
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
data-turn?string
Mirrors turn.
--log-stream-text-rowsstringRelated
- Pro
Terminal Text
EntranceTyped commands and their output
- Pro
Typing Text
EntranceA single line typed out
- Pro
Status Pulse Text
DecorativeA live status beside a dot
- Pro
JSON Text
EntranceA payload written key by key
- Pro
Regex Text
DecorativeMatches of a pattern marked in a log
- Pro
Dot Matrix Text
DecorativeA ticker lit on a grid of dots