Skip to content

Terminal

A command-line style panel that types its lines in once: a prompt, the commands, then the output. It has a copy button, and a still mode that shows every line at once. The lines are real text in the page from the start.

Motionv0.1.0experimentalWCAG 2.2 AAView spec

Optional, and kept apart.

Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.

npx rdloom init
Created rdloom.json
npx rdloom add button
Added button to src/components/ui
import { Terminal } from "@rdloom/react";

export default function TerminalBasicExample() {
  return (
    <div className="flex w-full justify-center">
      <Terminal
        className="w-full max-w-2xl"
        lines={[
          { text: "npx rdloom init" },
          { text: "Created rdloom.json", kind: "output" },
          { text: "npx rdloom add button" },
          { text: "Added button to src/components/ui", kind: "output" },
        ]}
      />
    </div>
  );
}

Installation

npx rdloom add terminal

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.

It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/terminal.json

Works, but without upgrade tracking, and you import the motion CSS yourself.

Usage

import { Terminal } from "@rdloom/react";

<div className="flex w-full justify-center">
  <Terminal
    className="w-full max-w-2xl"
    lines={[
      { text: "npx rdloom init" },
      { text: "Created rdloom.json", kind: "output" },
      { text: "npx rdloom add button" },
      { text: "Added button to src/components/ui", kind: "output" },
    ]}
  />
</div>

Install

npm install @rdloom/react
npx rdloom add dialog
import { Terminal } from "@rdloom/react";

export default function TerminalInstallExample() {
  return (
    <div className="flex w-full justify-center">
      <Terminal
        className="w-full max-w-2xl"
        label="Install steps"
        prompt=">"
        speed={25}
        copyLabel="Copy commands"
        lines={[{ text: "npm install @rdloom/react" }, { text: "npx rdloom add dialog" }]}
      />
    </div>
  );
}

Still

npm run build
Built 42 pages in 6.1s
No problems found
import { Terminal } from "@rdloom/react";

export default function TerminalStillExample() {
  return (
    <div className="flex w-full justify-center">
      <Terminal
        isPaused
        className="w-full max-w-2xl"
        label="Build output"
        lines={[
          { text: "npm run build" },
          { text: "Built 42 pages in 6.1s", kind: "output" },
          { text: "No problems found", kind: "output" },
        ]}
      />
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
linesrequired

The lines, each { text, kind }. kind is "command" (typed, with a prompt) or "output" (appears whole after a short pause). Default kind is command.

{ text: string; kind?: "command" | "output" }[]none
label

Accessible name of the panel.

string"Terminal"
prompt

Text shown before each command.

string"$"
speed

Milliseconds per typed character.

number35
lineDelay

Milliseconds to wait between lines.

number450
showCopy

Shows a Copy button that copies the commands (without prompts or output).

booleantrue
copyLabel

Text of the button.

string"Copy"
copiedLabel

Text of the button after copying.

string"Copied"
isPaused

Still mode: shows every line at once and does not type.

booleanfalse

Accessibility

Role group, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

  • Tab: moves to the Copy button and to the scrollable text area
  • Enter or Space: copies the commands

Screen readers announce

  • Group named by label, then the lines as plain text, then the Copy button

What your code must do

  • The panel is a group named by label
  • Every line is real text in the server HTML and is readable with no JavaScript
  • While a line is being typed, the full text of the line is available to screen readers at once and the typed copy is hidden; nothing is read letter by letter
  • Typing runs once and stops; it never loops, so there is no moving content to stop after the lines are in
  • Reduced motion, isPaused and anything inside rdm-still show every line at once
  • The Copy button confirms with a polite status message
  • The text area scrolls and takes keyboard focus, so long lines are reachable without a mouse

Guidelines

Use it when

  • Showing an install or setup command
  • A short scripted demo of a command-line tool

Avoid it when

  • A real interactive shell
  • Long logs (use a log viewer)

Don't

  • Putting secrets in the lines
  • Typing very long scripts that delay the reader

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-surface-subtle
  • --rd-color-border-default
  • --rd-color-text-default
  • --rd-color-text-muted
  • --rd-color-focus-ring
  • --rd-radius-control