Feedback

TerminalFrame

Frame a consumer-owned real PTY with terminal chrome, connection status, reload handling, and character-cell resize reporting.

import { TerminalFrame } from '@lostgradient/cinder';
terminalptyshell
01

Overview

Reference usage

TerminalFrame supplies chrome, connection state, recovery UI, and character-cell resize reporting around a consumer-owned real PTY renderer. It does not implement a terminal emulator or own a transport. Resize callbacks receive { cols, rows }.

Use TerminalOutput for read-only ANSI streams. Use TerminalFrame when the child content is an interactive terminal implementation whose backend needs { cols, rows } resize updates.

For a hosted terminal that is already wired to a pseudo-terminal, use @lostgradient/terminal, the private browser terminal workspace in the corvidae repository. Its Terminal component composes TerminalFrame, mounts the terminal engine inside it, and owns the fitting, input, paste review and recovery that this component leaves to the consumer.

Usage

svelte
<script lang="ts">
  import { TerminalFrame, type TerminalFrameDimensions } from '@lostgradient/cinder';

  let dimensions = $state<TerminalFrameDimensions>({ cols: 80, rows: 24 });
</script>

<TerminalFrame
  title="Build shell"
  status="connected"
  onDimensionsChange={(nextDimensions) => (dimensions = nextDimensions)}
>
  <textarea
    aria-label="Interactive shell"
    rows={dimensions.rows}
    cols={dimensions.cols}
    value="$ bun run dev"></textarea>
</TerminalFrame>
Live preview

Basic terminal frame

Build shell

connected
$ bun run build
Build complete.

02

When to use

Use when
  • Hosting a real interactive terminal implementation that needs consistent chrome and resize dimensions.
Avoid when
  • Rendering a read-only stream — use TerminalOutput.
03

Examples

Basic terminal frame

Frame a connected terminal surface with status chrome.

04

Props

Props for terminal-frame
Name
Type
Default
Description
title required text Title shown in the frame chrome.
status 'connecting' | 'connected' | 'disconnected' | 'error' 'connecting' Connection status shown in the frame chrome. Defaults to 'connecting'.
announceStatus boolean true Whether the status chip is a polite live region (role="status"), so a change of status is announced. Set false when the consumer announces state itself through a more detailed live region and a second announcement would be noise; the chip keeps its visible text. Defaults to true.
error text Recovery error message. The recovery UI is gated on error being a non-empty string ({#if error}), not on status—error="" shows nothing, the same as undefined, even though the prop is set. If error stays non-empty after status moves away from 'error' (for example to 'connected'), the recovery UI remains visible until the caller clears error too.
onReloadRequest () => void Called when the user requests a reload from the recovery UI. The recovery UI (and this button) show whenever error is a non-empty string, regardless of the current status—see that prop.
onDimensionsChange (dimensions: TerminalFrameDimensions) => void Called with { cols, rows } whenever the character-cell size changes, so the host can resize its PTY. A new measurement is never taken—and this never fires from one—while columnWidth or rowHeight is non-finite or <= 0. That's not an absolute guarantee this never fires while invalid, though: the component replays the last valid measurement whenever the onDimensionsChange reference itself changes (e.g. a parent passing a new inline handler each render), and that replay doesn't re-check columnWidth/rowHeight—so a stale measurement can still reach a newly-passed handler even after the cell size becomes invalid.
columnWidth number 8 Character-cell width, in pixels, used to compute { cols, rows } on resize. Must be positive and finite for a new measurement to run (see onDimensionsChange for the one exception). Defaults to 8.
rowHeight number 18 Character-cell height, in pixels, used to compute { cols, rows } on resize. Must be positive and finite for a new measurement to run (see onDimensionsChange for the one exception). Defaults to 18.
children required snippet Consumer-owned PTY renderer.