tawasuyu/llimphi
Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.
⎇ main
widgets/theme-switcher/examples/theme_switcher_demo.rs
Ñawpa willay
Pi imata llamkarqan
ch'uya
chore: refresco desde el monorepo — vello 0.9 / wgpu 29, 120 miembros
1//! Showcase de `llimphi-widget-theme-switcher`.
2//!
3//! Una ventana con el switcher en la cabecera + un sample de paneles
4//! que cambian de color al ciclar. Validación visual de que el theme
5//! propaga a la UI: al hacer click en el switcher, los paneles se
6//! repintan con el siguiente preset.
7//!
8//! Corre: `cargo run -p llimphi-widget-theme-switcher --example theme_switcher_demo --release`.
9
10use llimphi_theme::Theme;
11use llimphi_ui::llimphi_layout::taffy::{
12 prelude::{length, percent, AlignItems, FlexDirection, JustifyContent, Size, Style},
13 Rect,
14};
15use llimphi_ui::llimphi_text::Alignment;
16use llimphi_ui::{App, Handle, View};
17use llimphi_widget_theme_switcher::theme_switcher_view;
18
19#[derive(Clone, Debug)]
20enum Msg {
21 ChangeTheme(Theme),
22}
23
24struct Model {
25 theme: Theme,
26}
27
28struct Showcase;
29
30impl App for Showcase {
31 type Model = Model;
32 type Msg = Msg;
33
34 fn title() -> &'static str {
35 "llimphi · theme-switcher"
36 }
37
38 fn init(_: &Handle<Msg>) -> Model {
39 Model {
40 theme: Theme::dark(),
41 }
42 }
43
44 fn update(model: Model, msg: Msg, _: &Handle<Msg>) -> Model {
45 let mut m = model;
46 match msg {
47 Msg::ChangeTheme(t) => m.theme = t,
48 }
49 m
50 }
51
52 fn view(model: &Model) -> View<Msg> {
53 let switcher = theme_switcher_view(&model.theme, Msg::ChangeTheme);
54
55 let header = View::new(Style {
56 size: Size {
57 width: percent(1.0_f32),
58 height: length(48.0_f32),
59 },
60 flex_direction: FlexDirection::Row,
61 align_items: Some(AlignItems::CENTER),
62 justify_content: Some(JustifyContent::SPACE_BETWEEN),
63 padding: Rect {
64 left: length(16.0_f32),
65 right: length(16.0_f32),
66 top: length(0.0_f32),
67 bottom: length(0.0_f32),
68 },
69 ..Default::default()
70 })
71 .fill(model.theme.bg_panel)
72 .children(vec![
73 View::new(Style {
74 size: Size {
75 width: length(220.0_f32),
76 height: length(32.0_f32),
77 },
78 ..Default::default()
79 })
80 .text_aligned(
81 format!("Preset actual: {}", model.theme.name),
82 13.0,
83 model.theme.fg_text,
84 Alignment::Start,
85 ),
86 switcher,
87 ]);
88
89 let card_a = sample_card("Panel principal", &model.theme, model.theme.bg_panel);
90 let card_b = sample_card(
91 "Strip alternativo",
92 &model.theme,
93 model.theme.bg_panel_alt,
94 );
95 let card_c = sample_card("Input focado", &model.theme, model.theme.bg_input_focus);
96
97 let body = View::new(Style {
98 flex_direction: FlexDirection::Column,
99 size: Size {
100 width: percent(1.0_f32),
101 height: percent(1.0_f32),
102 },
103 padding: Rect {
104 left: length(24.0_f32),
105 right: length(24.0_f32),
106 top: length(24.0_f32),
107 bottom: length(24.0_f32),
108 },
109 gap: Size {
110 width: length(0.0_f32),
111 height: length(14.0_f32),
112 },
113 ..Default::default()
114 })
115 .fill(model.theme.bg_app)
116 .children(vec![card_a, card_b, card_c]);
117
118 View::new(Style {
119 flex_direction: FlexDirection::Column,
120 size: Size {
121 width: percent(1.0_f32),
122 height: percent(1.0_f32),
123 },
124 ..Default::default()
125 })
126 .fill(model.theme.bg_app)
127 .children(vec![header, body])
128 }
129}
130
131fn sample_card(label: &str, theme: &Theme, bg: llimphi_ui::llimphi_raster::peniko::Color) -> View<Msg> {
132 View::new(Style {
133 size: Size {
134 width: percent(1.0_f32),
135 height: length(60.0_f32),
136 },
137 padding: Rect {
138 left: length(14.0_f32),
139 right: length(14.0_f32),
140 top: length(0.0_f32),
141 bottom: length(0.0_f32),
142 },
143 align_items: Some(AlignItems::CENTER),
144 ..Default::default()
145 })
146 .fill(bg)
147 .radius(6.0)
148 .text_aligned(label.to_string(), 13.0, theme.fg_text, Alignment::Start)
149}
150
151fn main() {
152 llimphi_ui::run::<Showcase>();
153}