Terminal
Full-featured terminal UI block with xterm.js and restty GPU renderers, ANSI log parsing, multi-session panels, and glassmorphism chrome.
Terminal Block
A production-grade terminal UI block with dual renderer support (xterm.js + restty GPU), log parsing engine, multi-session management, and premium glassmorphism panel chrome.
Blocks are high-level, ready-to-use components that compose primitives, UI components, and hooks into complete features — similar to Shadcn Blocks.
Import
import {
TerminalPanel,
TerminalLogsPanel,
TerminalInteractivePanel,
LogParserService,
useTerminalWebSocket,
useTerminalSettings,
SYNTHWAVE_TERMINAL_THEME,
} from '@mks2508/mks-ui/react/blocks/Terminal';Installation
The Terminal block requires optional peer dependencies depending on which renderer you use:
For xterm.js renderer
pnpm i @xterm/xterm @xterm/addon-fit @xterm/addon-web-links @xterm/addon-search @xterm/addon-unicode11For restty GPU renderer
pnpm i resttyFor log viewer (React mode)
pnpm i @tanstack/react-virtual shikiBrowser-Only
The Terminal block uses xterm.js and restty which require browser globals (window, self). You must load it client-side only:
// Next.js
import dynamic from 'next/dynamic';
const TerminalPanel = dynamic(
() => import('@mks2508/mks-ui/react/blocks/Terminal').then(m => m.TerminalPanel),
{ ssr: false }
);Basic Usage
Simple Terminal Panel
import { TerminalPanel } from '@mks2508/mks-ui/react/blocks/Terminal';
function App() {
return (
<TerminalPanel
mode="interactive"
wsUrl="ws://localhost:3100/api/terminal/session-1"
title="Dev Server"
onData={(data) => console.log('Input:', data)}
/>
);
}Log Viewer Panel
import {
TerminalLogsPanel,
TerminalPanelChrome,
} from '@mks2508/mks-ui/react/blocks/Terminal';
function LogViewer({ logs }) {
return (
<TerminalPanelChrome>
<TerminalLogsPanel
entries={logs}
followCursor
showLineNumbers
/>
</TerminalPanelChrome>
);
}Interactive Terminal with xterm.js
import {
TerminalInteractivePanel,
useTerminalWebSocket,
} from '@mks2508/mks-ui/react/blocks/Terminal';
function InteractiveTerminal() {
const { status, sendInput, sendResize } = useTerminalWebSocket({
url: 'ws://localhost:3100/api/terminal/session-1',
onOutput: (data) => terminalRef.current?.write(data),
});
return (
<TerminalInteractivePanel
session={{ id: '1', name: 'dev', isActive: true }}
isConnected={status === 'connected'}
/>
);
}Restty GPU Terminal
import { TerminalRestty } from '@mks2508/mks-ui/react/blocks/Terminal';
function GPUTerminal() {
return (
<TerminalRestty
wsUrl="ws://localhost:3100/api/terminal/session-1"
fontSize={14}
gpuRenderer="auto"
onReady={(restty) => console.log('GPU terminal ready')}
onResize={(cols, rows) => console.log(`${cols}x${rows}`)}
/>
);
}Custom PTY Transport
For custom WebSocket protocols, inject a transport factory:
import { TerminalRestty } from '@mks2508/mks-ui/react/blocks/Terminal';
import type { IPtyTransportFactory } from '@mks2508/mks-ui/react/blocks/Terminal';
// Your custom transport that bridges your WebSocket protocol
const createMyTransport: IPtyTransportFactory = () => ({
connect: (options) => { /* ... */ },
disconnect: () => { /* ... */ },
sendInput: (data) => { /* ... */ return true; },
resize: (cols, rows) => { /* ... */ return true; },
isConnected: () => true,
destroy: () => { /* ... */ },
});
<TerminalRestty
createPtyTransport={createMyTransport}
wsUrl="ws://localhost:3100/terminal"
/>Log Parsing Engine
The Terminal block includes a framework-agnostic log parsing engine:
import {
LogParserService,
AnsiParser,
LogLevelDetector,
PersistentLogBuffer,
} from '@mks2508/mks-ui/react/blocks/Terminal';
// Parse a log line
const parser = new LogParserService();
const entry = parser.parseLine('[2024-01-15 10:30:00] INFO: Server started on port 3000');
// { level: 'info', message: 'Server started on port 3000', timestamp: '2024-01-15 10:30:00' }
// Parse ANSI escape codes
const ansi = new AnsiParser();
const result = ansi.parse('\x1b[31mError:\x1b[0m Something failed');
// Extracts styled spans with foreground/background colors
// Detect log levels
const detector = new LogLevelDetector();
const level = detector.detect('WARN: Memory usage high');
// { level: 'warn', confidence: 0.95 }Theme System
import {
SYNTHWAVE_TERMINAL_THEME,
getTerminalTheme,
xtermThemeToGhostty,
} from '@mks2508/mks-ui/react/blocks/Terminal';
// Use default Synthwave Dark theme
const theme = SYNTHWAVE_TERMINAL_THEME;
// Customize theme
const customTheme = getTerminalTheme({
background: '#1a1a2e',
foreground: '#ffffff',
cursor: '#ff0080',
});
// Convert xterm theme to restty/Ghostty format
const ghosttyTheme = xtermThemeToGhostty(customTheme);Settings Hook
import { useTerminalSettings } from '@mks2508/mks-ui/react/blocks/Terminal';
function Settings() {
const { settings, setRenderer, setFontSize, resetToDefaults } = useTerminalSettings();
return (
<div>
<p>Renderer: {settings.renderer}</p>
<p>Font size: {settings.fontSize}px</p>
<button onClick={() => setRenderer('restty')}>Use GPU</button>
<button onClick={() => setFontSize(16)}>Size 16</button>
<button onClick={resetToDefaults}>Reset</button>
</div>
);
}Architecture
blocks/Terminal/
├── index.ts # Barrel export
├── TerminalPanel.tsx # Main orchestrating component
├── Terminal.types.ts # All types + IPtyTransportFactory
├── Terminal.theme.ts # Synthwave theme + getTerminalTheme()
├── Terminal.theme.restty.ts # xterm ↔ Ghostty theme bridge
├── Terminal.adapter.ts # Adapter factory
├── XTermAdapter.ts # xterm.js adapter
├── ResttyAdapter.ts # restty GPU adapter
├── TerminalXterm.tsx # React wrapper for xterm.js
├── TerminalRestty.tsx # React wrapper for restty
├── components/ # UI sub-components
│ ├── LogLineBadges.tsx # Level/timestamp/tag badges
│ ├── SyntaxHighlight.tsx # Syntax highlighted text
│ ├── TerminalLogBadge.tsx # Log level colored badge
│ └── SpecializedSyntaxHighlighter.tsx
├── panel/ # Panel chrome and views
│ ├── TerminalPanelChrome.tsx # Glassmorphic wrapper
│ ├── TerminalLogsPanel.tsx # Log viewer (React mode)
│ ├── TerminalInteractivePanel.tsx # Interactive terminal
│ ├── TerminalSessionTabs.tsx # Multi-session tabs
│ ├── TerminalSettingsPopover.tsx
│ └── ...
├── parsing/ # Log parsing engine
│ ├── LogParserService.ts # Main parser
│ ├── AnsiParser.ts # ANSI escape codes
│ ├── LogLevelDetector.ts # Level detection
│ ├── PersistentLogBuffer.ts # Searchable buffer
│ └── ...
└── hooks/
├── useTerminalWebSocket.ts # WebSocket lifecycle
└── useTerminalSettings.ts # localStorage settingsExported Types
| Type | Description |
|---|---|
ITerminalTheme | Terminal color theme (16 ANSI colors + background/foreground/cursor) |
ITerminalAdapter | Pluggable renderer interface |
ITerminalAdapterCapabilities | Runtime feature detection |
IPtyTransport | Custom PTY transport interface |
IPtyTransportFactory | Factory for creating custom transports |
ITerminalRendererType | 'xterm' | 'restty' |
ITerminalMode | 'interactive' | 'readonly' |
TLogLevel | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'unknown' |
IParsedLogEntry | Parsed log line with level, timestamp, content type |
Panel Components
| Component | Description |
|---|---|
TerminalPanel | Main component with toolbar, terminal, and status |
TerminalPanelChrome | Glassmorphic wrapper with noise texture |
TerminalPanelHeader | macOS-style header with traffic lights |
TerminalLogsPanel | Virtualized log viewer with filtering |
TerminalInteractivePanel | Interactive terminal (auto-selects renderer) |
TerminalSettingsPopover | Settings gear menu |
TerminalThemeSelector | Searchable theme dropdown (458 themes) |
LogLinesViewer | Virtualized log line renderer |
Hooks
| Hook | Description |
|---|---|
useTerminalWebSocket | WebSocket lifecycle with auto-reconnect |
useTerminalSettings | Global settings with localStorage persistence |