feat(yahweh): caret blinking + slots ornament en theme + MetaApp full themed

Iters 8-9 combinadas. Tres mejoras pequeñas que cierran la
integración del theme:

1) text-input caret blinking: caret_visible bool toggea cada 500ms
   via cx.spawn loop. _blink_task se mantiene en self para que
   drop cancele. render dibuja | sólo si focused && caret_visible.

2) yahweh-theme: 5 slots ornament secundario como methods (no
   fields) derivados de is_dark via ornament_slots() helper:
   bg_input/bg_button/bg_button_hover/accent_destructive/
   bg_destructive_hover. No requiere modificar los 6 presets.

3) MetaApp ornament cleanup: 11 rgb(0x...) hardcoded → slots del
   theme. Sidebar menu items, list row separator/buttons, icon ✕
   delete y su hover, EntityRef selector hovers, form submit
   button + fallback input bg, confirm modal hint y hovers.

Pattern: let X = theme.slot() antes de las closures + move |d|
d.bg(X) en hover/when para tomar ownership.

Antes MetaApp tenía la paleta principal themed (iter 5) pero el
ornament secundario seguía hardcoded. Ahora el theme switcher
cambia absolutamente todo el chrome.

Tests: 117 verdes. Downstream compila. Smoke nakui-ui: bootstrap
OK.

Limitación: nouser-explorer todavía hardcoded — próxima iter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-05-10 11:05:39 +00:00
parent fc4da751ca
commit ea074d7d57
4 changed files with 199 additions and 24 deletions
@@ -51,7 +51,67 @@ pub struct Theme {
impl Global for Theme {}
/// Helper privado: deriva los 5 slots "ornament secundario"
/// (bg_input/button/button_hover + accent_destructive +
/// bg_destructive_hover) según `is_dark`.
///
/// Devuelve los slots en el orden de los métodos públicos del
/// `Theme`. Los métodos del impl los exponen individualmente.
fn ornament_slots(is_dark: bool) -> (Hsla, Hsla, Hsla, Hsla, Hsla) {
if is_dark {
(
// bg_input: muy oscuro, sutil tinte azul/gris
hsla(220.0 / 360.0, 0.20, 0.07, 1.0),
// bg_button: medio oscuro
hsla(220.0 / 360.0, 0.18, 0.20, 1.0),
// bg_button_hover: un poco más claro
hsla(220.0 / 360.0, 0.20, 0.27, 1.0),
// accent_destructive: rojo medio-claro para visibilidad
hsla(0.0, 0.55, 0.65, 1.0),
// bg_destructive_hover: rojo oscuro de fondo
hsla(0.0, 0.55, 0.18, 1.0),
)
} else {
(
hsla(220.0 / 360.0, 0.10, 0.97, 1.0),
hsla(220.0 / 360.0, 0.15, 0.85, 1.0),
hsla(220.0 / 360.0, 0.20, 0.75, 1.0),
hsla(0.0, 0.65, 0.45, 1.0),
hsla(0.0, 0.55, 0.92, 1.0),
)
}
}
impl Theme {
/// Bg sutil para fields editables que se quieren marcar como
/// "input target" sin ser un panel. Derivado de `is_dark`.
pub fn bg_input(&self) -> Hsla {
ornament_slots(self.is_dark).0
}
/// Bg para clickable controls (botones secundarios, edit/delete
/// icons en filas). Más prominente que `bg_panel_alt`, menos que
/// `accent`. Derivado de `is_dark`.
pub fn bg_button(&self) -> Hsla {
ornament_slots(self.is_dark).1
}
/// Hover de [`Self::bg_button`].
pub fn bg_button_hover(&self) -> Hsla {
ornament_slots(self.is_dark).2
}
/// Accent rojo para acciones destructivas (delete, drop, force).
pub fn accent_destructive(&self) -> Hsla {
ornament_slots(self.is_dark).3
}
/// Bg de hover sobre clickable destructive elements (icon ✕,
/// botones de "borrar"). Más oscuro que `accent_destructive`.
pub fn bg_destructive_hover(&self) -> Hsla {
ornament_slots(self.is_dark).4
}
pub fn global(cx: &gpui::App) -> &Self {
cx.global::<Self>()
}