# Terminal

> An animated React terminal window for dev-tool landing pages and docs: typed commands, output, spinners and progress bars.

- Type: React component (Text & Effects)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add terminal`
- Docs: https://wingo-ui.com/components/terminal

## Interaction

Scroll the window into view and it plays a session: a caret types each command after the prompt, a spinner turns into a check or a progress bar fills to 100%, then the output prints line by line and the prompt waits with a blinking caret. The whole transcript is laid out from the first frame, so the page never shifts, and screen readers and search engines get the full text. The copy button copies every command at once and the replay button starts over. Long lines scroll sideways inside the window only (Tab to it and use the arrow keys); the page never scrolls sideways, and below 640px the type steps down one size. With reduced motion on, the finished transcript shows at once.

## Installation

```bash
npx wingo-ui@latest add terminal
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/terminal` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/ui/terminal.tsx`

npm dependencies: `npm i motion lucide-react`

Wingo UI dependencies (installed automatically):

- [Button](https://wingo-ui.com/components/button) ([Markdown](https://wingo-ui.com/components/button.md))
- [Copy Button](https://wingo-ui.com/components/copy-button) ([Markdown](https://wingo-ui.com/components/copy-button.md))
- [Tooltip](https://wingo-ui.com/components/tooltip) ([Markdown](https://wingo-ui.com/components/tooltip.md))
- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
import { Terminal, type TerminalLine } from "@/components/ui/terminal"

const lines: TerminalLine[] = [
  { command: "npm install @acme/sdk", spinner: "Installing", duration: 1200, output: [{ text: "✓ Added 1 package in 1.8s", tone: "success" }] },
  { command: "npx acme login", output: ["Opening https://acme.dev/login in your browser", { text: "✓ Signed in as emma@northwind.com", tone: "success" }] },
  { command: "npx acme deploy", progress: "Uploading", duration: 1600, output: [{ text: "✓ Live at https://northwind.acme.app", tone: "success" }] },
]

export function InstallSteps() {
  return <Terminal lines={lines} title="emma@macbook: ~/northwind" mode="dark" trafficLights className="max-w-xl" />
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `lines?` | `TerminalLine[]` |  | The session, one step per entry: { command?, output?, delay?, tone?, spinner?, progress?, duration?, prompt? }. A step types its command, runs its spinner or progress bar for duration ms, then prints its output lines (strings or { text, tone }). Defaults to a short install, build and deploy session (DEFAULT_TERMINAL_LINES). |
| `title?` | `string` | `""` | The window title, like a path or a host. Centered with the mac chrome, left-aligned with plain. Also names the transcript region for screen readers. |
| `prompt?` | `string` | `"$"` | The prompt before every command, painted in the tone. A step can set its own ("#", "~/app ❯"). |
| `copyValue?` | `string` | `""` | The text the copy button copies. Defaults to every command, one per line. |
| `labels?` | `Partial<TerminalLabels>` |  | Every string: { region: "Terminal", copy: "Copy commands", copied: "Copied", replay: "Replay" }. region names the transcript when there is no title. |
| `chrome?` | `"mac" \| "plain" \| "none"` | `"mac"` | mac: three window dots and a centered title. plain: a title bar with the title on the left. none: only the transcript, with the buttons floating in the corner. |
| `trafficLights?` | `boolean` | `false` | Colors the mac dots red, yellow and green instead of a calm gray. Override them with [--terminal-dot-1:...] up to 3. |
| `mode?` | `"auto" \| "dark"` | `"auto"` | auto follows the page theme; dark keeps the window dark on a light page, the classic look for a hero. |
| `size?` | `"sm" \| "md" \| "lg"` | `"md"` | Type 12 / 13 / 14px (one step smaller below 640px), with matching padding and title bar height (36 / 40 / 48px). |
| `radius?` | `"none" \| "sm" \| "md" \| "lg" \| "full"` | `"md"` | Corner radius of the window: 0, 12, 16 or 24px; full falls back to 24px. |
| `tone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Color of the prompt, the caret and the progress bars. Output colors come from each step's tone. |
| `color?` | `string` | `""` | Any CSS color for the prompt, caret and progress bars. Replaces the tone; leave empty to use the tone. |
| `showCopy?` | `boolean` | `true` | A copy button in the title bar that copies the commands, with a check and a screen reader announcement. |
| `showReplay?` | `boolean` | `true` | A replay button that plays the session again from the start. Hidden when animate is off. |
| `cursor?` | `boolean` | `true` | The block caret that types each command, and the waiting prompt with a blinking caret at the end. |
| `speed?` | `number` | `45` | Milliseconds per typed character. |
| `trigger?` | `"mount" \| "in-view"` | `"in-view"` | mount plays as soon as the page has loaded; in-view waits until a third of the window is on screen. |
| `loop?` | `boolean` | `false` | Starts over after the last line. A looping window rests while it is off screen. |
| `loopDelay?` | `number` | `2400` | With loop, how long the finished transcript stays before it starts over, in ms. |
| `animate?` | `boolean` | `true` | Off renders the finished transcript with no typing, like a static code sample. |
| `defaultPlaying?` | `boolean` | `true` | Whether it plays on its own once triggered. Off waits on an empty prompt until playing turns true or replay is pressed. |
| `playing?` | `boolean` |  | Controlled playback: true plays (from the start once it has finished), false pauses where it is. Pair it with onPlayingChange, which reports false when the session ends. |
| `onPlayingChange?` | `(playing: boolean) => void` |  | Called when playback starts or stops, including false at the end of a session that does not loop. |
| `onComplete?` | `() => void` |  | Called each time the session finishes (every round with loop). |
| `ref?` | `Ref<HTMLDivElement> (a useRef object or an (el) => void callback)` |  | The window element. |
| `classNames?` | `Partial<Record<"header" \| "dots" \| "title" \| "actions" \| "viewport" \| "body" \| "line" \| "prompt" \| "command" \| "caret" \| "output" \| "spinner" \| "progress", string>>` |  | Extra classes for the inner parts. |
| `className?` | `string` |  | Extra classes for the window, merged last. Set a width or override the tone vars here. |

## Parts

### TerminalLine (type)

One step of the session: command, output (TerminalOutput or an array), delay (ms before it starts), tone, spinner or progress (a label), duration (ms they run, default 1400) and prompt.

### TerminalOutput (type)

An output line: a string, or { text, tone } to color one line on its own.

### TerminalTone (type)

The line colors: the six tones plus "muted", the default dimmed output.

### TerminalLabels (type)

The strings of labels: region, copy, copied and replay.

### DEFAULT_TERMINAL_LABELS (constant)

The English labels, to spread and translate.

### DEFAULT_TERMINAL_LINES (constant)

The sample install, build and deploy session shown when lines is left out.

### TerminalSize (type)

"sm" | "md" | "lg".

### TerminalRadius (type)

"none" | "sm" | "md" | "lg" | "full".

### TerminalChrome (type)

"mac" | "plain" | "none".

### TerminalTrigger (type)

"mount" | "in-view".

### TerminalMode (type)

"auto" | "dark".

### TerminalState (type)

The playback state, written to the root as data-state: "idle", "playing" or "done".

### TerminalSlot (type)

The keys of classNames.

### TerminalProps (type)

The props of Terminal, plus every div attribute.

## Examples

- **A failing test run**: A danger spinner ends in a cross; output lines take their own success, warning and danger tones.
- **Sizes**: 12, 13 and 14px type with matching padding and title bar, one step smaller on phones.
- **Window chrome**: mac dots with traffic lights, a plain title bar, or no chrome with floating buttons.
- **Controlled playback**: playing and onPlayingChange drive it from your own button; onComplete counts each run.
- **Looping hero**: A dark window with a brand prompt that replays while it stays on screen.
- **Long commands on a phone**: Lines never wrap: the window scrolls sideways inside itself and the page stays put.
- **Custom color**: Any CSS color for the prompt, caret and bars, and a per-step prompt like a root shell.

## See also

- [Code Block](https://wingo-ui.com/components/code-block) ([Markdown](https://wingo-ui.com/components/code-block.md))
- [Copy Button](https://wingo-ui.com/components/copy-button) ([Markdown](https://wingo-ui.com/components/copy-button.md))
- [Text Animate](https://wingo-ui.com/components/text-animate) ([Markdown](https://wingo-ui.com/components/text-animate.md))
- [Developers Page](https://wingo-ui.com/templates/developers-page) ([Markdown](https://wingo-ui.com/templates/developers-page.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))

---

Canonical: https://wingo-ui.com/components/terminal
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
