feat(yahweh-widget-text-input): focus-aware border + caret sólo on focus

Iter 7 (mini-iter — el text-input ya estaba themed, faltaba el
polish de focus visibility). Antes el border era siempre
accent_strong y el caret | siempre presente — imposible distinguir
cuál input está activo en un form con varios fields.

- Border focus-aware: focused → accent_strong; blur → border (slot
  tenue del theme).
- Caret | sólo on focus; sin focus se muestra texto plano (reduce
  ruido visual).
- render usa window.is_focused(focus_handle) para chequear.

Sin cambios en API pública. Tests downstream verdes.

Limitación: caret estático (no parpadea). Iter futura si emerge
la necesidad de animation timer via cx.spawn.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-05-10 10:51:00 +00:00
parent 8fdef818cc
commit fc4da751ca
2 changed files with 54 additions and 4 deletions
@@ -122,14 +122,28 @@ impl TextInput {
}
impl Render for TextInput {
fn render(&mut self, _w: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
fn render(&mut self, w: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let theme = Theme::global(cx).clone();
let is_empty = self.text.is_empty();
// Border-color depende del focus: focused → accent (señal
// clara de "vas a tipear acá"); blur → border (silencioso).
// Sin esto era imposible saber qué input estaba activo en
// un form con varios fields.
let is_focused = self.focus_handle.is_focused(w);
let border_color = if is_focused {
theme.accent_strong
} else {
theme.border
};
let display: SharedString = if is_empty {
self.placeholder.clone()
} else {
// Cursor siempre al final — sin movimiento de cursor.
} else if is_focused {
// Caret al final, sólo cuando el input tiene focus —
// así el usuario ve dónde va a aparecer el siguiente
// char. Inputs sin focus no muestran caret (es ruido).
SharedString::from(format!("{}|", self.text))
} else {
SharedString::from(self.text.clone())
};
let text_color = if is_empty {
theme.fg_disabled
@@ -147,7 +161,7 @@ impl Render for TextInput {
.min_w(px(200.0))
.bg(theme.bg_panel.clone())
.border_1()
.border_color(theme.accent_strong)
.border_color(border_color)
.rounded(px(4.0))
.text_size(px(13.0))
.text_color(text_color)