Content Panes
The workspace content area is populated by content panes, each responsible for rendering a specific type of view. WorkspaceView orchestrates which pane is visible based on the active session’skind field or whether it’s a terminal/agent session.
TerminalPane
File:src/components/TerminalPane.tsx
TerminalPane renders an interactive terminal using xterm.js and manages the PTY session lifecycle. It’s the most complex pane due to WebGL context pooling, resize handling, and keyboard interception.
Props
xterm.js Extensions
TerminalPane loads several xterm.js addons:Theme
Terminal colors are pulled from CSS custom properties (—tempest-terminal-*) and injected as an xterm.js theme object:PTY Attachment
On mount, TerminalPane:- Creates the xterm.js Terminal instance
- Calls
sessionManager.attach(sessionId, onData)to subscribe to PTY output - Replays any buffered data (from before the pane mounted)
- Registers an
onDatahandler to write incoming bytes to the terminal
Keyboard Handling
Custom key event handler intercepts specific keys:Resize Handling
On every resize event, the terminal is re-fitted and the PTY is notified of the new dimensions:setTimeout(..., 16) prevents excessive PTY resize calls during animated resizes.
WebGL Context Pooling
xterm.js can render with WebGL for performance, but WebGL contexts are limited (6 per OS). TerminalPane manages this viawebglPool:
Search
Ctrl+F opens an in-terminal search bar powered by xterm.js’s SearchAddon:User Input Tracking
When the user types (PTYonData fires), TerminalPane signals the SessionManager:
Title Change Monitoring
For agent sessions, TerminalPane monitors OSC 0/2 title changes (agents send status glyphs):DiffPane
File:src/components/DiffPane.tsx
DiffPane provides a full Git UI: staging/unstaging files, viewing diffs, committing, pushing, and branch management. It calls Rust backend commands for all git operations.
Props
Data Model
Layout
Two-column layout: files on left, diff on right. Left column:- Staged files section (with “Unstage All” button)
- Unstaged files section (with “Stage All” button)
- Commit form (title + description + co-author toggle + commit button)
- Selected file’s unified diff with line numbers
- Header showing file path and section (staged/unstaged)
- Loading state during diff fetch
Loading File List
On mount and whenevergitRevision changes, load the repo status:
.tempest-pid file (used internally) is filtered out.
Staging Operations
Per-File Diff Rendering
Committing
Branch Operations
Branch menu: Click the pill showing current branch to open a dropdown menu:- List all branches
- Switch branch (disabled for current)
- Delete branch button (shows trash icon for non-current)
Two-Way Sync
When a file is selected and staged/unstaged (via button), the pane automatically re-loads and follows the file to its new section. This keeps the UI in sync with the git state.CodeMirrorPane
File:src/components/CodeMirrorPane.tsx
CodeMirrorPane provides a read/edit interface for files with syntax highlighting. It doubles as a Markdown previewer.
Props
Supported Languages
@codemirror/lang-* packages.
Editor Setup
Theme
Both editor colors and syntax highlighting use CSS custom properties (—tempest-*):Saving
Ctrl+S writes the file:Markdown Preview
For.md and .markdown files, a toggle appears to switch between “Raw” (editor) and “Preview” modes:
<style> tag:
.markdown-body CSS rules don’t conflict between light and dark instances.
Image Resolution
Relative image paths in Markdown are resolved relative to the file’s directory:PreviewPane
File:src/components/PreviewPane.tsx
PreviewPane embeds a native webview (via Tauri) to display a live dev server preview. It handles URL navigation, history, viewport presets (mobile/tablet/desktop), and bounds synchronization.
Props
Initialization
First time (no URL set), show the UrlPicker:http://localhost:) and triggers navigation.
Webview Embedding
Once a URL is set, invoke Tauri to embed a native webview:preview-content). Bounds are computed from the div’s getBoundingClientRect().
Bounds Synchronization
On resize/scroll, update webview bounds:Navigation History
Similar to a browser, maintain a history stack:Viewport Presets
Three presets and free-form dimensions:viewW and viewH. Clicking a dimension value opens an inline editor. Setting to null or “auto” returns to full-width/full-height.
The frame div is positioned with constrained dimensions:
URL Polling
Every 500ms, poll the webview to detect SPA navigation (pushState):Reload vs. Navigation
- Reload: Same URL, increment
reloadKeyto force re-embed - Navigate: Different URL, call
pushEntry()to add to history and re-embed - Same-URL reload from URL bar: Detected by
sameUrl(), triggers reload
TopBar
File:src/components/TopBar.tsx
TopBar is the minimal window chrome at the very top of the app. It includes the Tempest mark, window controls (minimize/maximize/close), and a disabled zen-mode button.
Components
getCurrentWindow() to call native window methods.
The data-tauri-drag-region attribute on the drag div tells Tauri that clicks on it are meant to drag the window (not interact with content).
Zen mode (future feature) would switch the app to focus on a single project with a flat worktree view and hidden sidebars. The button is disabled for now.