Add this component

npx zentauri-ui add terminal-emulator

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Check Installation for shared peers. This component keeps styling in Tailwind classes and the --zui-* token contract.

Data display

Terminal Emulator for displaying console sessions

Use the terminal emulator to render a console session as a styled, read-only window. Pass an array of typed lines — command, output, error, or comment — and each renders with the right color: commands are prefixed with a configurable prompt, output is muted, errors are red, and comments are green and italic. An optional window header adds traffic-light dots, a centered title, and a copy-to-clipboard control.

zsh — my-app
# scaffold and install
$ pnpm create zentauri-app my-app
Creating my-app in ./my-app
$ cd my-app && pnpm install
Packages: +312
Done in 4.1s
$ pnpm build
✓ Compiled successfully

Terminal emulator playground

Pick a session, chrome appearance, and size to preview the terminal emulator live. Toggle the window header to expose the traffic-light dots, title, and copy control, switch on a motion preset, and use Show output / Show code to copy the matching snippet.


Install
# install dependencies
$ pnpm install
Packages: +312
Progress: resolved 312, reused 312
Done in 4.1s

All appearances

Every shipped chrome appearance over the same session. Click any card to load it into the playground above.

default
# install dependencies
$ pnpm install
Packages: +312
Progress: resolved 312, reused 312
Done in 4.1s
subtle
# install dependencies
$ pnpm install
Packages: +312
Progress: resolved 312, reused 312
Done in 4.1s
contrast
# install dependencies
$ pnpm install
Packages: +312
Progress: resolved 312, reused 312
Done in 4.1s
glass
# install dependencies
$ pnpm install
Packages: +312
Progress: resolved 312, reused 312
Done in 4.1s

Terminal Emulator API

Generated from the package prop types and variant definitions.

TerminalEmulator

TerminalEmulatorProps

Variants

PropTypeDefault
appearance
contrastdefaultglasssubtle
default
size
lgmdsm
md

Behavior

PropTypeDefault
enableClipboardShow a copy button that copies all line text.boolean | undefinednone
labelsOverride default header copy.TerminalEmulatorLabels | undefinednone
lines*The lines that make up the terminal session.TerminalLine[]none
promptPrompt symbol shown before each `command` line.string | undefinednone
showHeaderShow the window header bar with traffic-light dots and title.boolean | undefinednone
showTrafficLightsShow the decorative traffic-light dots in the header.boolean | undefinednone
titleWindow title shown centered in the header bar.string | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone

TerminalEmulatorVariant

TerminalEmulatorVariantProps

Behavior

PropTypeDefault
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone

TerminalEmulatorAnimated

TerminalEmulatorAnimatedProps

animated

Behavior

PropTypeDefault
animationReveal motion preset for the terminal body.TerminalEmulatorAnimation | undefinednone
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
enableClipboardShow a copy button that copies all line text.boolean | undefinednone
labelsOverride default header copy.TerminalEmulatorLabels | undefinednone
lines*The lines that make up the terminal session.TerminalLine[]none
promptPrompt symbol shown before each `command` line.string | undefinednone
refAllows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).Ref<HTMLDivElement> | undefinednone
showHeaderShow the window header bar with traffic-light dots and title.boolean | undefinednone
showTrafficLightsShow the decorative traffic-light dots in the header.boolean | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone
titleWindow title shown centered in the header bar.string | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
CSS variable overrides

Terminal Emulator CSS variables

Override these terminal emulator variables on :root, a theme selector, or a component wrapper.

36 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-terminal-emulator-border: #0000001a;
  --zui-terminal-emulator-bg: oklch(98.4% 0.003 247.858);
  --zui-terminal-emulator-fg: oklch(20.8% 0.042 265.755);
  --zui-terminal-emulator-subtle-bg: oklch(92.9% 0.013 255.508);
  --zui-terminal-emulator-contrast-bg: #ffffff;
  --zui-terminal-emulator-glass-bg: #ffffffcc;
  --zui-terminal-emulator-glass-border: #ffffff66;
  --zui-terminal-emulator-header-bg: oklch(96.8% 0.007 247.896);
  --zui-terminal-emulator-header-fg: oklch(44.6% 0.043 257.281);
  --zui-terminal-emulator-title-fg: oklch(44.6% 0.043 257.281);
  --zui-terminal-emulator-dot: #cbd5e1;
  --zui-terminal-emulator-action-fg: oklch(44.6% 0.043 257.281);
  --zui-terminal-emulator-action-hover-bg: #0000000d;
  --zui-terminal-emulator-prompt-fg: #16a34a;
  --zui-terminal-emulator-command-fg: #0f172a;
  --zui-terminal-emulator-output-fg: #475569;
  --zui-terminal-emulator-error-fg: #dc2626;
  --zui-terminal-emulator-comment-fg: #16a34a;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-terminal-emulator-border-dark: #ffffff1a;
  --zui-terminal-emulator-bg-dark: oklch(12.9% 0.042 264.695);
}

Composition and API

Pass the session through the lines prop as an array of { type, text } entries, where type is command, output, error, or comment. The prompt prop sets the symbol shown before each command line (defaults to $). showHeader toggles the window header bar; within it, showTrafficLights toggles the decorative dots, title sets the centered window label, and enableClipboard toggles the copy button, which copies every line joined by newlines (commands prefixed with the prompt). appearance switches between default, subtle, contrast, and glass chrome, and size controls the monospace text scale. The separate animated entry adds stagger and fade reveal presets for the body.

Accessibility

The copy control is a real button, and the traffic-light dots are decorative (aria-hidden) so they are skipped by assistive technology. The root and every line carry data-slot attributes for styling and testing, and each line exposes a data-type attribute reflecting its kind. Line colors ship light and dark pairs that meet contrast on their surfaces; the animated entry's motion is short and easing-based, so pair it with prefers-reduced-motion handling in your app where needed.

Next.js integration notes

The static TerminalEmulator entry ships no framer-motion and is safe in any Server or Client Component tree (it is a Client Component because the copy button manages local state). The animated TerminalEmulatorAnimated entry imports framer-motion, which is an optional peer dependency — install it only if you use the animated entry. Both render deterministically from the same lines, so server and client output match and there is no hydration mismatch.

FAQ

How do I distinguish commands from their output?

Set the type field on each line. command lines are prefixed with the prompt symbol and use the command color, output lines are muted, error lines are red, and comment lines are green and italic. The component never executes anything — it is a presentational view of a session you supply.

Can I change the prompt symbol?

Yes. Use the prompt prop, which defaults to "$". It is rendered before every command line and is also used when building the copy text, so a copied command reads exactly as it appears.

Do I need framer-motion?

Only for the animated entry. The default import from @zentauri-ui/zentauri-components/ui/terminal-emulator is framer-motion-free. Import TerminalEmulatorAnimated from the /animated subpath when you want the stagger or fade reveal, and install framer-motion as a peer dependency.

How do I theme the line colors?

Override the --zui-terminal-emulator-* CSS variables (bg, fg, border, header, prompt, command, output, error, comment, and more) on :root, a theme selector, or a wrapper. Each variable ships a light fallback and a paired -dark variant for dark mode.