Skip to content

Commit e9507b5

Browse files
committed
fix(tui): placeholder clears immediately on first keystroke
Move placeholder ('Type a message...') from InputBox Widget to render_input_with_prompt() in app.rs. Placeholder renders as a background layer; any character in InputBox overwrites it. This fixes the issue where IME pre-edit characters appeared alongside the placeholder text.
1 parent 92310ae commit e9507b5

2 files changed

Lines changed: 16 additions & 12 deletions

File tree

crates/tui/src/app.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,16 @@ fn render_input_with_prompt(
10531053
width: area.width.saturating_sub(prefix_width + 2),
10541054
height: area.height,
10551055
};
1056+
1057+
// Show placeholder only when input is completely empty
1058+
if input.is_empty() {
1059+
let placeholder = Line::from(Span::styled(
1060+
"Type a message...",
1061+
Style::default().fg(Color::DarkGray),
1062+
));
1063+
Widget::render(placeholder, input_area, buf);
1064+
}
1065+
// Always render input on top (when non-empty, overwrites placeholder)
10561066
Widget::render(input, input_area, buf);
10571067
}
10581068

crates/tui/src/components/input.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
44
use ratatui::buffer::Buffer;
55
use ratatui::layout::Rect;
6-
use ratatui::style::{Color, Style};
7-
use ratatui::text::{Line, Span};
6+
use ratatui::text::Line;
87
use ratatui::widgets::Widget;
98

109
/// Multi-line text input box with cursor and history support.
@@ -319,14 +318,7 @@ impl Widget for &InputBox {
319318
.enumerate()
320319
{
321320
let y = area.y + i as u16;
322-
let display = if line.is_empty() && i == 0 && scroll_offset == 0 && self.is_empty() {
323-
Line::from(Span::styled(
324-
"Type a message...",
325-
Style::default().fg(Color::DarkGray),
326-
))
327-
} else {
328-
Line::from(line.as_str())
329-
};
321+
let display = Line::from(line.as_str());
330322
let line_area = Rect {
331323
x: area.x,
332324
y,
@@ -538,7 +530,8 @@ mod tests {
538530
}
539531

540532
#[test]
541-
fn renders_placeholder_when_empty() {
533+
fn renders_empty_when_no_text() {
534+
// Placeholder moved to app.rs render_input_with_prompt()
542535
let input = InputBox::new();
543536
let area = Rect::new(0, 0, 30, 1);
544537
let mut buf = Buffer::empty(area);
@@ -547,7 +540,8 @@ mod tests {
547540
let content: String = (0..area.width)
548541
.map(|x| buf.cell((x, 0)).unwrap().symbol().to_string())
549542
.collect();
550-
assert!(content.contains("Type a message"));
543+
// InputBox itself no longer renders placeholder
544+
assert!(!content.contains("Type a message"));
551545
}
552546

553547
#[test]

0 commit comments

Comments
 (0)