Skip to content
CodeTerminalMenu

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.

A scripted pnpm test run fails on one assertion, then the rerun passes.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/terminal.json

Usage

tsx
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.

An input line with history, Ctrl C and Ctrl L, driving a small scripted shell.

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.

Waiting for output, a clean exit and a failed build.

Props

PropTypeNotes
textstringRaw output so far
commandstringHeader, after a $
titleReactNodeHeader without a single command, for example zsh
cwdstringWorking directory in the header
runningbooleanSpinner, elapsed time, Latest output pill
exitCodenumber | nullBadge. Non-zero is a failure
durationMs, startedAtnumberMeasured automatically when omitted
wrap, defaultWrap, onWrapChangebooleanOff by default, like a terminal
follow, defaultFollow, onFollowChangebooleanOn by default
onClear() => voidWithout it, Clear hides the lines on screen locally
onCommand(command) => voidAdds the input line
onInterrupt() => voidCtrl C while running
prompt, placeholderReactNode, stringInput line prompt. Default $
height, maxHeightnumber | stringFixed height, or a cap. Default cap 360
maxLinesnumberOlder lines fold behind Show earlier lines. Default 1000
hideHeaderbooleanFor a terminal inside another panel
actionsReactNodeExtra header buttons

Follow mode is exported as useChatcnTerminalFollow for any log view.

Keyboard

KeyAction
TabHeader toggles, then the output (scrollable with arrows), then the input
Up, PageUp, Home in the outputScroll back. Turns follow off
Enter in the inputRun the command. Ignored while an IME is composing
Up, Down in the inputCommand history
Ctrl CInterrupt while running, or clear the input line
Ctrl LClear

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 1 next 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.