Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Terminal Text for React

A terminal session that plays itself: commands typed after a prompt, their output printed a line at a time. For React with Base UI, when an install step or a CLI should be shown running.

Framework

Terminal Text plays a short terminal session: a prompt, a command typed a character at a time, its output printed a line at a time, then the next command, ending on a prompt with a blinking caret. You write the session as you'd paste it into a README: lines that start with $ are commands, anything else is output, and lines that start with a tick, a cross, a warning sign or a tag such as [info] take the theme's colours.

Use it for an install step on a landing page, a CLI's hero, or a quick-start that shows what running a command looks like. For a single typed line inside your own mock-up, use Typing Text; for a stream of log lines that never ends, Log Stream Text. There's no timer: every character and line is in place from the start, hidden, and a CSS keyframe animation the install adds to your stylesheet shows each at its moment, so the box never changes size and nothing re-renders. With reduced motion the whole session is there at once.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { TerminalText } from "@/components/ui/terminal-text";
<TerminalText
  text={`$ npx shadcn@latest add terminal-text
✓ Created components/ui/terminal-text.tsx`}
/>

Demos

Session

Several commands in a row, each with its output. prompt is what shows before each command, a path or a host as your shell prints it; the commands in text still start with $ . Output that starts with warning or error takes the theme's warning or destructive colour.

Preview width

Timing

delay is the wait at each prompt before its command is typed, and again before its output, speed the average time per character, and stagger the time between one line of output and the next. cursor is the caret's shape: block, the default, bar, underscore or none.

Preview width

Accessibility

Screen readers read the whole session once, line by line, from a visually hidden copy, never the half-typed commands; the animated session is hidden from them. The prompts can't be selected, so a command copied from the box pastes without its $. The session stays left to right on a right-to-left page, as a terminal does. The caret blinks once a second, only while it waits, and with reduced motion the session is all there, with a still caret on the last prompt.

FAQ

How do I write the session?

As one string, a line per line, the way a README shows a terminal: a line that starts with $ (or is just $) is a command, typed after the prompt; every other line is output, printed whole. Blank lines at the start and the end are dropped, so a template literal can start on its own line.

Which output lines are coloured?

Lines that start with ✓ or [ok] take the theme's success colour, ✗, [error] or error the destructive colour, ⚠, [warn] or warning the warning colour, and ℹ or [info] the info colour; the rest are muted. Each output line has data-tone, so you can style them from outside.

When does it play?

Once, when at least a quarter of it is in view. Pass trigger="mount" to play it as soon as the page shows it, from CSS alone, before the page's script loads.

Does the box grow as the session plays?

No. Every character and line is laid out from the start, hidden, so the box has its final size before anything appears and the page below it never moves. Long lines wrap inside the box.

Can it play again?

Give it a new key and React renders it fresh, so it plays again from the start.

What does it show without JavaScript?

The whole session, still, as it ends.

What happens with reduced motion?

The whole session is there from the start, with a still caret on the last prompt.

API Reference

TerminalText

<div> data-slot="terminal-text"

PropType
textstring

The session, a line per line: a line that starts with $ is a command, typed after the prompt; any other line is output, printed whole.

cursor?"block" | "bar" | "underscore" | "none"

The caret: a terminal's block, a bar, an underscore, or none. @default "block".

Type
"block" | "bar" | "underscore" | "none"
Default
"block"
delay?number

The wait at each prompt before its command is typed, and after a command before its output prints, in milliseconds.

Default
500
prompt?string

What's shown before each command. @default "$".

Default
"$"
speed?number

The time to type one character of a command, on average, in milliseconds. @default 50.

Default
50
stagger?number

The time between one line of output and the next, in milliseconds. @default 100.

Default
100
trigger?"mount" | "view"

When it plays: as soon as it's on the page, or once it scrolls into view.

Type
"mount" | "view"
Default
"view"
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.

AttributeType
data-tone?string

Mirrors tone.

data-view?string

"in" when visible is true, otherwise "out".

All 97 text effects