feat(yahweh-widget-banner): widget compartido para toasts/errores cross-app
Patrón visual común a yahweh-widget-meta-form (toast success +
error banner) y nakui-explorer (error banner): div con bg + text
colored según severidad. Antes duplicado con colores hardcoded en
cada consumer.
Crate nuevo crates/modules/ui_engine/widgets/banner:
- pub enum Banner { Info, Success, Warning, Error } con bg()/fg()
hardcoded por variant.
- pub fn banner(kind, message) -> Div: padding/text_size defaults;
caller compone con .child()/.px()/.on_click()/etc.
- 2 tests sanity (no color collisions).
Migración:
- yahweh-widget-meta-form: 12 líneas hardcoded → 2 llamadas a
banner().
- nakui-explorer: error banner usa banner() + override de
padding custom del header.
Tests stack: 109 → 111 (+2). Cada crate compila individualmente.
Próximo natural: confirm_delete_banner (Warning + botones) puede
extraerse como modal-banner cuando emerja segundo consumer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ uuid = { workspace = true, features = ["serde"] }
|
||||
yahweh-meta-runtime = { path = "../../libs/meta-runtime" }
|
||||
yahweh-meta-schema = { path = "../../libs/meta-schema" }
|
||||
yahweh-theme = { path = "../../libs/theme" }
|
||||
yahweh-widget-banner = { path = "../banner" }
|
||||
yahweh-widget-text-input = { path = "../text_input" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -34,6 +34,7 @@ use yahweh_meta_runtime::{
|
||||
MetaBackend, WriteOutcome,
|
||||
};
|
||||
use yahweh_meta_schema::{Action, FieldKind, FieldSpec, FormView, ListView, Module, View};
|
||||
use yahweh_widget_banner::{banner, Banner};
|
||||
use yahweh_widget_text_input::TextInput;
|
||||
|
||||
/// Estado del runtime de UI. Toda la persistencia/ejecución está
|
||||
@@ -450,24 +451,14 @@ impl<B: MetaBackend> Render for MetaApp<B> {
|
||||
let sidebar = self.render_sidebar(cx, panel, border, text, text_dim, accent_active);
|
||||
let main_panel = self.render_main(cx, panel, border, text, text_dim, accent);
|
||||
let confirm_banner = self.render_confirm_delete_banner(cx);
|
||||
let toast_div = self.toast.as_ref().map(|t| {
|
||||
div()
|
||||
.px(px(12.))
|
||||
.py(px(6.))
|
||||
.bg(gpui::rgb(0x2d3a2a))
|
||||
.text_color(gpui::rgb(0xc0e0a0))
|
||||
.text_size(px(11.))
|
||||
.child(t.clone())
|
||||
});
|
||||
let error_banner = self.load_error.as_ref().map(|e| {
|
||||
div()
|
||||
.px(px(12.))
|
||||
.py(px(6.))
|
||||
.bg(gpui::rgb(0x4a2020))
|
||||
.text_color(gpui::rgb(0xffd0d0))
|
||||
.text_size(px(11.))
|
||||
.child(e.clone())
|
||||
});
|
||||
let toast_div = self
|
||||
.toast
|
||||
.as_ref()
|
||||
.map(|t| banner(Banner::Success, t.clone()));
|
||||
let error_banner = self
|
||||
.load_error
|
||||
.as_ref()
|
||||
.map(|e| banner(Banner::Error, e.clone()));
|
||||
|
||||
div()
|
||||
.flex()
|
||||
|
||||
Reference in New Issue
Block a user