j3w1 / TerminalVue · HTML · React · Astro

J3W1 / DESIGN SYSTEM

Terminal

Terminal text on the terminal surface with the sixteen heritage ANSI slots carried exactly, the cursor, the selection and the six text attributes; a transcript, the slot grid and the attributes.

stable · LIGHT DOM · 1.1.0

Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.

Live variants

default

 ~/theme  main  ls -l ports
total 5
drwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 alacritty
drwx------  2 j3w1 j3w1  4096 Sep  6 09:12 gtk
-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 README.md
-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 verify.sh
lrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 xresources -> ../tokens/
-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 evidence.tar.gz
 ~/theme  main  cat ports/gtk/port.json
cat: ports/gtk/port.json: No such file or directory
 ~/theme  main  npm run validate

<j3w1-terminal id="example-terminal-default"><pre class="terminal terminal-transcript" role="log" aria-label="Shell transcript" tabindex="0"><span class="terminal-line"><span class="terminal-prompt"><span class="terminal-prompt-path"> ~/theme </span><span class="terminal-prompt-arrow terminal-prompt-arrow-path" aria-hidden="true">▶</span><span class="terminal-prompt-branch"> main </span><span class="terminal-prompt-arrow terminal-prompt-arrow-branch" aria-hidden="true">▶</span></span> ls -l ports</span>
<span class="terminal-line">total 5</span>
<span class="terminal-line">drwxr-xr-x  2 j3w1 j3w1  4096 Sep  6 09:12 <span class="terminal-fg-5 terminal-bold">alacritty</span></span>
<span class="terminal-line">drwx------  2 j3w1 j3w1  4096 Sep  6 09:12 <span class="terminal-fg-5 terminal-bold">gtk</span></span>
<span class="terminal-line">-rw-r--r--  1 j3w1 j3w1  1180 Sep  6 09:12 <span class="terminal-sel">README.md</span></span>
<span class="terminal-line"><span class="terminal-sel">-rwxr-xr-x  1 j3w1 j3w1   512 Sep  6 09:12 </span><span class="terminal-sel terminal-fg-3">verify.sh</span></span>
<span class="terminal-line">lrwxrwxrwx  1 j3w1 j3w1    11 Sep  6 09:12 <span class="terminal-fg-7">xresources</span> -&gt; <span class="terminal-fg-2">../tokens/</span></span>
<span class="terminal-line">-rw-r--r--  1 j3w1 j3w1 20480 Sep  6 09:12 <span class="terminal-fg-11">evidence.tar.gz</span></span>
<span class="terminal-line"><span class="terminal-prompt"><span class="terminal-prompt-path"> ~/theme </span><span class="terminal-prompt-arrow terminal-prompt-arrow-path" aria-hidden="true">▶</span><span class="terminal-prompt-branch"> main </span><span class="terminal-prompt-arrow terminal-prompt-arrow-branch" aria-hidden="true">▶</span></span> cat ports/gtk/port.json</span>
<span class="terminal-line terminal-fg-5">cat: ports/gtk/port.json: No such file or directory</span>
<span class="terminal-line terminal-line-cursor"><span class="terminal-prompt"><span class="terminal-prompt-path"> ~/theme </span><span class="terminal-prompt-arrow terminal-prompt-arrow-path" aria-hidden="true">▶</span><span class="terminal-prompt-branch"> main </span><span class="terminal-prompt-arrow terminal-prompt-arrow-branch" aria-hidden="true">▶</span></span> npm run validate<span class="terminal-cursor" aria-hidden="true"> </span></span></pre></j3w1-terminal>

ansi-grid

slot    normal  bold    background
 0           
 1           
 2      normal  bold    
 3      normal  bold    
 4           
 5      normal  bold    
 6           
 7      normal  bold    
 8           
 9           
10           
11      normal  bold    
12           
13           
14           
15           
✕ fails 4.5:1 on the terminal background; the extended profile reassigns the slots

<j3w1-terminal id="example-terminal-ansi-grid"><pre class="terminal terminal-ansi-grid" aria-label="The sixteen ANSI slots as normal and bold foregrounds and as backgrounds; a cross marks a slot that fails 4.5 to 1 on the terminal background" tabindex="0"><span class="terminal-line"><span class="terminal-label">slot    normal  bold    background</span></span>
<span class="terminal-line"><span class="terminal-label"> 0</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-0 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-0 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-0 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 1</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-1 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-1 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-1 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 2</span>      <span class="terminal-fg-2">normal</span>  <span class="terminal-fg-2 terminal-bold">bold</span>    <span class="terminal-bg-2 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 3</span>      <span class="terminal-fg-3">normal</span>  <span class="terminal-fg-3 terminal-bold">bold</span>    <span class="terminal-bg-3 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 4</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-4 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-4 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-4 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 5</span>      <span class="terminal-fg-5">normal</span>  <span class="terminal-fg-5 terminal-bold">bold</span>    <span class="terminal-bg-5 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 6</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-6 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-6 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-6 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 7</span>      <span class="terminal-fg-7">normal</span>  <span class="terminal-fg-7 terminal-bold">bold</span>    <span class="terminal-bg-7 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 8</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-8 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-8 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-8 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label"> 9</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-9 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-9 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-9 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label">10</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-10 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-10 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-10 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label">11</span>      <span class="terminal-fg-11">normal</span>  <span class="terminal-fg-11 terminal-bold">bold</span>    <span class="terminal-bg-11 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label">12</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-12 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-12 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-12 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label">13</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-13 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-13 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-13 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label">14</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-14 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-14 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-14 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line"><span class="terminal-label">15</span> <span class="terminal-fail">✕</span>    <span class="terminal-fg-15 terminal-swatch" aria-hidden="true"></span>  <span class="terminal-fg-15 terminal-swatch" aria-hidden="true"></span>    <span class="terminal-bg-15 terminal-swatch-bg" aria-hidden="true"></span></span>
<span class="terminal-line terminal-line-cursor"><span class="terminal-label">✕ fails 4.5:1 on the terminal background; </span><span class="terminal-sel">the extended profile reassigns the slots</span><span class="terminal-cursor" aria-hidden="true"> </span></span></pre></j3w1-terminal>

attributes

bold       Warm-black surfaces, rose text.
dim        Warm-black surfaces, rose text.
italic     Warm-black surfaces, rose text.
underline  Warm-black surfaces, rose text.
inverse    Warm-black surfaces, rose text.
strike     Warm-black surfaces, rose text.
selected   Warm-black surfaces, rose text.

<j3w1-terminal id="example-terminal-attributes"><pre class="terminal terminal-attributes" aria-label="Terminal text attributes" tabindex="0"><span class="terminal-line"><span class="terminal-label">bold       </span><span class="terminal-bold">Warm-black surfaces, rose text.</span></span>
<span class="terminal-line"><span class="terminal-label">dim        </span><span class="terminal-dim">Warm-black surfaces, rose text.</span></span>
<span class="terminal-line"><span class="terminal-label">italic     </span><span class="terminal-italic">Warm-black surfaces, rose text.</span></span>
<span class="terminal-line"><span class="terminal-label">underline  </span><span class="terminal-underline">Warm-black surfaces, rose text.</span></span>
<span class="terminal-line"><span class="terminal-label">inverse    </span><span class="terminal-inverse">Warm-black surfaces, rose text.</span></span>
<span class="terminal-line"><span class="terminal-label">strike     </span><span class="terminal-strike">Warm-black surfaces, rose text.</span></span>
<span class="terminal-line terminal-line-cursor"><span class="terminal-label">selected   </span><span class="terminal-sel">Warm-black surfaces, rose text.</span><span class="terminal-cursor" aria-hidden="true"> </span></span></pre></j3w1-terminal>

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

npm install --save-exact @j3w1/ui@1.1.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/terminal.css';
import '@j3w1/ui/register/terminal';

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@1.1.0 j3w1-ui copy terminal --out ./vendor/j3w1/terminal

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

Public API

attributes

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.
setText(text: string): voidReplace the bounded read-only text view; no code or shell execution occurs.

events

NameType / signatureMeaning
j3w1-actionCustomEventRequest a developer-view action; editing and execution belong to the host.

Dependencies and verification

Registered components: none. Style dependencies: none.

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

Full implementation manifest, API and token dependency closure

Canonical specification

Purpose

The reference for terminal text: the surface, the default foreground, the cursor, the selection, the six attributes and the sixteen slots the workstation froze in Xresources. The slots are the origin of the theme and are carried exactly; what a program does with a slot is that program’s choice, and the theme documents where a choice fails rather than quietly fixing it.

Anatomy

Root .terminal (the <pre>) with a variant class .terminal-transcript, .terminal-ansi-grid or .terminal-attributes. Parts .terminal-<part>: -line, -prompt with -prompt-path, -prompt-branch and -prompt-arrow, -cursor, -sel, -label, -fail (the ), and the attributes -bold, -dim, -italic, -underline, -inverse, -strike. Slot classes are .terminal-fg-0.terminal-fg-15 and .terminal-bg-0.terminal-bg-15, each a single role variable color.terminal.ansi.0color.terminal.ansi.15, so the profile switch on the specimen recolours the grid without touching the markup. The foreground is color.terminal.fg on color.terminal.bg; the prompt path segment is color.terminal.selection-text on color.terminal.ansi.4 and the branch segment color.terminal.bg on color.terminal.ansi.3, the two agnoster backgrounds the workstation used.

States

StateVisualNon-colour channel
defaulttext on color.terminal.bg; the cursor cell hollow, a 1px color.terminal.cursor outline; no ringthe hollow cursor
focus-visiblecontainer ring 2px color.interaction.focus.ring-container at −3px; the cursor solid color.terminal.cursor with color.terminal.bg textthe ring; the cursor fills
selectedthe run filled color.terminal.selection-bg with color.terminal.selection-text; slot colours inside the run give way to the selection textthe fill spans whole cells; the emulator exposes the selection
busya command is running: the cursor is a solid static block at the end of the output; the transcript is aria-busyaria-busy; the cursor shape; no blink
currentthe cursor line filled color.code.current-line across its width; the cursor as in focusthe row fill; the cursor cell

The cursor never blinks in the reference. A host keeps the user’s own blink setting and stops blinking under reduced motion; the theme never turns it on.

Keyboard

The emulator and the shell own every key, including Tab, Escape and the selection modifiers. The reference transcript is a single focus stop that consumes nothing. The theme draws the ring when the host reports focus, the fill when the host reports a selection, and the block cursor where the host puts it.

Accessibility

The transcript is role=log so new output is announced politely; the grid and the attribute sheet are plain <pre> elements with a label. The sixteen slots are exact in every profile: slots 2, 3, 5, 7 and 11 reach 4.5:1 on the terminal background; slots 1, 4, 6, 8, 9, 10, 12, 13 and 14 do not (1.86:1–4.43:1), and the grid marks each of them with a after its number so the failure is visible, not implied. Two more are marked on the same evidence: slot 15 measures 4.45:1 and slot 0 is the background itself. The extended overlay reassigns the slots to a semantic sixteen that all reach 4.5:1; the site’s profile control shows the grid under it. The background row is legible only with a foreground the program chooses: with the default foreground only slots 0 and 8 pass, which is why the row is shown and not declared as a contract. Two escape families bypass the slots entirely and are outside the theme: bold-as-bright, which substitutes slots 8–15 for 0–7 and must be off for the slots to hold, and 256-colour or 24-bit sequences, which carry their own values. Attributes are attributes: dim uses color.text.muted (5.81:1) rather than a slot, inverse swaps foreground and background (8.65:1), and bold, italic, underline and strikethrough are text styles a screen reader can expose.

Portability

Every emulator with a sixteen-slot palette can hold these values byte for byte; the port’s evidence records whether bold-as-bright is off and whether the cursor and selection keys exist. Programs that pick slot 4 or 12 for directories inherit the documented failure; a port may recommend LS_COLORS or a prompt configuration but never changes the slots to compensate. The cursor shape (block, bar, underline) is the user’s setting; the theme only supplies its colour.

Non-examples

Normalising the heritage slots so every one reaches 4.5:1 and calling it heritage-ansi. A blinking cursor in the reference. A cursor that is a glowing bar. Bold rendered as bright, which silently swaps the slots. A purple or cyan slot borrowed from another scheme. Wrapping the transcript at narrow widths and breaking the prompt segments. A selection drawn as a ring instead of a fill. Rounded prompt segments or a gradient prompt.

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • DEMO Vue application demo
  • SPEC Complete UI theme specification