Terminal
Streaming command output with ANSI colors in the kit palette, a command header, exit code and duration, copy, clear, wrap and follow toggles, and an optional input line.
On this page
Installation
Usage
import { Terminal } from "@/components/ui/chatcn/terminal"
<Terminal
command="pnpm test"
cwd="~/code/checkout"
text={output} // raw output so far, escape codes included
running={!done}
exitCode={done ? code : undefined}
/>Pass the whole output each time. When the new text extends the old one, only the appended part is parsed, and finished lines never re-render. A text that does not extend the last one (a new command) starts a fresh stream and turns follow back on.
Colors map onto the kit hues through the shared chatcn-ansi parser, tuned so every tool's output reads in light and dark: red failures, green passes, amber warnings. Bold is weight and dim steps back. Carriage-return progress bars collapse to their latest frame and OSC 8 links become links.
Examples
Interactive
Pass onCommand to add an input line. Enter runs, Up and Down walk the history, Ctrl C clears the line or calls onInterrupt while a command runs, and Ctrl L clears. Clicking the output puts the caret back in the input unless you were selecting text. Echo the command into text yourself, the way a shell does.
States
Running shows the spinner and an elapsed counter after one second. A clean exit shows the duration and exit 0. A failure turns the glyph and badge red and announces itself.
Props
| Prop | Type | Notes |
|---|---|---|
text | string | Raw output so far |
command | string | Header, after a $ |
title | ReactNode | Header without a single command, for example zsh |
cwd | string | Working directory in the header |
running | boolean | Spinner, elapsed time, Latest output pill |
exitCode | number | null | Badge. Non-zero is a failure |
durationMs, startedAt | number | Measured automatically when omitted |
wrap, defaultWrap, onWrapChange | boolean | Off by default, like a terminal |
follow, defaultFollow, onFollowChange | boolean | On by default |
onClear | () => void | Without it, Clear hides the lines on screen locally |
onCommand | (command) => void | Adds the input line |
onInterrupt | () => void | Ctrl C while running |
prompt, placeholder | ReactNode, string | Input line prompt. Default $ |
height, maxHeight | number | string | Fixed height, or a cap. Default cap 360 |
maxLines | number | Older lines fold behind Show earlier lines. Default 1000 |
hideHeader | boolean | For a terminal inside another panel |
actions | ReactNode | Extra header buttons |
Follow mode is exported as useChatcnTerminalFollow for any log view.
Keyboard
| Key | Action |
|---|---|
Tab | Header toggles, then the output (scrollable with arrows), then the input |
Up, PageUp, Home in the output | Scroll back. Turns follow off |
Enter in the input | Run the command. Ignored while an IME is composing |
Up, Down in the input | Command history |
Ctrl C | Interrupt while running, or clear the input line |
Ctrl L | Clear |
Accessibility
- The output is a labelled, focusable region ("Output of pnpm test"), so keyboard users can scroll it.
- A polite live region announces the end ("Command failed with exit code 1"), never each line.
- Wrap and follow are toggle buttons with
aria-pressed. Every icon button has a label and a tooltip. - A failure is never color alone: the badge says
exit 1next to a cross.
Motion
- New lines append with no effect. Follow mode pins instantly, the way a real terminal scrolls.
- Any upward wheel, touch, key or scrollbar drag turns follow off in the same event. It never fights the reader.
- The Latest output pill fades and rises 4 px over 150 ms. The header glyph swaps with a 150 ms blur crossfade.