Skip to main content

TerminalOverlay

Surfacesterminal

The console-dress modal frame: a real Radix Dialog painted on the terminal ground, with a title row, arbitrary caller content, and an optional key-hint legend along the bottom — a frame, not a catalogue of panels.

import { TerminalOverlay } from "@elabs-ai/components-terminal";
Install
npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-terminal

Skipping the @source line is the most common first failure: Tailwind does not scan node_modules, so every component renders unstyled. The one-time wiring

Prompt for your coding agent

Paste it into Claude Code, Cursor, Codex or any other coding agent. Text in [brackets] is yours to fill in.

Add the brand-ui TerminalOverlay component (from @elabs-ai/components-terminal) to this project.

1. Read https://elabs-ai.com/llms.txt first: it maps every package and the rules. If you can use MCP servers, connect https://elabs-ai.com/mcp and use its search, docs and tokens tools. If not, run the same lookups in the terminal: `npx -y @elabs-ai/components-cli search "<what you need>"` and `npx -y @elabs-ai/components-cli docs <Component>`.
2. Look TerminalOverlay up before writing code: `npx -y @elabs-ai/components-cli docs TerminalOverlay` prints its real props, variants, what it pairs with and what to avoid.
3. If @elabs-ai/components-terminal is not installed yet: `pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-terminal` (or `npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-terminal`). If this is the first brand-ui package in the project, wire it once: import `@elabs-ai/components-tokens/styles.css` plus the `themes/light.css` and `themes/dark.css` stylesheets in the CSS entry, add one Tailwind `@source` line per installed @elabs-ai package (Tailwind does not scan node_modules, so without it everything renders unstyled), and wrap the app root in `ThemeProvider` from `@elabs-ai/components-tokens`.
4. Use it here: [the screen or file, and what it should show]
5. Rules: use only @elabs-ai/components-* components and the semantic tokens — no raw colours, no raw font sizes, no arbitrary Tailwind values. Look up each component's real props with the docs tool before you use it; never guess a prop.
6. Done means: the typecheck passes, `npx -y @elabs-ai/components-cli audit src --strict` reports nothing, and you have opened the app and looked at every screen you touched in the light and the dark theme.

Avoid

  • Keeping DialogContent's baked-in close icon — it is styled with `text-muted-foreground`, a token calibrated for `--card`/`--background`, never the terminal ground (the same class of bug a sibling already had to repair on this ground); it is hidden and replaced with a close control styled from the terminal token group.
  • Adding a `border` alongside the dialog's `shadow-ring-*` — an overlay floats; the elevation rule bans a border beside a ring shadow (the 'double edge').
  • Rendering the footer's key glyphs as the only carrier of an action's meaning — each hint's action reaches assistive tech as real words; the glyph is decorative.
  • Building the settings-modal catalogue itself here — this component is the ground, the dismissal and the legend only; the content is the caller's (a stated #117 non-goal).

Works with

Examples

4 live examples

With Description

A caller-supplied description, linked to the panel via `aria-describedby`.

No Hints

No `hints` at all — the footer legend does not render, never an empty bar.

With Keyboard Shortcuts

The canonical filler: `KeyboardShortcuts` (`@elabs-ai/components-ui`) hosted inside the frame. `KeyboardShortcuts` is calibrated against `--card`/`--background`, not the always-dark terminal ground, so it is wrapped in its own ordinary card surface — "a chip punched out of the console", inverted: an ordinary card punched INTO the console frame.

API

TerminalOverlay

PropTypeDescription
openrequiredbooleanControlled open state — the app owns it.
onOpenChangerequired(open: boolean) => voidFires on the close control, Escape, an outside click, and any other Radix dismissal.
titlerequiredReactNodeThe panel's heading, read by assistive tech as the dialog's accessible name.
descriptionReactNodeOne line of supporting context under the title. Omitted, the panel carries no description.
hintsTerminalOverlayHint[]The footer key-hint legend, in order. Omitted or empty, no footer renders at all — never an empty bar.
childrenReactNodeThe panel's own content. The caller's — see the module doc.

Also accepts: Omit<HTMLAttributes<HTMLDivElement>, "title">

Theming

The tokens each state resolves to. Change the token and every theme follows.

StateToken
chromebg-terminal-background text-terminal-foreground
legendborder-terminal-border text-terminal-muted