Release v1.01 Enhanced: Vi Control, TUI Gen5, Core Stability

This commit is contained in:
Gemini AI
2025-12-20 01:12:45 +04:00
Unverified
parent 2407c42eb9
commit 142aaeee1e
254 changed files with 44888 additions and 31025 deletions

View File

@@ -1,90 +1,231 @@
/**
* TUI Theme Module - Centralized styling for OpenQode TUI
* Provides consistent colors, spacing, and border styles
* With capability detection for cross-platform compatibility
* TUI Theme Module - Premium Design System
* Provides consistent semantic colors, spacing, and rail styling
* With profile-gated backgrounds for cross-platform compatibility
*
* DESIGN PRINCIPLES:
* 1. Single accent color (no neon chaos)
* 2. Semantic roles (fg, muted, accent, border, success/warn/error)
* 3. Profile-gated backgrounds (SAFE_ASCII avoids most backgrounds)
* 4. One-frame rule (only outer container has border)
*/
// Capability detection
const hasUnicode = process.platform !== 'win32' ||
process.env.WT_SESSION || // Windows Terminal
process.env.TERM_PROGRAM === 'vscode'; // VS Code integrated terminal
import { getCapabilities, PROFILE, isBackgroundOK, isDimOK, isUnicodeOK } from './terminal-profile.mjs';
// Theme configuration
export const theme = {
// Spacing scale (terminal rows/chars)
spacing: {
xs: 0,
sm: 1,
md: 2,
lg: 3
},
// ═══════════════════════════════════════════════════════════════
// SEMANTIC COLOR TOKENS
// ═══════════════════════════════════════════════════════════════
export const colors = {
// Primary text
fg: 'white',
fgBold: 'whiteBright',
// Semantic colors
colors: {
fg: 'white',
muted: 'gray',
border: 'gray',
info: 'cyan',
success: 'green',
warning: 'yellow',
error: 'red',
accent: 'magenta',
// Muted/secondary text
muted: 'gray',
mutedDim: 'gray', // isDimOK() ? dimmed gray : regular gray
// Single accent (not multi-color chaos)
accent: 'cyan',
accentBold: 'cyanBright',
// Borders and dividers
border: 'gray',
borderFocus: 'cyan',
divider: 'gray',
// Semantic status colors
success: 'green',
warning: 'yellow',
error: 'red',
info: 'blue',
// Role-specific rail colors (left rail indicator)
rail: {
user: 'cyan',
assistant: 'white',
system: 'yellow'
assistant: 'green',
system: 'yellow',
tool: 'magenta',
error: 'red',
thinking: 'gray'
},
// Border styles with fallback
borders: {
default: hasUnicode ? 'round' : 'single',
single: 'single',
round: hasUnicode ? 'round' : 'single',
double: hasUnicode ? 'double' : 'single'
// Focus/selection
focus: 'cyan',
selection: 'blue'
};
// ═══════════════════════════════════════════════════════════════
// SPACING SCALE (terminal rows/chars)
// ═══════════════════════════════════════════════════════════════
export const spacing = {
none: 0,
xs: 0,
sm: 1,
md: 2,
lg: 3,
xl: 4
};
// ═══════════════════════════════════════════════════════════════
// TYPOGRAPHY HIERARCHY
// ═══════════════════════════════════════════════════════════════
export const typography = {
// Section headers (e.g., "PROJECT", "SESSION")
header: { bold: true, color: colors.fg },
// Labels (e.g., "Branch:", "Model:")
label: { color: colors.muted },
// Values (e.g., "main", "qwen-coder-plus")
value: { color: colors.fg },
// Muted metadata
meta: { color: colors.muted, dimColor: true },
// Status text
status: { color: colors.accent },
// Error text
error: { color: colors.error, bold: true }
};
// ═══════════════════════════════════════════════════════════════
// BORDER STYLES
// ═══════════════════════════════════════════════════════════════
export function getBorderStyle() {
return isUnicodeOK() ? 'round' : 'single';
}
export const borders = {
// Only use for outer app frame
frame: {
style: getBorderStyle,
color: colors.border
},
// Card-specific styles
cards: {
system: {
borderStyle: hasUnicode ? 'round' : 'single',
borderColor: 'yellow',
paddingX: 1,
paddingY: 0,
marginBottom: 1
},
user: {
marginTop: 1,
marginBottom: 1,
promptIcon: hasUnicode ? '' : '>',
promptColor: 'cyan'
},
assistant: {
borderStyle: 'single',
borderColor: 'gray',
paddingX: 1,
paddingY: 0,
marginBottom: 1,
divider: hasUnicode ? '── Assistant ──' : '-- Assistant --'
},
error: {
borderStyle: hasUnicode ? 'round' : 'single',
borderColor: 'red',
paddingX: 1,
paddingY: 0,
marginBottom: 1,
icon: hasUnicode ? '⚠' : '!'
}
// Inner elements use NO borders - only dividers
none: null
};
// ═══════════════════════════════════════════════════════════════
// RAIL STYLING (replaces nested boxes)
// ═══════════════════════════════════════════════════════════════
export const rail = {
width: 2, // Rail column width
// Characters
char: {
active: isUnicodeOK() ? '' : '|',
streaming: isUnicodeOK() ? '┃' : '|',
dimmed: isUnicodeOK() ? '╎' : ':'
},
// Icons with fallback
icons: {
info: hasUnicode ? '' : 'i',
warning: hasUnicode ? '⚠' : '!',
error: hasUnicode ? '✗' : 'X',
success: hasUnicode ? '✓' : 'OK',
bullet: hasUnicode ? '•' : '-',
arrow: hasUnicode ? '→' : '->',
prompt: hasUnicode ? '' : '>'
// Colors by role
colors: {
user: colors.rail.user,
assistant: colors.rail.assistant,
system: colors.rail.system,
tool: colors.rail.tool,
error: colors.rail.error,
thinking: colors.rail.thinking
}
};
// ═══════════════════════════════════════════════════════════════
// LAYOUT CONSTANTS
// ═══════════════════════════════════════════════════════════════
export const layout = {
// Sidebar
sidebar: {
minWidth: 20,
maxWidth: 28,
defaultWidth: 24
},
// Divider between sidebar and main
divider: {
width: 1,
char: isUnicodeOK() ? '│' : '|',
color: colors.border
},
// Transcript (main content)
transcript: {
maxLineWidth: 90, // Clamp for readability
minLineWidth: 40,
padding: 1
},
// Input bar (fixed height)
inputBar: {
height: 3, // Fixed - never changes
borderTop: true
},
// Status strip (single line)
statusStrip: {
height: 1
},
// Fixed row reservations
reservedRows: {
statusStrip: 1,
inputBar: 3,
frameTop: 1,
frameBottom: 1
}
};
// ═══════════════════════════════════════════════════════════════
// BREAKPOINTS
// ═══════════════════════════════════════════════════════════════
export const breakpoints = {
tiny: 60, // Hide sidebar
narrow: 80, // Minimal sidebar
medium: 100, // Normal sidebar
wide: 120 // Full sidebar
};
// ═══════════════════════════════════════════════════════════════
// PROFILE-GATED BACKGROUNDS
// ═══════════════════════════════════════════════════════════════
export function getBackground(purpose) {
// SAFE_ASCII: avoid backgrounds entirely
if (!isBackgroundOK()) {
return undefined;
}
const backgrounds = {
selection: '#1a1a2e', // Dark selection
focus: '#0d1117', // Focus highlight
error: '#2d1f1f', // Error background
warning: '#2d2a1f', // Warning background
thinking: '#1a1a1a' // Thinking block
};
return backgrounds[purpose];
}
// ═══════════════════════════════════════════════════════════════
// UNIFIED THEME OBJECT (backwards compatible)
// ═══════════════════════════════════════════════════════════════
export const theme = {
colors,
spacing,
typography,
borders,
rail,
layout,
breakpoints,
// Helper functions
getBorderStyle,
getBackground,
// Capability checks
isUnicodeOK,
isBackgroundOK,
isDimOK
};
export default theme;