Skip to main content

vtcode_config/constants/
ui.rs

1pub const TOOL_OUTPUT_MODE_COMPACT: &str = "compact";
2pub const TOOL_OUTPUT_MODE_FULL: &str = "full";
3pub const DEFAULT_INLINE_VIEWPORT_ROWS: u16 = 16;
4pub const DEFAULT_REASONING_VISIBLE: bool = false;
5pub const SLASH_SUGGESTION_LIMIT: usize = 50; // All commands are scrollable
6pub const SLASH_PALETTE_MIN_WIDTH: u16 = 40;
7pub const SLASH_PALETTE_MIN_HEIGHT: u16 = 9;
8pub const SLASH_PALETTE_HORIZONTAL_MARGIN: u16 = 8;
9pub const SLASH_PALETTE_TOP_OFFSET: u16 = 3;
10pub const SLASH_PALETTE_CONTENT_PADDING: u16 = 6;
11pub const SLASH_PALETTE_HINT_PRIMARY: &str = "Type to filter slash commands.";
12pub const SLASH_PALETTE_HINT_SECONDARY: &str = "Press Enter to apply • Esc to dismiss.";
13pub const MODAL_MIN_WIDTH: u16 = 36;
14pub const MODAL_MIN_HEIGHT: u16 = 9;
15pub const MODAL_LIST_MIN_HEIGHT: u16 = 12;
16pub const MODAL_WIDTH_RATIO: f32 = 0.6;
17pub const MODAL_HEIGHT_RATIO: f32 = 0.6;
18pub const MODAL_MAX_WIDTH_RATIO: f32 = 0.9;
19pub const MODAL_MAX_HEIGHT_RATIO: f32 = 0.8;
20pub const MODAL_CONTENT_HORIZONTAL_PADDING: u16 = 8;
21pub const MODAL_CONTENT_VERTICAL_PADDING: u16 = 6;
22pub const MODAL_INSTRUCTIONS_TITLE: &str = "";
23pub const MODAL_INSTRUCTIONS_BULLET: &str = "•";
24pub const INLINE_HEADER_HEIGHT: u16 = 3;
25pub const INLINE_INPUT_HEIGHT: u16 = 4;
26pub const INLINE_INPUT_MAX_LINES: usize = 10;
27pub const INLINE_NAVIGATION_PERCENT: u16 = 28;
28pub const INLINE_NAVIGATION_MIN_WIDTH: u16 = 24;
29pub const INLINE_CONTENT_MIN_WIDTH: u16 = 48;
30pub const INLINE_STACKED_NAVIGATION_PERCENT: u16 = INLINE_NAVIGATION_PERCENT;
31pub const INLINE_SCROLLBAR_EDGE_PADDING: u16 = 1;
32pub const INLINE_TRANSCRIPT_BOTTOM_PADDING: u16 = 6;
33pub const INLINE_PREVIEW_MAX_CHARS: usize = 56;
34pub const INLINE_PREVIEW_ELLIPSIS: &str = "…";
35pub const HEADER_HIGHLIGHT_PREVIEW_MAX_CHARS: usize = 48;
36pub const INLINE_AGENT_MESSAGE_LEFT_PADDING: &str = "";
37pub const INLINE_AGENT_QUOTE_PREFIX: &str = "";
38pub const INLINE_USER_MESSAGE_DIVIDER_SYMBOL: &str = "─";
39
40/// Scroll percentage format in status bar
41pub const SCROLL_INDICATOR_FORMAT: &str = "↕";
42/// Show scroll percentage in status bar
43pub const SCROLL_INDICATOR_ENABLED: bool = true;
44
45pub const INLINE_BLOCK_TOP_LEFT: &str = "╭";
46pub const INLINE_BLOCK_TOP_RIGHT: &str = "╮";
47pub const INLINE_BLOCK_BODY_LEFT: &str = "│";
48pub const INLINE_BLOCK_BODY_RIGHT: &str = "│";
49pub const INLINE_BLOCK_BOTTOM_LEFT: &str = "╰";
50pub const INLINE_BLOCK_BOTTOM_RIGHT: &str = "╯";
51pub const INLINE_BLOCK_HORIZONTAL: &str = "─";
52pub const INLINE_TOOL_HEADER_LABEL: &str = "Tool";
53pub const INLINE_TOOL_ACTION_PREFIX: &str = "→";
54pub const INLINE_TOOL_DETAIL_PREFIX: &str = "↳";
55pub const INLINE_PTY_HEADER_LABEL: &str = "Terminal";
56pub const INLINE_PTY_RUNNING_LABEL: &str = "running";
57pub const INLINE_PTY_STATUS_LIVE: &str = "LIVE";
58pub const INLINE_PTY_STATUS_DONE: &str = "DONE";
59pub const INLINE_PTY_PLACEHOLDER: &str = "Terminal output";
60pub const MODAL_LIST_HIGHLIGHT_SYMBOL: &str = "✦";
61pub const MODAL_LIST_HIGHLIGHT_FULL: &str = "✦ ";
62pub const MODAL_LIST_SUMMARY_FILTER_LABEL: &str = "Filter";
63pub const MODAL_LIST_SUMMARY_SEPARATOR: &str = " • ";
64pub const MODAL_LIST_SUMMARY_MATCHES_LABEL: &str = "Matches";
65pub const MODAL_LIST_SUMMARY_TOTAL_LABEL: &str = "of";
66pub const MODAL_LIST_SUMMARY_NO_MATCHES: &str = "No matches";
67pub const MODAL_LIST_SUMMARY_RESET_HINT: &str = "Press Esc to reset";
68pub const MODAL_LIST_NO_RESULTS_MESSAGE: &str = "No matching options";
69pub const HEADER_VERSION_PROMPT: &str = "> ";
70pub const HEADER_VERSION_PREFIX: &str = "VT Code";
71pub const HEADER_VERSION_LEFT_DELIMITER: &str = "(";
72pub const HEADER_VERSION_RIGHT_DELIMITER: &str = ")";
73pub const HEADER_MODE_INLINE: &str = "Inline session";
74pub const HEADER_MODE_ALTERNATE: &str = "Alternate session";
75pub const HEADER_MODE_AUTO: &str = "Auto session";
76pub const HEADER_MODE_FULL_AUTO_SUFFIX: &str = " (full)";
77pub const HEADER_MODE_PRIMARY_SEPARATOR: &str = " | ";
78pub const HEADER_MODE_SECONDARY_SEPARATOR: &str = " | ";
79pub const HEADER_PROVIDER_PREFIX: &str = "Provider: ";
80pub const HEADER_MODEL_PREFIX: &str = "Model: ";
81pub const HEADER_REASONING_PREFIX: &str = "Reasoning effort: ";
82pub const HEADER_TRUST_PREFIX: &str = "Trust: ";
83pub const HEADER_TOOLS_PREFIX: &str = "Tools: ";
84pub const HEADER_MCP_PREFIX: &str = "MCP: ";
85pub const HEADER_GIT_PREFIX: &str = "git: ";
86pub const HEADER_GIT_CLEAN_SUFFIX: &str = "✓";
87pub const HEADER_GIT_DIRTY_SUFFIX: &str = "*";
88pub const HEADER_UNKNOWN_PLACEHOLDER: &str = "unavailable";
89pub const HEADER_STATUS_LABEL: &str = "Status";
90pub const HEADER_STATUS_ACTIVE: &str = "Active";
91pub const HEADER_STATUS_PAUSED: &str = "Paused";
92pub const HEADER_MESSAGES_LABEL: &str = "Messages";
93pub const HEADER_INPUT_LABEL: &str = "Input";
94pub const HEADER_INPUT_ENABLED: &str = "Enabled";
95pub const HEADER_INPUT_DISABLED: &str = "Disabled";
96pub const INLINE_USER_PREFIX: &str = " ";
97pub const CHAT_INPUT_PLACEHOLDER_BOOTSTRAP: &str =
98    "Implement {feature} in {file} (@files, #prompts, /commands)";
99pub const CHAT_INPUT_PLACEHOLDER_FOLLOW_UP: &str =
100    "Build something (@files, #prompts, /commands or Shift+Tab to switch to modes)";
101pub const HEADER_SHORTCUT_HINT: &str = "Shortcuts: Enter=submit | Shift+Enter=newline | Ctrl/Cmd+Enter=queue | Esc=cancel | Ctrl+C=interrupt | @=file picker | #=custom prompts | /=slash commands";
102pub const HEADER_META_SEPARATOR: &str = "   ";
103pub const WELCOME_TEXT_WIDTH: usize = 80;
104pub const WELCOME_SHORTCUT_SECTION_TITLE: &str = "Keyboard Shortcuts";
105pub const WELCOME_SHORTCUT_HINT_PREFIX: &str = "Shortcuts:";
106pub const WELCOME_SHORTCUT_SEPARATOR: &str = "•";
107pub const WELCOME_SHORTCUT_INDENT: &str = "  ";
108pub const WELCOME_SLASH_COMMAND_SECTION_TITLE: &str = "Slash Commands";
109pub const WELCOME_SLASH_COMMAND_LIMIT: usize = 6;
110pub const WELCOME_SLASH_COMMAND_PREFIX: &str = "/";
111pub const WELCOME_SLASH_COMMAND_INTRO: &str = "";
112pub const WELCOME_SLASH_COMMAND_INDENT: &str = "  ";
113pub const NAVIGATION_BLOCK_TITLE: &str = "Timeline";
114pub const NAVIGATION_BLOCK_SHORTCUT_NOTE: &str = "Ctrl+T";
115pub const NAVIGATION_EMPTY_LABEL: &str = "Waiting for activity";
116pub const NAVIGATION_INDEX_PREFIX: &str = "#";
117pub const NAVIGATION_LABEL_AGENT: &str = "Agent";
118pub const NAVIGATION_LABEL_ERROR: &str = "Error";
119pub const NAVIGATION_LABEL_INFO: &str = "Info";
120pub const NAVIGATION_LABEL_POLICY: &str = "Policy";
121pub const NAVIGATION_LABEL_TOOL: &str = "Tool";
122pub const NAVIGATION_LABEL_USER: &str = "User";
123pub const NAVIGATION_LABEL_PTY: &str = "PTY";
124pub const PLAN_BLOCK_TITLE: &str = "TODOs";
125pub const PLAN_STATUS_EMPTY: &str = "No TODOs";
126pub const PLAN_STATUS_IN_PROGRESS: &str = "In progress";
127pub const PLAN_STATUS_DONE: &str = "Done";
128pub const PLAN_IN_PROGRESS_NOTE: &str = "in progress";
129pub const SUGGESTION_BLOCK_TITLE: &str = "Slash Commands";
130pub const STATUS_LINE_MODE: &str = "auto";
131pub const STATUS_LINE_REFRESH_INTERVAL_MS: u64 = 1000;
132pub const STATUS_LINE_COMMAND_TIMEOUT_MS: u64 = 200;
133
134// TUI tick rate constants for smooth scrolling
135/// Tick rate (Hz) when user is actively interacting with the TUI
136pub const TUI_ACTIVE_TICK_RATE_HZ: f64 = 60.0;
137/// Tick rate (Hz) when TUI is idle to save CPU
138pub const TUI_IDLE_TICK_RATE_HZ: f64 = 4.0;
139/// Duration (ms) to remain in active mode after last input
140pub const TUI_ACTIVE_TIMEOUT_MS: u64 = 500;
141/// Shimmer frame interval in milliseconds
142pub const TUI_SHIMMER_FRAME_INTERVAL_MS: u64 = 50;
143/// Shimmer sweep duration in milliseconds
144pub const TUI_SHIMMER_SWEEP_DURATION_MS: u64 = 2000;
145
146// Viewport size limits to prevent pathological CPU usage with huge terminals
147// (e.g., 2000+ columns causes 100% CPU without these guards)
148// See: https://github.com/anthropics/claude-code/issues/21567
149/// Maximum effective viewport width (columns) for rendering
150pub const TUI_MAX_VIEWPORT_WIDTH: u16 = 500;
151/// Maximum effective viewport height (rows) for rendering
152pub const TUI_MAX_VIEWPORT_HEIGHT: u16 = 200;
153
154// Theme and color constants
155pub const THEME_MIN_CONTRAST_RATIO: f64 = 4.5;
156pub const THEME_FOREGROUND_LIGHTEN_RATIO: f64 = 0.25;
157pub const THEME_SECONDARY_LIGHTEN_RATIO: f64 = 0.2;
158pub const THEME_MIX_RATIO: f64 = 0.35;
159pub const THEME_TOOL_BODY_MIX_RATIO: f64 = 0.35;
160pub const THEME_TOOL_BODY_LIGHTEN_RATIO: f64 = 0.2;
161pub const THEME_RESPONSE_COLOR_LIGHTEN_RATIO: f64 = 0.15;
162pub const THEME_REASONING_COLOR_LIGHTEN_RATIO: f64 = 0.3;
163pub const THEME_USER_COLOR_LIGHTEN_RATIO: f64 = 0.2;
164pub const THEME_SECONDARY_USER_COLOR_LIGHTEN_RATIO: f64 = 0.4;
165pub const THEME_PRIMARY_STATUS_LIGHTEN_RATIO: f64 = 0.35;
166pub const THEME_PRIMARY_STATUS_SECONDARY_LIGHTEN_RATIO: f64 = 0.5;
167pub const THEME_LOGO_ACCENT_BANNER_LIGHTEN_RATIO: f64 = 0.35;
168pub const THEME_LOGO_ACCENT_BANNER_SECONDARY_LIGHTEN_RATIO: f64 = 0.25;
169
170// UI Color constants
171pub const THEME_COLOR_WHITE_RED: u8 = 0xFF;
172pub const THEME_COLOR_WHITE_GREEN: u8 = 0xFF;
173pub const THEME_COLOR_WHITE_BLUE: u8 = 0xFF;
174pub const THEME_MIX_RATIO_MIN: f64 = 0.0;
175pub const THEME_MIX_RATIO_MAX: f64 = 1.0;
176pub const THEME_BLEND_CLAMP_MIN: f64 = 0.0;
177pub const THEME_BLEND_CLAMP_MAX: f64 = 255.0;
178
179// WCAG contrast algorithm constants
180pub const THEME_RELATIVE_LUMINANCE_CUTOFF: f64 = 0.03928;
181pub const THEME_RELATIVE_LUMINANCE_LOW_FACTOR: f64 = 12.92;
182pub const THEME_RELATIVE_LUMINANCE_OFFSET: f64 = 0.055;
183pub const THEME_RELATIVE_LUMINANCE_EXPONENT: f64 = 2.4;
184pub const THEME_CONTRAST_RATIO_OFFSET: f64 = 0.05;
185pub const THEME_RED_LUMINANCE_COEFFICIENT: f64 = 0.2126;
186pub const THEME_GREEN_LUMINANCE_COEFFICIENT: f64 = 0.7152;
187pub const THEME_BLUE_LUMINANCE_COEFFICIENT: f64 = 0.0722;
188pub const THEME_LUMINANCE_LIGHTEN_RATIO: f64 = 0.2;
189
190// === Safe ANSI Color Palette ===
191// Based on terminal color portability research: https://blog.xoria.org/terminal-colors/
192// These 11 colors are safe across Basic (light/dark), Tango, and Solarized themes.
193// Colors NOT in this list have visibility issues in common terminal configurations.
194
195/// WCAG AA standard minimum contrast ratio (4.5:1)
196pub const WCAG_AA_CONTRAST_RATIO: f64 = 4.5;
197
198/// WCAG AAA standard minimum contrast ratio (7.0:1)
199pub const WCAG_AAA_CONTRAST_RATIO: f64 = 7.0;
200
201/// Large text minimum contrast ratio (3.0:1)
202pub const WCAG_LARGE_TEXT_CONTRAST_RATIO: f64 = 3.0;
203
204// Safe ANSI color indices (standard 0-15 palette)
205// These colors are portable across common terminal themes.
206
207/// Safe regular colors (ANSI 0-7 subset that works everywhere)
208/// Note: black (0) and white (7) are excluded due to theme conflicts
209pub const SAFE_ANSI_RED: u8 = 1;
210pub const SAFE_ANSI_GREEN: u8 = 2;
211pub const SAFE_ANSI_YELLOW: u8 = 3;
212pub const SAFE_ANSI_BLUE: u8 = 4;
213pub const SAFE_ANSI_MAGENTA: u8 = 5;
214pub const SAFE_ANSI_CYAN: u8 = 6;
215
216/// Safe bright colors (ANSI 8-15 subset that works everywhere)
217/// Note: brblack (8) is invisible in Solarized Dark
218/// Note: bryellow (11), brblue (12), brwhite (15) have visibility issues
219pub const SAFE_ANSI_BRIGHT_RED: u8 = 9;
220pub const SAFE_ANSI_BRIGHT_GREEN: u8 = 10;
221pub const SAFE_ANSI_BRIGHT_MAGENTA: u8 = 13;
222pub const SAFE_ANSI_BRIGHT_CYAN: u8 = 14;
223
224/// All safe ANSI color indices as an array
225/// These 10 colors are safe to use across all common terminal themes
226pub const SAFE_ANSI_COLORS: [u8; 10] = [
227    SAFE_ANSI_RED,
228    SAFE_ANSI_GREEN,
229    SAFE_ANSI_YELLOW,
230    SAFE_ANSI_BLUE,
231    SAFE_ANSI_MAGENTA,
232    SAFE_ANSI_CYAN,
233    SAFE_ANSI_BRIGHT_RED,
234    SAFE_ANSI_BRIGHT_GREEN,
235    SAFE_ANSI_BRIGHT_MAGENTA,
236    SAFE_ANSI_BRIGHT_CYAN,
237];
238
239/// Problematic ANSI colors to avoid when safe_colors_only is enabled
240/// - 0 (black): Low contrast on dark backgrounds
241/// - 7 (white): Low contrast on light backgrounds
242/// - 8 (brblack): Invisible in Solarized Dark (hijacked for base03)
243/// - 11 (bryellow): Low contrast on light backgrounds
244/// - 12 (brblue): Low contrast in Basic Dark
245/// - 15 (brwhite): Low contrast on light backgrounds
246pub const PROBLEMATIC_ANSI_COLORS: [u8; 6] = [0, 7, 8, 11, 12, 15];