feat(nouser-explorer): integración al stack yahweh themed
Iter 10. nouser-explorer (paralela a nakui-explorer pero para ver Mónadas via daemon nouser) tenía colors hardcoded idénticos al patrón previo. Aplico el mismo refactor: theme global instalado, chrome a slots, widgets compartidos. - Nuevas deps: yahweh-theme + 3 widgets (banner, card, theme-switcher). - main() instala Theme::install_default. - render: 4 vars rgb() chrome → theme slots. - Header: flex_row + theme switcher a la derecha (mismo pattern que nakui-explorer). - error_banner: div hardcoded → banner_themed(Error). - 2 cards (Engine/Monad): div().flex_col().p().bg().rounded()... → card_themed(cx).border_l_4().border_color(accent). - Accents semánticos (engine cyan, data purple) quedan locales como señales de dominio. Las dos apps explorer del repo ahora comparten paleta themed + switcher común. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,43 @@ ratio/diff ver `git show <sha>`.
|
|||||||
|
|
||||||
## 2026-05-10
|
## 2026-05-10
|
||||||
|
|
||||||
|
### feat(nouser-explorer): integración al stack yahweh themed
|
||||||
|
Iter 10. `nouser-explorer` (la app paralela a `nakui-explorer`
|
||||||
|
para ver Mónadas via daemon nouser) tenía colors hardcoded
|
||||||
|
idénticos al patrón previo. Aplico el mismo refactor que se hizo
|
||||||
|
para `nakui-explorer` en iter 4: instala el theme global, migra
|
||||||
|
chrome a slots, usa los widgets `banner_themed` / `card_themed` /
|
||||||
|
`theme_switcher`.
|
||||||
|
|
||||||
|
Cambios en `nouser-explorer`:
|
||||||
|
- **Nuevas deps**: `yahweh-theme`, `yahweh-widget-banner`,
|
||||||
|
`yahweh-widget-card`, `yahweh-widget-theme-switcher`.
|
||||||
|
- **`main()`**: `Theme::install_default(cx)` antes de
|
||||||
|
`cx.open_window`.
|
||||||
|
- **`render`**: 4 vars `let X = rgb(...)` (chrome) → theme slots
|
||||||
|
(`bg_app`/`fg_text`/`fg_muted`/`bg_panel`/`border`).
|
||||||
|
- **Header**: gana flex_row + theme switcher en la derecha (mismo
|
||||||
|
pattern que nakui-explorer).
|
||||||
|
- **`error_banner`**: pasa de div hardcoded a `banner_themed(cx,
|
||||||
|
Banner::Error, ...)` con override de padding (16/8) por
|
||||||
|
convención del header.
|
||||||
|
- **2 cards de Engine y Monad**: pasan de `div().flex().flex_col()
|
||||||
|
.p().mb().bg(card_bg).rounded().border_l_4().border_color()...`
|
||||||
|
a `card_themed(cx).border_l_4().border_color(accent)...`.
|
||||||
|
- **Acentos semánticos**: `accent_engine` (cyan, las "máquinas")
|
||||||
|
y `accent_data` (purple, las Mónadas) quedan locales — son
|
||||||
|
señales del dominio nouser, no del chrome.
|
||||||
|
|
||||||
|
Tests: workspace stack intacto. nouser-explorer no tiene tests
|
||||||
|
propios (siempre fue una vista live del daemon, sin lógica
|
||||||
|
testable separada).
|
||||||
|
|
||||||
|
Beneficio operativo: las dos apps explorer del repo
|
||||||
|
(`nakui-explorer` para event log + `nouser-explorer` para Mónadas)
|
||||||
|
ahora comparten la misma paleta themed + el mismo control de
|
||||||
|
switcher. Si un usuario las corre lado a lado, la consistencia
|
||||||
|
visual emerge sola.
|
||||||
|
|
||||||
### feat(yahweh): caret blinking + slots ornament en theme + MetaApp full themed
|
### feat(yahweh): caret blinking + slots ornament en theme + MetaApp full themed
|
||||||
Iters 8-9 combinadas. Tres mejoras pequeñas que cierran la
|
Iters 8-9 combinadas. Tres mejoras pequeñas que cierran la
|
||||||
integración del theme:
|
integración del theme:
|
||||||
|
|||||||
Generated
+4
@@ -6857,6 +6857,10 @@ dependencies = [
|
|||||||
"brahman-sidecar",
|
"brahman-sidecar",
|
||||||
"gpui",
|
"gpui",
|
||||||
"nouser-card",
|
"nouser-card",
|
||||||
|
"yahweh-theme",
|
||||||
|
"yahweh-widget-banner",
|
||||||
|
"yahweh-widget-card",
|
||||||
|
"yahweh-widget-theme-switcher",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ description = "Explorador GPUI de Mónadas: panel que descubre al daemon nouser
|
|||||||
brahman-card = { path = "../../core/brahman-card" }
|
brahman-card = { path = "../../core/brahman-card" }
|
||||||
brahman-sidecar = { path = "../../shared/brahman-sidecar" }
|
brahman-sidecar = { path = "../../shared/brahman-sidecar" }
|
||||||
nouser-card = { path = "../../modules/nouser/card" }
|
nouser-card = { path = "../../modules/nouser/card" }
|
||||||
|
yahweh-theme = { path = "../../modules/ui_engine/libs/theme" }
|
||||||
|
yahweh-widget-banner = { path = "../../modules/ui_engine/widgets/banner" }
|
||||||
|
yahweh-widget-card = { path = "../../modules/ui_engine/widgets/card" }
|
||||||
|
yahweh-widget-theme-switcher = { path = "../../modules/ui_engine/widgets/theme-switcher" }
|
||||||
gpui = { workspace = true }
|
gpui = { workspace = true }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ use gpui::{
|
|||||||
use nouser_card::query::client as query_client;
|
use nouser_card::query::client as query_client;
|
||||||
use nouser_card::query::{transport, ListMonadsResponse, FLOW_MONAD_LIST, FLOW_TYPE_NAME};
|
use nouser_card::query::{transport, ListMonadsResponse, FLOW_MONAD_LIST, FLOW_TYPE_NAME};
|
||||||
use nouser_card::Lens;
|
use nouser_card::Lens;
|
||||||
|
use yahweh_theme::Theme;
|
||||||
|
use yahweh_widget_banner::{banner_themed, Banner};
|
||||||
|
use yahweh_widget_card::card_themed;
|
||||||
|
use yahweh_widget_theme_switcher::theme_switcher;
|
||||||
|
|
||||||
const REFRESH_INTERVAL: Duration = Duration::from_secs(2);
|
const REFRESH_INTERVAL: Duration = Duration::from_secs(2);
|
||||||
const DISCOVERY_TIMEOUT: Duration = Duration::from_secs(3);
|
const DISCOVERY_TIMEOUT: Duration = Duration::from_secs(3);
|
||||||
@@ -36,6 +40,9 @@ const QUERY_TIMEOUT: Duration = Duration::from_secs(2);
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Application::new().run(|cx: &mut App| {
|
Application::new().run(|cx: &mut App| {
|
||||||
|
// Theme global instalado al boot — los widgets themed lo
|
||||||
|
// requieren y unifica el chrome del app.
|
||||||
|
Theme::install_default(cx);
|
||||||
let bounds = Bounds::centered(None, gpui::size(px(900.), px(640.)), cx);
|
let bounds = Bounds::centered(None, gpui::size(px(900.), px(640.)), cx);
|
||||||
cx.open_window(
|
cx.open_window(
|
||||||
WindowOptions {
|
WindowOptions {
|
||||||
@@ -192,11 +199,14 @@ fn discover_via_broker() -> Result<PathBuf, ConsumerError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Render for Explorer {
|
impl Render for Explorer {
|
||||||
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 bg = rgb(0x14171c);
|
// Chrome viene del Theme global; los acentos por kind
|
||||||
let card_bg = rgb(0x1d2128);
|
// (engine cyan, data purple) son señales semánticas del
|
||||||
let text_dim = rgb(0x9ba1ad);
|
// dominio nouser y se mantienen locales.
|
||||||
let text = rgb(0xe6e8ec);
|
let theme = Theme::global(cx).clone();
|
||||||
|
let bg = theme.bg_app.clone();
|
||||||
|
let text = theme.fg_text;
|
||||||
|
let text_dim = theme.fg_muted;
|
||||||
let accent_engine = rgb(0x88c0d0);
|
let accent_engine = rgb(0x88c0d0);
|
||||||
let accent_data = rgb(0xb48ead);
|
let accent_data = rgb(0xb48ead);
|
||||||
|
|
||||||
@@ -216,24 +226,27 @@ impl Render for Explorer {
|
|||||||
_ => "Buscando daemon nouser vía brahman-broker…".to_string(),
|
_ => "Buscando daemon nouser vía brahman-broker…".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Header con título a la izquierda + theme switcher a la
|
||||||
|
// derecha (mismo pattern que nakui-explorer).
|
||||||
let header = div()
|
let header = div()
|
||||||
|
.flex()
|
||||||
|
.flex_row()
|
||||||
|
.items_center()
|
||||||
.px(px(16.))
|
.px(px(16.))
|
||||||
.py(px(12.))
|
.py(px(12.))
|
||||||
.bg(card_bg)
|
.bg(theme.bg_panel.clone())
|
||||||
.border_b_1()
|
.border_b_1()
|
||||||
.border_color(rgb(0x2a2f38))
|
.border_color(theme.border)
|
||||||
.text_color(text)
|
.text_color(text)
|
||||||
.text_size(px(14.))
|
.text_size(px(14.))
|
||||||
.child(header_text);
|
.child(div().flex_grow().child(header_text))
|
||||||
|
.child(theme_switcher(cx));
|
||||||
|
|
||||||
let error_banner = self.error.as_ref().map(|e| {
|
let error_banner = self.error.as_ref().map(|e| {
|
||||||
div()
|
banner_themed(cx, Banner::Error, e.clone())
|
||||||
.px(px(16.))
|
.px(px(16.))
|
||||||
.py(px(8.))
|
.py(px(8.))
|
||||||
.bg(rgb(0x4a2020))
|
|
||||||
.text_color(rgb(0xffd0d0))
|
|
||||||
.text_size(px(12.))
|
.text_size(px(12.))
|
||||||
.child(e.clone())
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let cards: Vec<gpui::AnyElement> = match &self.snapshot {
|
let cards: Vec<gpui::AnyElement> = match &self.snapshot {
|
||||||
@@ -243,16 +256,9 @@ impl Render for Explorer {
|
|||||||
|
|
||||||
// Engine card primero — el "ser" que owns las Mónadas.
|
// Engine card primero — el "ser" que owns las Mónadas.
|
||||||
out.push(
|
out.push(
|
||||||
div()
|
card_themed(cx)
|
||||||
.flex()
|
|
||||||
.flex_col()
|
|
||||||
.p(px(12.))
|
|
||||||
.mb(px(8.))
|
|
||||||
.bg(card_bg)
|
|
||||||
.rounded(px(6.))
|
|
||||||
.border_l_4()
|
.border_l_4()
|
||||||
.border_color(accent_engine)
|
.border_color(accent_engine)
|
||||||
.gap(px(2.))
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
@@ -305,16 +311,9 @@ impl Render for Explorer {
|
|||||||
.map(|m| format!("model: {m}"));
|
.map(|m| format!("model: {m}"));
|
||||||
|
|
||||||
out.push(
|
out.push(
|
||||||
div()
|
card_themed(cx)
|
||||||
.flex()
|
|
||||||
.flex_col()
|
|
||||||
.p(px(12.))
|
|
||||||
.mb(px(8.))
|
|
||||||
.bg(card_bg)
|
|
||||||
.rounded(px(6.))
|
|
||||||
.border_l_4()
|
.border_l_4()
|
||||||
.border_color(accent_data)
|
.border_color(accent_data)
|
||||||
.gap(px(2.))
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
|
|||||||
Reference in New Issue
Block a user