Skip to main content

TextBuilder

Struct TextBuilder 

Source
pub struct TextBuilder { /* private fields */ }
Expand description

Builder for styled Text views.

Implementations§

Source§

impl TextBuilder

Source

pub fn new(content: impl Into<String>) -> Self

Source

pub fn color(self, color: Color) -> Self

Set the text color.

Examples found in repository?
examples/24_async_data.rs (line 189)
183fn render_profile_section(profile: &Async<UserProfile>) -> View {
184    View::vstack()
185        .spacing(1)
186        .child(
187            View::styled_text("User Profile")
188                .bold()
189                .color(Color::Cyan)
190                .build(),
191        )
192        .child(View::styled_text("(loads in 2s)").dim().build())
193        .child(View::gap(1))
194        .child(match profile {
195            Async::Loading => View::vstack()
196                .child(View::styled_text("Loading...").dim().build())
197                .child(View::text("[=========>          ]"))
198                .build(),
199            Async::Ready(p) => View::vstack()
200                .spacing(0)
201                .child(View::text(format!("Name: {}", p.name)))
202                .child(View::text(format!("Email: {}", p.email)))
203                .child(View::text(format!("Member since: {}", p.member_since)))
204                .build(),
205            Async::Error(e) => View::styled_text(format!("Error: {}", e))
206                .color(Color::Red)
207                .build(),
208        })
209        .build()
210}
211
212fn render_stats_section(stats: &Async<Stats>) -> View {
213    View::vstack()
214        .spacing(1)
215        .child(
216            View::styled_text("User Stats")
217                .bold()
218                .color(Color::Green)
219                .build(),
220        )
221        .child(View::styled_text("(loads in 1s)").dim().build())
222        .child(View::gap(1))
223        .child(match stats {
224            Async::Loading => View::vstack()
225                .child(View::styled_text("Loading...").dim().build())
226                .child(View::text("[==================> ]"))
227                .build(),
228            Async::Ready(s) => View::vstack()
229                .spacing(0)
230                .child(View::text(format!("Posts: {}", s.posts)))
231                .child(View::text(format!("Followers: {}", s.followers)))
232                .child(View::text(format!("Following: {}", s.following)))
233                .build(),
234            Async::Error(e) => View::styled_text(format!("Error: {}", e))
235                .color(Color::Red)
236                .build(),
237        })
238        .build()
239}
240
241fn render_error_section(data: &Async<String>) -> View {
242    View::vstack()
243        .spacing(1)
244        .child(
245            View::styled_text("Failing Request")
246                .bold()
247                .color(Color::Red)
248                .build(),
249        )
250        .child(View::styled_text("(fails after 0.5s)").dim().build())
251        .child(View::gap(1))
252        .child(match data {
253            Async::Loading => View::vstack()
254                .child(View::styled_text("Loading...").dim().build())
255                .child(View::text("[=====================]"))
256                .build(),
257            Async::Ready(d) => View::text(format!("Data: {}", d)),
258            Async::Error(e) => View::vstack()
259                .child(
260                    View::styled_text("Request failed!")
261                        .color(Color::Red)
262                        .build(),
263                )
264                .child(View::styled_text(e.clone()).dim().build())
265                .build(),
266        })
267        .build()
268}
More examples
Hide additional examples
examples/04_timer.rs (line 49)
22    fn render(&self, cx: Scope) -> View {
23        let show_help = state!(cx, || false);
24
25        // F1 toggles help
26        cx.use_command(
27            KeyBinding::key(KeyCode::F(1)),
28            with!(show_help => move || show_help.update(|v| *v = !*v)),
29        );
30
31        // Stream that yields elapsed seconds
32        let elapsed = stream!(cx, || {
33            (0u64..).inspect(|&s| {
34                if s > 0 {
35                    std::thread::sleep(Duration::from_secs(1));
36                }
37            })
38        });
39
40        let seconds = elapsed.get();
41        let is_running = elapsed.is_loading();
42
43        // Format as MM:SS
44        let minutes = seconds / 60;
45        let secs = seconds % 60;
46        let time_display = format!("{:02}:{:02}", minutes, secs);
47
48        View::vstack()
49            .child(View::styled_text("Timer").color(Color::Cyan).bold().build())
50            .child(View::gap(1))
51            .child(
52                View::hstack()
53                    .child(View::styled_text(&time_display).bold().build())
54                    .child(if is_running {
55                        View::styled_text(" ●").color(Color::Green).build()
56                    } else {
57                        View::styled_text(" ○").dim().build()
58                    })
59                    .build(),
60            )
61            .child(View::gap(1))
62            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
63            .child(
64                View::modal()
65                    .visible(show_help.get())
66                    .title("Example 04: Timer")
67                    .on_dismiss(with!(show_help => move || show_help.set(false)))
68                    .child(
69                        View::vstack()
70                            .child(View::styled_text("What you're seeing").bold().build())
71                            .child(View::text("• stream!() macro for background data"))
72                            .child(View::text("• Auto-updating UI without user input"))
73                            .child(View::text("• Green dot = stream is running"))
74                            .child(View::gap(1))
75                            .child(View::styled_text("Key concepts").bold().build())
76                            .child(View::text("• Streams run in background threads"))
77                            .child(View::text("• Each yielded value triggers a re-render"))
78                            .child(View::text("• is_loading() tells you if stream is active"))
79                            .child(View::gap(1))
80                            .child(View::styled_text("Try this").bold().build())
81                            .child(View::text("• Just watch - the timer ticks automatically"))
82                            .child(View::text("• No button presses needed for updates"))
83                            .child(View::gap(1))
84                            .child(View::styled_text("Next up").bold().build())
85                            .child(View::text("→ 05_todo_list: text input and list management"))
86                            .child(View::gap(1))
87                            .child(View::styled_text("Press Escape to close").dim().build())
88                            .build(),
89                    )
90                    .build(),
91            )
92            .build()
93    }
examples/09_syntax_comparison.rs (line 46)
24    fn render(&self, cx: Scope) -> View {
25        let use_jsx = state!(cx, || false);
26        let show_help = state!(cx, || false);
27
28        // F1 toggles help
29        cx.use_command(
30            KeyBinding::key(KeyCode::F(1)),
31            with!(show_help => move || show_help.update(|v| *v = !*v)),
32        );
33
34        let toggle = with!(use_jsx => move || use_jsx.set(!use_jsx.get()));
35
36        // Show which syntax is currently displayed
37        let syntax_name = if use_jsx.get() {
38            "view! macro (JSX-like)"
39        } else {
40            "Builder pattern"
41        };
42
43        View::vstack()
44            .child(
45                View::styled_text("Syntax Comparison")
46                    .color(Color::Cyan)
47                    .bold()
48                    .build(),
49            )
50            .child(
51                View::styled_text("Same UI, two ways to write it")
52                    .dim()
53                    .build(),
54            )
55            .child(View::gap(1))
56            .child(
57                View::hstack()
58                    .child(View::text("Current syntax: "))
59                    .child(
60                        View::styled_text(syntax_name)
61                            .color(Color::Yellow)
62                            .bold()
63                            .build(),
64                    )
65                    .build(),
66            )
67            .child(View::gap(1))
68            .child(
69                View::boxed()
70                    .border(true)
71                    .padding(1)
72                    .child(if use_jsx.get() {
73                        counter_jsx(cx.clone())
74                    } else {
75                        counter_builder(cx.clone())
76                    })
77                    .build(),
78            )
79            .child(View::gap(1))
80            .child(
81                View::button()
82                    .label("Toggle Syntax")
83                    .on_press(toggle)
84                    .build(),
85            )
86            .child(View::gap(1))
87            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
88            .child(
89                View::modal()
90                    .visible(show_help.get())
91                    .title("Example 09: Syntax Comparison")
92                    .on_dismiss(with!(show_help => move || show_help.set(false)))
93                    .child(
94                        View::vstack()
95                            .child(View::styled_text("What you're seeing").bold().build())
96                            .child(View::text("• Two syntaxes that produce identical output"))
97                            .child(View::text("• Builder: View::vstack().child(...).build()"))
98                            .child(View::text("• Macro: view! { <VStack>...</VStack> }"))
99                            .child(View::gap(1))
100                            .child(View::styled_text("Key concepts").bold().build())
101                            .child(View::text("• Builder is Rust-native, IDE-friendly"))
102                            .child(View::text("• view! macro is JSX-like, less boilerplate"))
103                            .child(View::text("• Choose based on your preference"))
104                            .child(View::gap(1))
105                            .child(View::styled_text("Try this").bold().build())
106                            .child(View::text("• Toggle between syntaxes"))
107                            .child(View::text("• Notice the output is identical"))
108                            .child(View::text("• Check the source code to see both styles"))
109                            .child(View::gap(1))
110                            .child(View::styled_text("Next up").bold().build())
111                            .child(View::text("→ 10_state_explained: deep dive into state"))
112                            .child(View::gap(1))
113                            .child(View::styled_text("Press Escape to close").dim().build())
114                            .build(),
115                    )
116                    .build(),
117            )
118            .build()
119    }
120}
121
122// =============================================================================
123// Builder Pattern
124// =============================================================================
125// Rust-native, explicit, IDE-friendly. Each method call is clear.
126// Good for: Complex conditional logic, learning the API, debugging.
127
128fn counter_builder(cx: Scope) -> View {
129    let count = state!(cx, || 0i32);
130
131    // with! macro clones the handle for you - much cleaner!
132    let increment = with!(count => move || count.update(|n| *n += 1));
133    let decrement = with!(count => move || count.update(|n| *n -= 1));
134
135    View::vstack()
136        .child(
137            View::styled_text("// Built with builder pattern")
138                .color(Color::DarkGrey)
139                .build(),
140        )
141        .child(View::gap(1))
142        .child(
143            View::styled_text(format!("Count: {}", count.get()))
144                .bold()
145                .build(),
146        )
147        .child(View::gap(1))
148        .child(
149            View::hstack()
150                .child(View::button().label(" - ").on_press(decrement).build())
151                .child(View::text(" "))
152                .child(View::button().label(" + ").on_press(increment).build())
153                .build(),
154        )
155        .build()
156}
examples/35_slider.rs (line 75)
21    fn render(&self, cx: Scope) -> View {
22        let show_help = state!(cx, || false);
23
24        cx.use_command(
25            KeyBinding::key(KeyCode::F(1)),
26            with!(show_help => move || show_help.update(|v| *v = !*v)),
27        );
28
29        let r = state!(cx, || 128.0);
30        let g = state!(cx, || 0.0);
31        let b = state!(cx, || 255.0);
32
33        let rv = r.get() as u8;
34        let gv = g.get() as u8;
35        let bv = b.get() as u8;
36
37        View::vstack()
38            .spacing(1)
39            .child(View::styled_text("RGB Color Mixer").bold().build())
40            .child(
41                View::slider()
42                    .min(0.0)
43                    .max(255.0)
44                    .step(1.0)
45                    .value(r.get())
46                    .label(&format!("Red:   {:>3}", rv))
47                    .color(Color::Rgb { r: 255, g: 80, b: 80 })
48                    .on_change(with!(r => move |v: f64| r.set(v)))
49                    .build(),
50            )
51            .child(
52                View::slider()
53                    .min(0.0)
54                    .max(255.0)
55                    .step(1.0)
56                    .value(g.get())
57                    .label(&format!("Green: {:>3}", gv))
58                    .color(Color::Rgb { r: 80, g: 255, b: 80 })
59                    .on_change(with!(g => move |v: f64| g.set(v)))
60                    .build(),
61            )
62            .child(
63                View::slider()
64                    .min(0.0)
65                    .max(255.0)
66                    .step(1.0)
67                    .value(b.get())
68                    .label(&format!("Blue:  {:>3}", bv))
69                    .color(Color::Rgb { r: 80, g: 80, b: 255 })
70                    .on_change(with!(b => move |v: f64| b.set(v)))
71                    .build(),
72            )
73            .child(
74                View::styled_text("████████████████")
75                    .color(Color::Rgb { r: rv, g: gv, b: bv })
76                    .bold()
77                    .build(),
78            )
79            .child(View::styled_text(format!("#{:02X}{:02X}{:02X}", rv, gv, bv)).bold().build())
80            .child(View::styled_text("Tab: switch slider • Left/Right: adjust • F1: help • Ctrl+Q: quit").dim().build())
81            .child(
82                View::modal()
83                    .visible(show_help.get())
84                    .title("Example 35: Slider")
85                    .on_dismiss(with!(show_help => move || show_help.set(false)))
86                    .child(
87                        View::vstack()
88                            .child(View::styled_text("What you're seeing").bold().build())
89                            .child(View::text("• Three sliders for R, G, B"))
90                            .child(View::text("• Color preview swatch"))
91                            .child(View::text("• Live hex code"))
92                            .child(View::gap(1))
93                            .child(View::styled_text("Key concepts").bold().build())
94                            .child(View::text("• View::slider() with min/max/step"))
95                            .child(View::text("• on_change callback with f64"))
96                            .child(View::text("• Color::Rgb for true color"))
97                            .child(View::gap(1))
98                            .child(View::styled_text("Try this").bold().build())
99                            .child(View::text("• Tab between sliders"))
100                            .child(View::text("• Left/Right arrows to adjust"))
101                            .child(View::text("• Watch the preview change"))
102                            .child(View::gap(1))
103                            .child(View::styled_text("Next up").bold().build())
104                            .child(View::text("-> 36_reducer: state machine wizard"))
105                            .child(View::gap(1))
106                            .child(View::styled_text("Press Escape to close").dim().build())
107                            .build(),
108                    )
109                    .build(),
110            )
111            .build()
112    }
examples/15_markdown.rs (line 68)
54    fn render(&self, cx: Scope) -> View {
55        let show_help = state!(cx, || false);
56
57        // F1 toggles help
58        cx.use_command(
59            KeyBinding::key(KeyCode::F(1)),
60            with!(show_help => move || show_help.update(|v| *v = !*v)),
61        );
62
63        let rendered = telex::markdown::render(DEMO_MARKDOWN);
64
65        View::vstack()
66            .child(
67                View::styled_text("Markdown Rendering Demo")
68                    .color(Color::Cyan)
69                    .bold()
70                    .build(),
71            )
72            .child(
73                View::boxed()
74                    .flex(1)
75                    .child(
76                        View::split()
77                            .horizontal()
78                            .ratio(0.4)
79                            .first(
80                                View::vstack()
81                                    .child(View::styled_text(" Source ").bold().build())
82                                    .child(
83                                        View::boxed()
84                                            .flex(1)
85                                            .border(true)
86                                            .scroll(true)
87                                            .child(View::text(DEMO_MARKDOWN))
88                                            .build(),
89                                    )
90                                    .build(),
91                            )
92                            .second(
93                                View::vstack()
94                                    .child(View::styled_text(" Rendered ").bold().build())
95                                    .child(
96                                        View::boxed()
97                                            .flex(1)
98                                            .border(true)
99                                            .scroll(true)
100                                            .child(rendered)
101                                            .build(),
102                                    )
103                                    .build(),
104                            )
105                            .build(),
106                    )
107                    .build(),
108            )
109            .child(
110                View::styled_text("Tab: switch panes | ↑↓/jk: scroll | F1 help | Ctrl+Q: quit")
111                    .dim()
112                    .build(),
113            )
114            .child(
115                View::modal()
116                    .visible(show_help.get())
117                    .title("Example 15: Markdown")
118                    .on_dismiss(with!(show_help => move || show_help.set(false)))
119                    .child(
120                        View::vstack()
121                            .child(View::styled_text("What you're seeing").bold().build())
122                            .child(View::text("• Side-by-side markdown source and rendered"))
123                            .child(View::text("• Full markdown syntax support"))
124                            .child(View::text("• Scrollable panes for long content"))
125                            .child(View::gap(1))
126                            .child(View::styled_text("Key concepts").bold().build())
127                            .child(View::text("• telex::markdown::render() parses markdown"))
128                            .child(View::text("• Returns a View tree with styled text"))
129                            .child(View::text("• Code blocks, lists, quotes, headers"))
130                            .child(View::text("• Split view for comparison"))
131                            .child(View::gap(1))
132                            .child(View::styled_text("Try this").bold().build())
133                            .child(View::text("• Tab between source and rendered panes"))
134                            .child(View::text("• Scroll with arrow keys or j/k"))
135                            .child(View::text("• Compare source with rendered output"))
136                            .child(View::gap(1))
137                            .child(View::styled_text("Next up").bold().build())
138                            .child(View::text("→ 16_progress: progress bars"))
139                            .child(View::gap(1))
140                            .child(View::styled_text("Press Escape to close").dim().build())
141                            .build(),
142                    )
143                    .build(),
144            )
145            .build()
146    }
examples/16_tree.rs (line 67)
20    fn render(&self, cx: Scope) -> View {
21        let show_help = state!(cx, || false);
22
23        // F1 toggles help
24        cx.use_command(
25            KeyBinding::key(KeyCode::F(1)),
26            with!(show_help => move || show_help.update(|v| *v = !*v)),
27        );
28
29        // Track selected path
30        let selected = state!(cx, || vec![0usize]);
31
32        // Track expanded state for each node (by path prefix)
33        let expanded_paths = state!(cx, || {
34            vec![
35                vec![0],    // src/ expanded
36                vec![0, 0], // src/components/ expanded
37            ]
38        });
39
40        // Build tree items with current expanded state
41        let items = build_tree(&expanded_paths.get());
42
43        let on_select = with!(selected => move |path: TreePath| {
44            selected.set(path);
45        });
46
47        let on_activate = with!(expanded_paths => move |path: TreePath| {
48            // Toggle expand/collapse for the activated item
49            let mut paths = expanded_paths.get().clone();
50            if let Some(pos) = paths.iter().position(|p| *p == path) {
51                // Currently expanded, collapse it
52                paths.remove(pos);
53            } else {
54                // Currently collapsed, expand it
55                paths.push(path.clone());
56            }
57            expanded_paths.set(paths);
58        });
59
60        let selected_label = get_item_at_path(&items, &selected.get())
61            .map(|item| item.label.clone())
62            .unwrap_or_else(|| "Nothing".to_string());
63
64        View::vstack()
65            .child(
66                View::styled_text("File Browser")
67                    .color(Color::Cyan)
68                    .bold()
69                    .build(),
70            )
71            .child(
72                View::styled_text(format!("Selected: {}", selected_label))
73                    .dim()
74                    .build(),
75            )
76            .child(
77                View::boxed()
78                    .flex(1)
79                    .border(true)
80                    .child(
81                        View::tree()
82                            .items(items)
83                            .selected(selected.get().clone())
84                            .on_select(on_select)
85                            .on_activate(on_activate)
86                            .build(),
87                    )
88                    .build(),
89            )
90            .child(
91                View::styled_text(
92                    "↑↓/jk: navigate | Enter: expand/collapse | F1 help | Ctrl+Q: quit",
93                )
94                .dim()
95                .build(),
96            )
97            .child(
98                View::modal()
99                    .visible(show_help.get())
100                    .title("Example 16: Tree View")
101                    .on_dismiss(with!(show_help => move || show_help.set(false)))
102                    .child(
103                        View::vstack()
104                            .child(View::styled_text("What you're seeing").bold().build())
105                            .child(View::text("• Hierarchical tree widget"))
106                            .child(View::text("• Expand/collapse folders"))
107                            .child(View::text("• Path-based selection tracking"))
108                            .child(View::gap(1))
109                            .child(View::styled_text("Key concepts").bold().build())
110                            .child(View::text("• View::tree() for hierarchical data"))
111                            .child(View::text("• TreeItem::new().child() builds hierarchy"))
112                            .child(View::text("• on_select returns TreePath (Vec<usize>)"))
113                            .child(View::text("• on_activate for expand/collapse"))
114                            .child(View::gap(1))
115                            .child(View::styled_text("Try this").bold().build())
116                            .child(View::text("• Navigate with arrow keys"))
117                            .child(View::text("• Press Enter to expand/collapse folders"))
118                            .child(View::text("• Watch the 'Selected:' text update"))
119                            .child(View::gap(1))
120                            .child(View::styled_text("Next up").bold().build())
121                            .child(View::text("→ 17_table: data tables with sorting"))
122                            .child(View::gap(1))
123                            .child(View::styled_text("Press Escape to close").dim().build())
124                            .build(),
125                    )
126                    .build(),
127            )
128            .build()
129    }
Source

pub fn bg(self, color: Color) -> Self

Set the background color.

Source

pub fn bold(self) -> Self

Make the text bold.

Examples found in repository?
examples/01_hello_world.rs (line 29)
19    fn render(&self, cx: Scope) -> View {
20        let show_help = state!(cx, || false);
21
22        // F1 toggles help
23        cx.use_command(
24            KeyBinding::key(KeyCode::F(1)),
25            with!(show_help => move || show_help.update(|v| *v = !*v)),
26        );
27
28        View::vstack()
29            .child(View::styled_text("Hello World").bold().build())
30            .child(View::gap(1))
31            .child(View::text("Welcome to Telex!"))
32            .child(View::gap(1))
33            .child(
34                View::styled_text("F1 for help • Ctrl+Q to quit")
35                    .dim()
36                    .build(),
37            )
38            .child(
39                View::modal()
40                    .visible(show_help.get())
41                    .title("Example 01: Hello World")
42                    .on_dismiss(with!(show_help => move || show_help.set(false)))
43                    .child(
44                        View::vstack()
45                            .child(View::styled_text("What you're seeing").bold().build())
46                            .child(View::text(
47                                "• Basic app structure with struct + Component trait",
48                            ))
49                            .child(View::text(
50                                "• View::text() and View::styled_text() for display",
51                            ))
52                            .child(View::text("• View::vstack() for vertical layout"))
53                            .child(View::gap(1))
54                            .child(View::styled_text("Key concepts").bold().build())
55                            .child(View::text("• Every Telex app implements Component"))
56                            .child(View::text("• render() returns a View tree"))
57                            .child(View::text("• No state yet - this is purely static"))
58                            .child(View::gap(1))
59                            .child(View::styled_text("Next up").bold().build())
60                            .child(View::text("→ 02_counter: add state and interactivity"))
61                            .child(View::gap(1))
62                            .child(View::styled_text("Press Escape to close").dim().build())
63                            .build(),
64                    )
65                    .build(),
66            )
67            .build()
68    }
More examples
Hide additional examples
examples/30_image.rs (line 42)
30    fn render(&self, cx: Scope) -> View {
31        let show_help = state!(cx, || false);
32
33        // F1 toggles help
34        cx.use_command(
35            KeyBinding::key(KeyCode::F(1)),
36            with!(show_help => move || show_help.update(|v| *v = !*v)),
37        );
38        View::vstack()
39            .spacing(1)
40            .child(
41                View::styled_text("Image Widget Demo (Kitty Graphics)")
42                    .bold()
43                    .build(),
44            )
45            .child(View::text("Requires Kitty, Ghostty, or WezTerm terminal"))
46            .child(View::text(""))
47            // Load image from file path
48            .child(View::text("Logo (from file path):"))
49            .child(View::image().file("assets/telex-tui.png").build())
50            .child(View::text(""))
51            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
52            .child(
53                View::modal()
54                    .visible(show_help.get())
55                    .title("Example 30: Image")
56                    .on_dismiss(with!(show_help => move || show_help.set(false)))
57                    .child(
58                        View::vstack()
59                            .child(View::styled_text("What you're seeing").bold().build())
60                            .child(View::text("• Image display via Kitty protocol"))
61                            .child(View::text("• PNG/JPEG/GIF support"))
62                            .child(View::text("• Loaded from file path"))
63                            .child(View::gap(1))
64                            .child(View::styled_text("Key concepts").bold().build())
65                            .child(View::text("• View::image() displays images"))
66                            .child(View::text("• .file(\"path\") loads from disk"))
67                            .child(View::text("• .bytes(data) for embedded images"))
68                            .child(View::text("• Works in Kitty/Ghostty/WezTerm"))
69                            .child(View::gap(1))
70                            .child(View::styled_text("Try this").bold().build())
71                            .child(View::text("• Run in compatible terminal"))
72                            .child(View::text("• See the Telex logo rendered"))
73                            .child(View::gap(1))
74                            .child(View::styled_text("Next up").bold().build())
75                            .child(View::text("→ 31_animated_canvas: animations"))
76                            .child(View::gap(1))
77                            .child(View::styled_text("Press Escape to close").dim().build())
78                            .build(),
79                    )
80                    .build(),
81            )
82            .build()
83    }
examples/04_timer.rs (line 49)
22    fn render(&self, cx: Scope) -> View {
23        let show_help = state!(cx, || false);
24
25        // F1 toggles help
26        cx.use_command(
27            KeyBinding::key(KeyCode::F(1)),
28            with!(show_help => move || show_help.update(|v| *v = !*v)),
29        );
30
31        // Stream that yields elapsed seconds
32        let elapsed = stream!(cx, || {
33            (0u64..).inspect(|&s| {
34                if s > 0 {
35                    std::thread::sleep(Duration::from_secs(1));
36                }
37            })
38        });
39
40        let seconds = elapsed.get();
41        let is_running = elapsed.is_loading();
42
43        // Format as MM:SS
44        let minutes = seconds / 60;
45        let secs = seconds % 60;
46        let time_display = format!("{:02}:{:02}", minutes, secs);
47
48        View::vstack()
49            .child(View::styled_text("Timer").color(Color::Cyan).bold().build())
50            .child(View::gap(1))
51            .child(
52                View::hstack()
53                    .child(View::styled_text(&time_display).bold().build())
54                    .child(if is_running {
55                        View::styled_text(" ●").color(Color::Green).build()
56                    } else {
57                        View::styled_text(" ○").dim().build()
58                    })
59                    .build(),
60            )
61            .child(View::gap(1))
62            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
63            .child(
64                View::modal()
65                    .visible(show_help.get())
66                    .title("Example 04: Timer")
67                    .on_dismiss(with!(show_help => move || show_help.set(false)))
68                    .child(
69                        View::vstack()
70                            .child(View::styled_text("What you're seeing").bold().build())
71                            .child(View::text("• stream!() macro for background data"))
72                            .child(View::text("• Auto-updating UI without user input"))
73                            .child(View::text("• Green dot = stream is running"))
74                            .child(View::gap(1))
75                            .child(View::styled_text("Key concepts").bold().build())
76                            .child(View::text("• Streams run in background threads"))
77                            .child(View::text("• Each yielded value triggers a re-render"))
78                            .child(View::text("• is_loading() tells you if stream is active"))
79                            .child(View::gap(1))
80                            .child(View::styled_text("Try this").bold().build())
81                            .child(View::text("• Just watch - the timer ticks automatically"))
82                            .child(View::text("• No button presses needed for updates"))
83                            .child(View::gap(1))
84                            .child(View::styled_text("Next up").bold().build())
85                            .child(View::text("→ 05_todo_list: text input and list management"))
86                            .child(View::gap(1))
87                            .child(View::styled_text("Press Escape to close").dim().build())
88                            .build(),
89                    )
90                    .build(),
91            )
92            .build()
93    }
examples/02_counter.rs (line 33)
19    fn render(&self, cx: Scope) -> View {
20        let count = state!(cx, || 0i32);
21        let show_help = state!(cx, || false);
22
23        let increment = with!(count => move || count.update(|n| *n += 1));
24        let decrement = with!(count => move || count.update(|n| *n -= 1));
25
26        // F1 toggles help
27        cx.use_command(
28            KeyBinding::key(KeyCode::F(1)),
29            with!(show_help => move || show_help.update(|v| *v = !*v)),
30        );
31
32        View::vstack()
33            .child(View::styled_text("Counter").bold().build())
34            .child(View::gap(1))
35            .child(View::text(format!("Count: {}", count.get())))
36            .child(View::gap(1))
37            .child(
38                View::hstack()
39                    .child(
40                        View::button()
41                            .label("Decrement")
42                            .on_press(decrement)
43                            .build(),
44                    )
45                    .child(View::text(" "))
46                    .child(
47                        View::button()
48                            .label("Increment")
49                            .on_press(increment)
50                            .build(),
51                    )
52                    .build(),
53            )
54            .child(View::gap(1))
55            .child(
56                View::styled_text("Tab to switch • Enter to press • F1 for help • Ctrl+Q to quit")
57                    .dim()
58                    .build(),
59            )
60            .child(
61                View::modal()
62                    .visible(show_help.get())
63                    .title("Example 02: Counter")
64                    .on_dismiss(with!(show_help => move || show_help.set(false)))
65                    .child(
66                        View::vstack()
67                            .child(View::styled_text("What you're seeing").bold().build())
68                            .child(View::text("• state!() macro for reactive state"))
69                            .child(View::text("• View::button() with on_press callbacks"))
70                            .child(View::text(
71                                "• The with!() macro for capturing state in closures",
72                            ))
73                            .child(View::gap(1))
74                            .child(View::styled_text("Key concepts").bold().build())
75                            .child(View::text("• State persists across renders"))
76                            .child(View::text("• Updating state triggers a re-render"))
77                            .child(View::text("• Tab navigates between focusable elements"))
78                            .child(View::gap(1))
79                            .child(View::styled_text("Try this").bold().build())
80                            .child(View::text("• Press +/- rapidly - notice instant updates"))
81                            .child(View::text(
82                                "• The UI stays in sync with state automatically",
83                            ))
84                            .child(View::gap(1))
85                            .child(View::styled_text("Next up").bold().build())
86                            .child(View::text("→ 03_theme_switcher: styling and colors"))
87                            .child(View::gap(1))
88                            .child(View::styled_text("Press Escape to close").dim().build())
89                            .build(),
90                    )
91                    .build(),
92            )
93            .build()
94    }
examples/19_status_bar.rs (line 33)
24    fn render(&self, cx: Scope) -> View {
25        let show_help = state!(cx, || false);
26
27        // F1 toggles help
28        cx.use_command(
29            KeyBinding::key(KeyCode::F(1)),
30            with!(show_help => move || show_help.update(|v| *v = !*v)),
31        );
32        View::vstack()
33            .child(View::styled_text("Status Bar Examples").bold().build())
34            .child(View::text(""))
35            .child(View::text("Basic status bar (left only):"))
36            .child(View::status_bar().left("NORMAL").build())
37            .child(View::text(""))
38            .child(View::text("Left and right sections:"))
39            .child(
40                View::status_bar()
41                    .left("INSERT")
42                    .right("Ln 42, Col 8")
43                    .build(),
44            )
45            .child(View::text(""))
46            .child(View::text("All three sections:"))
47            .child(
48                View::status_bar()
49                    .left("VISUAL")
50                    .center("main.rs")
51                    .right("UTF-8 | LF | Rust")
52                    .build(),
53            )
54            .child(View::text(""))
55            .child(View::text("Custom colors (green on dark):"))
56            .child(
57                View::status_bar()
58                    .left("SUCCESS")
59                    .center("All tests passed")
60                    .right("100%")
61                    .fg(Color::Green)
62                    .bg(Color::DarkGreen)
63                    .build(),
64            )
65            .child(View::text(""))
66            .child(View::text("Editor-style status bar:"))
67            .child(
68                View::status_bar()
69                    .left("-- INSERT --")
70                    .center("~/projects/myapp/src/main.rs [+]")
71                    .right("1/100 | 50%")
72                    .build(),
73            )
74            .child(View::spacer())
75            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
76            .child(
77                View::modal()
78                    .visible(show_help.get())
79                    .title("Example 19: Status Bar")
80                    .on_dismiss(with!(show_help => move || show_help.set(false)))
81                    .child(
82                        View::vstack()
83                            .child(View::styled_text("What you're seeing").bold().build())
84                            .child(View::text("• Status bars with left/center/right sections"))
85                            .child(View::text("• Custom foreground and background colors"))
86                            .child(View::text("• Editor-style status line example"))
87                            .child(View::gap(1))
88                            .child(View::styled_text("Key concepts").bold().build())
89                            .child(View::text("• View::status_bar() creates status lines"))
90                            .child(View::text("• .left(), .center(), .right() for sections"))
91                            .child(View::text("• .fg() and .bg() for custom colors"))
92                            .child(View::text("• Great for showing mode, file info, etc."))
93                            .child(View::gap(1))
94                            .child(View::styled_text("Try this").bold().build())
95                            .child(View::text("• Compare different status bar styles"))
96                            .child(View::text("• Notice how sections align"))
97                            .child(View::gap(1))
98                            .child(View::styled_text("Next up").bold().build())
99                            .child(View::text("→ 20_menu_bar: dropdown menus"))
100                            .child(View::gap(1))
101                            .child(View::styled_text("Press Escape to close").dim().build())
102                            .build(),
103                    )
104                    .build(),
105            )
106            .build()
107    }
examples/09_syntax_comparison.rs (line 47)
24    fn render(&self, cx: Scope) -> View {
25        let use_jsx = state!(cx, || false);
26        let show_help = state!(cx, || false);
27
28        // F1 toggles help
29        cx.use_command(
30            KeyBinding::key(KeyCode::F(1)),
31            with!(show_help => move || show_help.update(|v| *v = !*v)),
32        );
33
34        let toggle = with!(use_jsx => move || use_jsx.set(!use_jsx.get()));
35
36        // Show which syntax is currently displayed
37        let syntax_name = if use_jsx.get() {
38            "view! macro (JSX-like)"
39        } else {
40            "Builder pattern"
41        };
42
43        View::vstack()
44            .child(
45                View::styled_text("Syntax Comparison")
46                    .color(Color::Cyan)
47                    .bold()
48                    .build(),
49            )
50            .child(
51                View::styled_text("Same UI, two ways to write it")
52                    .dim()
53                    .build(),
54            )
55            .child(View::gap(1))
56            .child(
57                View::hstack()
58                    .child(View::text("Current syntax: "))
59                    .child(
60                        View::styled_text(syntax_name)
61                            .color(Color::Yellow)
62                            .bold()
63                            .build(),
64                    )
65                    .build(),
66            )
67            .child(View::gap(1))
68            .child(
69                View::boxed()
70                    .border(true)
71                    .padding(1)
72                    .child(if use_jsx.get() {
73                        counter_jsx(cx.clone())
74                    } else {
75                        counter_builder(cx.clone())
76                    })
77                    .build(),
78            )
79            .child(View::gap(1))
80            .child(
81                View::button()
82                    .label("Toggle Syntax")
83                    .on_press(toggle)
84                    .build(),
85            )
86            .child(View::gap(1))
87            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
88            .child(
89                View::modal()
90                    .visible(show_help.get())
91                    .title("Example 09: Syntax Comparison")
92                    .on_dismiss(with!(show_help => move || show_help.set(false)))
93                    .child(
94                        View::vstack()
95                            .child(View::styled_text("What you're seeing").bold().build())
96                            .child(View::text("• Two syntaxes that produce identical output"))
97                            .child(View::text("• Builder: View::vstack().child(...).build()"))
98                            .child(View::text("• Macro: view! { <VStack>...</VStack> }"))
99                            .child(View::gap(1))
100                            .child(View::styled_text("Key concepts").bold().build())
101                            .child(View::text("• Builder is Rust-native, IDE-friendly"))
102                            .child(View::text("• view! macro is JSX-like, less boilerplate"))
103                            .child(View::text("• Choose based on your preference"))
104                            .child(View::gap(1))
105                            .child(View::styled_text("Try this").bold().build())
106                            .child(View::text("• Toggle between syntaxes"))
107                            .child(View::text("• Notice the output is identical"))
108                            .child(View::text("• Check the source code to see both styles"))
109                            .child(View::gap(1))
110                            .child(View::styled_text("Next up").bold().build())
111                            .child(View::text("→ 10_state_explained: deep dive into state"))
112                            .child(View::gap(1))
113                            .child(View::styled_text("Press Escape to close").dim().build())
114                            .build(),
115                    )
116                    .build(),
117            )
118            .build()
119    }
120}
121
122// =============================================================================
123// Builder Pattern
124// =============================================================================
125// Rust-native, explicit, IDE-friendly. Each method call is clear.
126// Good for: Complex conditional logic, learning the API, debugging.
127
128fn counter_builder(cx: Scope) -> View {
129    let count = state!(cx, || 0i32);
130
131    // with! macro clones the handle for you - much cleaner!
132    let increment = with!(count => move || count.update(|n| *n += 1));
133    let decrement = with!(count => move || count.update(|n| *n -= 1));
134
135    View::vstack()
136        .child(
137            View::styled_text("// Built with builder pattern")
138                .color(Color::DarkGrey)
139                .build(),
140        )
141        .child(View::gap(1))
142        .child(
143            View::styled_text(format!("Count: {}", count.get()))
144                .bold()
145                .build(),
146        )
147        .child(View::gap(1))
148        .child(
149            View::hstack()
150                .child(View::button().label(" - ").on_press(decrement).build())
151                .child(View::text(" "))
152                .child(View::button().label(" + ").on_press(increment).build())
153                .build(),
154        )
155        .build()
156}
Source

pub fn italic(self) -> Self

Make the text italic.

Examples found in repository?
examples/03_theme_switcher.rs (line 102)
20    fn render(&self, cx: Scope) -> View {
21        let selected = state!(cx, || 0usize);
22        let show_help = state!(cx, || false);
23
24        // F1 toggles help
25        cx.use_command(
26            KeyBinding::key(KeyCode::F(1)),
27            with!(show_help => move || show_help.update(|v| *v = !*v)),
28        );
29
30        let theme_names = vec![
31            "Dark".to_string(),
32            "Light".to_string(),
33            "Nord".to_string(),
34            "Monokai".to_string(),
35            "Catppuccin Mocha".to_string(),
36            "Catppuccin Latte".to_string(),
37            "Dracula".to_string(),
38            "Gruvbox Dark".to_string(),
39            "Solarized Dark".to_string(),
40            "Rosé Pine".to_string(),
41            "Tokyo Night".to_string(),
42            "HaX0R Blue".to_string(),
43            "HaX0R Green".to_string(),
44            "HaX0R Red".to_string(),
45        ];
46
47        // Apply theme when selection changes
48        let on_select = with!(selected => move |idx: usize| {
49            selected.set(idx);
50            let theme = match idx {
51                0 => Theme::dark(),
52                1 => Theme::light(),
53                2 => Theme::nord(),
54                3 => Theme::monokai(),
55                4 => Theme::catppuccin_mocha(),
56                5 => Theme::catppuccin_latte(),
57                6 => Theme::dracula(),
58                7 => Theme::gruvbox_dark(),
59                8 => Theme::solarized_dark(),
60                9 => Theme::rose_pine(),
61                10 => Theme::tokyo_night(),
62                11 => Theme::hax0r_blue(),
63                12 => Theme::hax0r_green(),
64                _ => Theme::hax0r_red(),
65            };
66            set_theme(theme);
67        });
68
69        let theme = current_theme();
70        let true_color = supports_true_color();
71
72        let mut stack = View::vstack();
73
74        // Show warning if true color isn't supported
75        if !true_color {
76            let term = terminal_name().unwrap_or_else(|| "Unknown".to_string());
77            stack = stack
78                .child(
79                    View::styled_text(format!("Warning: {} doesn't support true color", term))
80                        .color(theme.warning)
81                        .bold()
82                        .build(),
83                )
84                .child(
85                    View::styled_text("Only 'Dark' and 'Light' themes will display correctly")
86                        .color(theme.muted)
87                        .build(),
88                )
89                .child(View::gap(1));
90        }
91
92        stack
93            .child(
94                View::styled_text("Theme Switcher")
95                    .color(theme.primary)
96                    .bold()
97                    .build(),
98            )
99            .child(
100                View::styled_text("Select a theme from the list")
101                    .color(theme.muted)
102                    .italic()
103                    .build(),
104            )
105            .child(View::gap(1))
106            .child(
107                View::hstack()
108                    .spacing(2)
109                    .child(
110                        View::boxed()
111                            .border(true)
112                            .min_width(25)
113                            .child(
114                                View::list()
115                                    .items(theme_names)
116                                    .selected(selected.get())
117                                    .on_select(on_select)
118                                    .build(),
119                            )
120                            .build(),
121                    )
122                    .child(
123                        View::boxed()
124                            .border(true)
125                            .padding(1)
126                            .child(
127                                View::vstack()
128                                    .child(View::styled_text("Preview").bold().build())
129                                    .child(View::gap(1))
130                                    .child(
131                                        View::hstack()
132                                            .child(
133                                                View::styled_text("Primary")
134                                                    .color(theme.primary)
135                                                    .build(),
136                                            )
137                                            .child(View::text("  "))
138                                            .child(
139                                                View::styled_text("Secondary")
140                                                    .color(theme.secondary)
141                                                    .build(),
142                                            )
143                                            .build(),
144                                    )
145                                    .child(
146                                        View::hstack()
147                                            .child(
148                                                View::styled_text("Muted")
149                                                    .color(theme.muted)
150                                                    .build(),
151                                            )
152                                            .child(View::text("  "))
153                                            .child(
154                                                View::styled_text("Success")
155                                                    .color(theme.success)
156                                                    .build(),
157                                            )
158                                            .build(),
159                                    )
160                                    .child(
161                                        View::hstack()
162                                            .child(
163                                                View::styled_text("Warning")
164                                                    .color(theme.warning)
165                                                    .build(),
166                                            )
167                                            .child(View::text("  "))
168                                            .child(
169                                                View::styled_text("Error")
170                                                    .color(theme.error)
171                                                    .build(),
172                                            )
173                                            .build(),
174                                    )
175                                    .build(),
176                            )
177                            .build(),
178                    )
179                    .build(),
180            )
181            .child(View::gap(1))
182            .child(
183                View::styled_text("↑/↓ select • F1 help • Ctrl+Q quit")
184                    .color(theme.muted)
185                    .build(),
186            )
187            .child(
188                View::modal()
189                    .visible(show_help.get())
190                    .title("Example 03: Theme Switcher")
191                    .on_dismiss(with!(show_help => move || show_help.set(false)))
192                    .child(
193                        View::vstack()
194                            .child(View::styled_text("What you're seeing").bold().build())
195                            .child(View::text("• Built-in theme system with 14 themes"))
196                            .child(View::text("• View::list() for selection UI"))
197                            .child(View::text("• Live preview as you navigate"))
198                            .child(View::gap(1))
199                            .child(View::styled_text("Key concepts").bold().build())
200                            .child(View::text("• current_theme() gets active theme colors"))
201                            .child(View::text("• set_theme() changes theme globally"))
202                            .child(View::text(
203                                "• Themes provide semantic colors (primary, error, etc.)",
204                            ))
205                            .child(View::gap(1))
206                            .child(View::styled_text("Try this").bold().build())
207                            .child(View::text(
208                                "• Navigate with ↑/↓ to see themes change instantly",
209                            ))
210                            .child(View::text(
211                                "• Notice the preview panel updates with theme colors",
212                            ))
213                            .child(View::gap(1))
214                            .child(View::styled_text("Next up").bold().build())
215                            .child(View::text("→ 04_timer: streaming data without interaction"))
216                            .child(View::gap(1))
217                            .child(View::styled_text("Press Escape to close").dim().build())
218                            .build(),
219                    )
220                    .build(),
221            )
222            .build()
223    }
Source

pub fn underline(self) -> Self

Underline the text.

Source

pub fn dim(self) -> Self

Make the text dim/faded.

Examples found in repository?
examples/01_hello_world.rs (line 35)
19    fn render(&self, cx: Scope) -> View {
20        let show_help = state!(cx, || false);
21
22        // F1 toggles help
23        cx.use_command(
24            KeyBinding::key(KeyCode::F(1)),
25            with!(show_help => move || show_help.update(|v| *v = !*v)),
26        );
27
28        View::vstack()
29            .child(View::styled_text("Hello World").bold().build())
30            .child(View::gap(1))
31            .child(View::text("Welcome to Telex!"))
32            .child(View::gap(1))
33            .child(
34                View::styled_text("F1 for help • Ctrl+Q to quit")
35                    .dim()
36                    .build(),
37            )
38            .child(
39                View::modal()
40                    .visible(show_help.get())
41                    .title("Example 01: Hello World")
42                    .on_dismiss(with!(show_help => move || show_help.set(false)))
43                    .child(
44                        View::vstack()
45                            .child(View::styled_text("What you're seeing").bold().build())
46                            .child(View::text(
47                                "• Basic app structure with struct + Component trait",
48                            ))
49                            .child(View::text(
50                                "• View::text() and View::styled_text() for display",
51                            ))
52                            .child(View::text("• View::vstack() for vertical layout"))
53                            .child(View::gap(1))
54                            .child(View::styled_text("Key concepts").bold().build())
55                            .child(View::text("• Every Telex app implements Component"))
56                            .child(View::text("• render() returns a View tree"))
57                            .child(View::text("• No state yet - this is purely static"))
58                            .child(View::gap(1))
59                            .child(View::styled_text("Next up").bold().build())
60                            .child(View::text("→ 02_counter: add state and interactivity"))
61                            .child(View::gap(1))
62                            .child(View::styled_text("Press Escape to close").dim().build())
63                            .build(),
64                    )
65                    .build(),
66            )
67            .build()
68    }
More examples
Hide additional examples
examples/30_image.rs (line 51)
30    fn render(&self, cx: Scope) -> View {
31        let show_help = state!(cx, || false);
32
33        // F1 toggles help
34        cx.use_command(
35            KeyBinding::key(KeyCode::F(1)),
36            with!(show_help => move || show_help.update(|v| *v = !*v)),
37        );
38        View::vstack()
39            .spacing(1)
40            .child(
41                View::styled_text("Image Widget Demo (Kitty Graphics)")
42                    .bold()
43                    .build(),
44            )
45            .child(View::text("Requires Kitty, Ghostty, or WezTerm terminal"))
46            .child(View::text(""))
47            // Load image from file path
48            .child(View::text("Logo (from file path):"))
49            .child(View::image().file("assets/telex-tui.png").build())
50            .child(View::text(""))
51            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
52            .child(
53                View::modal()
54                    .visible(show_help.get())
55                    .title("Example 30: Image")
56                    .on_dismiss(with!(show_help => move || show_help.set(false)))
57                    .child(
58                        View::vstack()
59                            .child(View::styled_text("What you're seeing").bold().build())
60                            .child(View::text("• Image display via Kitty protocol"))
61                            .child(View::text("• PNG/JPEG/GIF support"))
62                            .child(View::text("• Loaded from file path"))
63                            .child(View::gap(1))
64                            .child(View::styled_text("Key concepts").bold().build())
65                            .child(View::text("• View::image() displays images"))
66                            .child(View::text("• .file(\"path\") loads from disk"))
67                            .child(View::text("• .bytes(data) for embedded images"))
68                            .child(View::text("• Works in Kitty/Ghostty/WezTerm"))
69                            .child(View::gap(1))
70                            .child(View::styled_text("Try this").bold().build())
71                            .child(View::text("• Run in compatible terminal"))
72                            .child(View::text("• See the Telex logo rendered"))
73                            .child(View::gap(1))
74                            .child(View::styled_text("Next up").bold().build())
75                            .child(View::text("→ 31_animated_canvas: animations"))
76                            .child(View::gap(1))
77                            .child(View::styled_text("Press Escape to close").dim().build())
78                            .build(),
79                    )
80                    .build(),
81            )
82            .build()
83    }
examples/04_timer.rs (line 57)
22    fn render(&self, cx: Scope) -> View {
23        let show_help = state!(cx, || false);
24
25        // F1 toggles help
26        cx.use_command(
27            KeyBinding::key(KeyCode::F(1)),
28            with!(show_help => move || show_help.update(|v| *v = !*v)),
29        );
30
31        // Stream that yields elapsed seconds
32        let elapsed = stream!(cx, || {
33            (0u64..).inspect(|&s| {
34                if s > 0 {
35                    std::thread::sleep(Duration::from_secs(1));
36                }
37            })
38        });
39
40        let seconds = elapsed.get();
41        let is_running = elapsed.is_loading();
42
43        // Format as MM:SS
44        let minutes = seconds / 60;
45        let secs = seconds % 60;
46        let time_display = format!("{:02}:{:02}", minutes, secs);
47
48        View::vstack()
49            .child(View::styled_text("Timer").color(Color::Cyan).bold().build())
50            .child(View::gap(1))
51            .child(
52                View::hstack()
53                    .child(View::styled_text(&time_display).bold().build())
54                    .child(if is_running {
55                        View::styled_text(" ●").color(Color::Green).build()
56                    } else {
57                        View::styled_text(" ○").dim().build()
58                    })
59                    .build(),
60            )
61            .child(View::gap(1))
62            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
63            .child(
64                View::modal()
65                    .visible(show_help.get())
66                    .title("Example 04: Timer")
67                    .on_dismiss(with!(show_help => move || show_help.set(false)))
68                    .child(
69                        View::vstack()
70                            .child(View::styled_text("What you're seeing").bold().build())
71                            .child(View::text("• stream!() macro for background data"))
72                            .child(View::text("• Auto-updating UI without user input"))
73                            .child(View::text("• Green dot = stream is running"))
74                            .child(View::gap(1))
75                            .child(View::styled_text("Key concepts").bold().build())
76                            .child(View::text("• Streams run in background threads"))
77                            .child(View::text("• Each yielded value triggers a re-render"))
78                            .child(View::text("• is_loading() tells you if stream is active"))
79                            .child(View::gap(1))
80                            .child(View::styled_text("Try this").bold().build())
81                            .child(View::text("• Just watch - the timer ticks automatically"))
82                            .child(View::text("• No button presses needed for updates"))
83                            .child(View::gap(1))
84                            .child(View::styled_text("Next up").bold().build())
85                            .child(View::text("→ 05_todo_list: text input and list management"))
86                            .child(View::gap(1))
87                            .child(View::styled_text("Press Escape to close").dim().build())
88                            .build(),
89                    )
90                    .build(),
91            )
92            .build()
93    }
examples/02_counter.rs (line 57)
19    fn render(&self, cx: Scope) -> View {
20        let count = state!(cx, || 0i32);
21        let show_help = state!(cx, || false);
22
23        let increment = with!(count => move || count.update(|n| *n += 1));
24        let decrement = with!(count => move || count.update(|n| *n -= 1));
25
26        // F1 toggles help
27        cx.use_command(
28            KeyBinding::key(KeyCode::F(1)),
29            with!(show_help => move || show_help.update(|v| *v = !*v)),
30        );
31
32        View::vstack()
33            .child(View::styled_text("Counter").bold().build())
34            .child(View::gap(1))
35            .child(View::text(format!("Count: {}", count.get())))
36            .child(View::gap(1))
37            .child(
38                View::hstack()
39                    .child(
40                        View::button()
41                            .label("Decrement")
42                            .on_press(decrement)
43                            .build(),
44                    )
45                    .child(View::text(" "))
46                    .child(
47                        View::button()
48                            .label("Increment")
49                            .on_press(increment)
50                            .build(),
51                    )
52                    .build(),
53            )
54            .child(View::gap(1))
55            .child(
56                View::styled_text("Tab to switch • Enter to press • F1 for help • Ctrl+Q to quit")
57                    .dim()
58                    .build(),
59            )
60            .child(
61                View::modal()
62                    .visible(show_help.get())
63                    .title("Example 02: Counter")
64                    .on_dismiss(with!(show_help => move || show_help.set(false)))
65                    .child(
66                        View::vstack()
67                            .child(View::styled_text("What you're seeing").bold().build())
68                            .child(View::text("• state!() macro for reactive state"))
69                            .child(View::text("• View::button() with on_press callbacks"))
70                            .child(View::text(
71                                "• The with!() macro for capturing state in closures",
72                            ))
73                            .child(View::gap(1))
74                            .child(View::styled_text("Key concepts").bold().build())
75                            .child(View::text("• State persists across renders"))
76                            .child(View::text("• Updating state triggers a re-render"))
77                            .child(View::text("• Tab navigates between focusable elements"))
78                            .child(View::gap(1))
79                            .child(View::styled_text("Try this").bold().build())
80                            .child(View::text("• Press +/- rapidly - notice instant updates"))
81                            .child(View::text(
82                                "• The UI stays in sync with state automatically",
83                            ))
84                            .child(View::gap(1))
85                            .child(View::styled_text("Next up").bold().build())
86                            .child(View::text("→ 03_theme_switcher: styling and colors"))
87                            .child(View::gap(1))
88                            .child(View::styled_text("Press Escape to close").dim().build())
89                            .build(),
90                    )
91                    .build(),
92            )
93            .build()
94    }
examples/19_status_bar.rs (line 75)
24    fn render(&self, cx: Scope) -> View {
25        let show_help = state!(cx, || false);
26
27        // F1 toggles help
28        cx.use_command(
29            KeyBinding::key(KeyCode::F(1)),
30            with!(show_help => move || show_help.update(|v| *v = !*v)),
31        );
32        View::vstack()
33            .child(View::styled_text("Status Bar Examples").bold().build())
34            .child(View::text(""))
35            .child(View::text("Basic status bar (left only):"))
36            .child(View::status_bar().left("NORMAL").build())
37            .child(View::text(""))
38            .child(View::text("Left and right sections:"))
39            .child(
40                View::status_bar()
41                    .left("INSERT")
42                    .right("Ln 42, Col 8")
43                    .build(),
44            )
45            .child(View::text(""))
46            .child(View::text("All three sections:"))
47            .child(
48                View::status_bar()
49                    .left("VISUAL")
50                    .center("main.rs")
51                    .right("UTF-8 | LF | Rust")
52                    .build(),
53            )
54            .child(View::text(""))
55            .child(View::text("Custom colors (green on dark):"))
56            .child(
57                View::status_bar()
58                    .left("SUCCESS")
59                    .center("All tests passed")
60                    .right("100%")
61                    .fg(Color::Green)
62                    .bg(Color::DarkGreen)
63                    .build(),
64            )
65            .child(View::text(""))
66            .child(View::text("Editor-style status bar:"))
67            .child(
68                View::status_bar()
69                    .left("-- INSERT --")
70                    .center("~/projects/myapp/src/main.rs [+]")
71                    .right("1/100 | 50%")
72                    .build(),
73            )
74            .child(View::spacer())
75            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
76            .child(
77                View::modal()
78                    .visible(show_help.get())
79                    .title("Example 19: Status Bar")
80                    .on_dismiss(with!(show_help => move || show_help.set(false)))
81                    .child(
82                        View::vstack()
83                            .child(View::styled_text("What you're seeing").bold().build())
84                            .child(View::text("• Status bars with left/center/right sections"))
85                            .child(View::text("• Custom foreground and background colors"))
86                            .child(View::text("• Editor-style status line example"))
87                            .child(View::gap(1))
88                            .child(View::styled_text("Key concepts").bold().build())
89                            .child(View::text("• View::status_bar() creates status lines"))
90                            .child(View::text("• .left(), .center(), .right() for sections"))
91                            .child(View::text("• .fg() and .bg() for custom colors"))
92                            .child(View::text("• Great for showing mode, file info, etc."))
93                            .child(View::gap(1))
94                            .child(View::styled_text("Try this").bold().build())
95                            .child(View::text("• Compare different status bar styles"))
96                            .child(View::text("• Notice how sections align"))
97                            .child(View::gap(1))
98                            .child(View::styled_text("Next up").bold().build())
99                            .child(View::text("→ 20_menu_bar: dropdown menus"))
100                            .child(View::gap(1))
101                            .child(View::styled_text("Press Escape to close").dim().build())
102                            .build(),
103                    )
104                    .build(),
105            )
106            .build()
107    }
examples/09_syntax_comparison.rs (line 52)
24    fn render(&self, cx: Scope) -> View {
25        let use_jsx = state!(cx, || false);
26        let show_help = state!(cx, || false);
27
28        // F1 toggles help
29        cx.use_command(
30            KeyBinding::key(KeyCode::F(1)),
31            with!(show_help => move || show_help.update(|v| *v = !*v)),
32        );
33
34        let toggle = with!(use_jsx => move || use_jsx.set(!use_jsx.get()));
35
36        // Show which syntax is currently displayed
37        let syntax_name = if use_jsx.get() {
38            "view! macro (JSX-like)"
39        } else {
40            "Builder pattern"
41        };
42
43        View::vstack()
44            .child(
45                View::styled_text("Syntax Comparison")
46                    .color(Color::Cyan)
47                    .bold()
48                    .build(),
49            )
50            .child(
51                View::styled_text("Same UI, two ways to write it")
52                    .dim()
53                    .build(),
54            )
55            .child(View::gap(1))
56            .child(
57                View::hstack()
58                    .child(View::text("Current syntax: "))
59                    .child(
60                        View::styled_text(syntax_name)
61                            .color(Color::Yellow)
62                            .bold()
63                            .build(),
64                    )
65                    .build(),
66            )
67            .child(View::gap(1))
68            .child(
69                View::boxed()
70                    .border(true)
71                    .padding(1)
72                    .child(if use_jsx.get() {
73                        counter_jsx(cx.clone())
74                    } else {
75                        counter_builder(cx.clone())
76                    })
77                    .build(),
78            )
79            .child(View::gap(1))
80            .child(
81                View::button()
82                    .label("Toggle Syntax")
83                    .on_press(toggle)
84                    .build(),
85            )
86            .child(View::gap(1))
87            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
88            .child(
89                View::modal()
90                    .visible(show_help.get())
91                    .title("Example 09: Syntax Comparison")
92                    .on_dismiss(with!(show_help => move || show_help.set(false)))
93                    .child(
94                        View::vstack()
95                            .child(View::styled_text("What you're seeing").bold().build())
96                            .child(View::text("• Two syntaxes that produce identical output"))
97                            .child(View::text("• Builder: View::vstack().child(...).build()"))
98                            .child(View::text("• Macro: view! { <VStack>...</VStack> }"))
99                            .child(View::gap(1))
100                            .child(View::styled_text("Key concepts").bold().build())
101                            .child(View::text("• Builder is Rust-native, IDE-friendly"))
102                            .child(View::text("• view! macro is JSX-like, less boilerplate"))
103                            .child(View::text("• Choose based on your preference"))
104                            .child(View::gap(1))
105                            .child(View::styled_text("Try this").bold().build())
106                            .child(View::text("• Toggle between syntaxes"))
107                            .child(View::text("• Notice the output is identical"))
108                            .child(View::text("• Check the source code to see both styles"))
109                            .child(View::gap(1))
110                            .child(View::styled_text("Next up").bold().build())
111                            .child(View::text("→ 10_state_explained: deep dive into state"))
112                            .child(View::gap(1))
113                            .child(View::styled_text("Press Escape to close").dim().build())
114                            .build(),
115                    )
116                    .build(),
117            )
118            .build()
119    }
Source

pub fn build(self) -> View

Examples found in repository?
examples/01_hello_world.rs (line 29)
19    fn render(&self, cx: Scope) -> View {
20        let show_help = state!(cx, || false);
21
22        // F1 toggles help
23        cx.use_command(
24            KeyBinding::key(KeyCode::F(1)),
25            with!(show_help => move || show_help.update(|v| *v = !*v)),
26        );
27
28        View::vstack()
29            .child(View::styled_text("Hello World").bold().build())
30            .child(View::gap(1))
31            .child(View::text("Welcome to Telex!"))
32            .child(View::gap(1))
33            .child(
34                View::styled_text("F1 for help • Ctrl+Q to quit")
35                    .dim()
36                    .build(),
37            )
38            .child(
39                View::modal()
40                    .visible(show_help.get())
41                    .title("Example 01: Hello World")
42                    .on_dismiss(with!(show_help => move || show_help.set(false)))
43                    .child(
44                        View::vstack()
45                            .child(View::styled_text("What you're seeing").bold().build())
46                            .child(View::text(
47                                "• Basic app structure with struct + Component trait",
48                            ))
49                            .child(View::text(
50                                "• View::text() and View::styled_text() for display",
51                            ))
52                            .child(View::text("• View::vstack() for vertical layout"))
53                            .child(View::gap(1))
54                            .child(View::styled_text("Key concepts").bold().build())
55                            .child(View::text("• Every Telex app implements Component"))
56                            .child(View::text("• render() returns a View tree"))
57                            .child(View::text("• No state yet - this is purely static"))
58                            .child(View::gap(1))
59                            .child(View::styled_text("Next up").bold().build())
60                            .child(View::text("→ 02_counter: add state and interactivity"))
61                            .child(View::gap(1))
62                            .child(View::styled_text("Press Escape to close").dim().build())
63                            .build(),
64                    )
65                    .build(),
66            )
67            .build()
68    }
More examples
Hide additional examples
examples/30_image.rs (line 43)
30    fn render(&self, cx: Scope) -> View {
31        let show_help = state!(cx, || false);
32
33        // F1 toggles help
34        cx.use_command(
35            KeyBinding::key(KeyCode::F(1)),
36            with!(show_help => move || show_help.update(|v| *v = !*v)),
37        );
38        View::vstack()
39            .spacing(1)
40            .child(
41                View::styled_text("Image Widget Demo (Kitty Graphics)")
42                    .bold()
43                    .build(),
44            )
45            .child(View::text("Requires Kitty, Ghostty, or WezTerm terminal"))
46            .child(View::text(""))
47            // Load image from file path
48            .child(View::text("Logo (from file path):"))
49            .child(View::image().file("assets/telex-tui.png").build())
50            .child(View::text(""))
51            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
52            .child(
53                View::modal()
54                    .visible(show_help.get())
55                    .title("Example 30: Image")
56                    .on_dismiss(with!(show_help => move || show_help.set(false)))
57                    .child(
58                        View::vstack()
59                            .child(View::styled_text("What you're seeing").bold().build())
60                            .child(View::text("• Image display via Kitty protocol"))
61                            .child(View::text("• PNG/JPEG/GIF support"))
62                            .child(View::text("• Loaded from file path"))
63                            .child(View::gap(1))
64                            .child(View::styled_text("Key concepts").bold().build())
65                            .child(View::text("• View::image() displays images"))
66                            .child(View::text("• .file(\"path\") loads from disk"))
67                            .child(View::text("• .bytes(data) for embedded images"))
68                            .child(View::text("• Works in Kitty/Ghostty/WezTerm"))
69                            .child(View::gap(1))
70                            .child(View::styled_text("Try this").bold().build())
71                            .child(View::text("• Run in compatible terminal"))
72                            .child(View::text("• See the Telex logo rendered"))
73                            .child(View::gap(1))
74                            .child(View::styled_text("Next up").bold().build())
75                            .child(View::text("→ 31_animated_canvas: animations"))
76                            .child(View::gap(1))
77                            .child(View::styled_text("Press Escape to close").dim().build())
78                            .build(),
79                    )
80                    .build(),
81            )
82            .build()
83    }
examples/04_timer.rs (line 49)
22    fn render(&self, cx: Scope) -> View {
23        let show_help = state!(cx, || false);
24
25        // F1 toggles help
26        cx.use_command(
27            KeyBinding::key(KeyCode::F(1)),
28            with!(show_help => move || show_help.update(|v| *v = !*v)),
29        );
30
31        // Stream that yields elapsed seconds
32        let elapsed = stream!(cx, || {
33            (0u64..).inspect(|&s| {
34                if s > 0 {
35                    std::thread::sleep(Duration::from_secs(1));
36                }
37            })
38        });
39
40        let seconds = elapsed.get();
41        let is_running = elapsed.is_loading();
42
43        // Format as MM:SS
44        let minutes = seconds / 60;
45        let secs = seconds % 60;
46        let time_display = format!("{:02}:{:02}", minutes, secs);
47
48        View::vstack()
49            .child(View::styled_text("Timer").color(Color::Cyan).bold().build())
50            .child(View::gap(1))
51            .child(
52                View::hstack()
53                    .child(View::styled_text(&time_display).bold().build())
54                    .child(if is_running {
55                        View::styled_text(" ●").color(Color::Green).build()
56                    } else {
57                        View::styled_text(" ○").dim().build()
58                    })
59                    .build(),
60            )
61            .child(View::gap(1))
62            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
63            .child(
64                View::modal()
65                    .visible(show_help.get())
66                    .title("Example 04: Timer")
67                    .on_dismiss(with!(show_help => move || show_help.set(false)))
68                    .child(
69                        View::vstack()
70                            .child(View::styled_text("What you're seeing").bold().build())
71                            .child(View::text("• stream!() macro for background data"))
72                            .child(View::text("• Auto-updating UI without user input"))
73                            .child(View::text("• Green dot = stream is running"))
74                            .child(View::gap(1))
75                            .child(View::styled_text("Key concepts").bold().build())
76                            .child(View::text("• Streams run in background threads"))
77                            .child(View::text("• Each yielded value triggers a re-render"))
78                            .child(View::text("• is_loading() tells you if stream is active"))
79                            .child(View::gap(1))
80                            .child(View::styled_text("Try this").bold().build())
81                            .child(View::text("• Just watch - the timer ticks automatically"))
82                            .child(View::text("• No button presses needed for updates"))
83                            .child(View::gap(1))
84                            .child(View::styled_text("Next up").bold().build())
85                            .child(View::text("→ 05_todo_list: text input and list management"))
86                            .child(View::gap(1))
87                            .child(View::styled_text("Press Escape to close").dim().build())
88                            .build(),
89                    )
90                    .build(),
91            )
92            .build()
93    }
examples/02_counter.rs (line 33)
19    fn render(&self, cx: Scope) -> View {
20        let count = state!(cx, || 0i32);
21        let show_help = state!(cx, || false);
22
23        let increment = with!(count => move || count.update(|n| *n += 1));
24        let decrement = with!(count => move || count.update(|n| *n -= 1));
25
26        // F1 toggles help
27        cx.use_command(
28            KeyBinding::key(KeyCode::F(1)),
29            with!(show_help => move || show_help.update(|v| *v = !*v)),
30        );
31
32        View::vstack()
33            .child(View::styled_text("Counter").bold().build())
34            .child(View::gap(1))
35            .child(View::text(format!("Count: {}", count.get())))
36            .child(View::gap(1))
37            .child(
38                View::hstack()
39                    .child(
40                        View::button()
41                            .label("Decrement")
42                            .on_press(decrement)
43                            .build(),
44                    )
45                    .child(View::text(" "))
46                    .child(
47                        View::button()
48                            .label("Increment")
49                            .on_press(increment)
50                            .build(),
51                    )
52                    .build(),
53            )
54            .child(View::gap(1))
55            .child(
56                View::styled_text("Tab to switch • Enter to press • F1 for help • Ctrl+Q to quit")
57                    .dim()
58                    .build(),
59            )
60            .child(
61                View::modal()
62                    .visible(show_help.get())
63                    .title("Example 02: Counter")
64                    .on_dismiss(with!(show_help => move || show_help.set(false)))
65                    .child(
66                        View::vstack()
67                            .child(View::styled_text("What you're seeing").bold().build())
68                            .child(View::text("• state!() macro for reactive state"))
69                            .child(View::text("• View::button() with on_press callbacks"))
70                            .child(View::text(
71                                "• The with!() macro for capturing state in closures",
72                            ))
73                            .child(View::gap(1))
74                            .child(View::styled_text("Key concepts").bold().build())
75                            .child(View::text("• State persists across renders"))
76                            .child(View::text("• Updating state triggers a re-render"))
77                            .child(View::text("• Tab navigates between focusable elements"))
78                            .child(View::gap(1))
79                            .child(View::styled_text("Try this").bold().build())
80                            .child(View::text("• Press +/- rapidly - notice instant updates"))
81                            .child(View::text(
82                                "• The UI stays in sync with state automatically",
83                            ))
84                            .child(View::gap(1))
85                            .child(View::styled_text("Next up").bold().build())
86                            .child(View::text("→ 03_theme_switcher: styling and colors"))
87                            .child(View::gap(1))
88                            .child(View::styled_text("Press Escape to close").dim().build())
89                            .build(),
90                    )
91                    .build(),
92            )
93            .build()
94    }
examples/19_status_bar.rs (line 33)
24    fn render(&self, cx: Scope) -> View {
25        let show_help = state!(cx, || false);
26
27        // F1 toggles help
28        cx.use_command(
29            KeyBinding::key(KeyCode::F(1)),
30            with!(show_help => move || show_help.update(|v| *v = !*v)),
31        );
32        View::vstack()
33            .child(View::styled_text("Status Bar Examples").bold().build())
34            .child(View::text(""))
35            .child(View::text("Basic status bar (left only):"))
36            .child(View::status_bar().left("NORMAL").build())
37            .child(View::text(""))
38            .child(View::text("Left and right sections:"))
39            .child(
40                View::status_bar()
41                    .left("INSERT")
42                    .right("Ln 42, Col 8")
43                    .build(),
44            )
45            .child(View::text(""))
46            .child(View::text("All three sections:"))
47            .child(
48                View::status_bar()
49                    .left("VISUAL")
50                    .center("main.rs")
51                    .right("UTF-8 | LF | Rust")
52                    .build(),
53            )
54            .child(View::text(""))
55            .child(View::text("Custom colors (green on dark):"))
56            .child(
57                View::status_bar()
58                    .left("SUCCESS")
59                    .center("All tests passed")
60                    .right("100%")
61                    .fg(Color::Green)
62                    .bg(Color::DarkGreen)
63                    .build(),
64            )
65            .child(View::text(""))
66            .child(View::text("Editor-style status bar:"))
67            .child(
68                View::status_bar()
69                    .left("-- INSERT --")
70                    .center("~/projects/myapp/src/main.rs [+]")
71                    .right("1/100 | 50%")
72                    .build(),
73            )
74            .child(View::spacer())
75            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
76            .child(
77                View::modal()
78                    .visible(show_help.get())
79                    .title("Example 19: Status Bar")
80                    .on_dismiss(with!(show_help => move || show_help.set(false)))
81                    .child(
82                        View::vstack()
83                            .child(View::styled_text("What you're seeing").bold().build())
84                            .child(View::text("• Status bars with left/center/right sections"))
85                            .child(View::text("• Custom foreground and background colors"))
86                            .child(View::text("• Editor-style status line example"))
87                            .child(View::gap(1))
88                            .child(View::styled_text("Key concepts").bold().build())
89                            .child(View::text("• View::status_bar() creates status lines"))
90                            .child(View::text("• .left(), .center(), .right() for sections"))
91                            .child(View::text("• .fg() and .bg() for custom colors"))
92                            .child(View::text("• Great for showing mode, file info, etc."))
93                            .child(View::gap(1))
94                            .child(View::styled_text("Try this").bold().build())
95                            .child(View::text("• Compare different status bar styles"))
96                            .child(View::text("• Notice how sections align"))
97                            .child(View::gap(1))
98                            .child(View::styled_text("Next up").bold().build())
99                            .child(View::text("→ 20_menu_bar: dropdown menus"))
100                            .child(View::gap(1))
101                            .child(View::styled_text("Press Escape to close").dim().build())
102                            .build(),
103                    )
104                    .build(),
105            )
106            .build()
107    }
examples/09_syntax_comparison.rs (line 48)
24    fn render(&self, cx: Scope) -> View {
25        let use_jsx = state!(cx, || false);
26        let show_help = state!(cx, || false);
27
28        // F1 toggles help
29        cx.use_command(
30            KeyBinding::key(KeyCode::F(1)),
31            with!(show_help => move || show_help.update(|v| *v = !*v)),
32        );
33
34        let toggle = with!(use_jsx => move || use_jsx.set(!use_jsx.get()));
35
36        // Show which syntax is currently displayed
37        let syntax_name = if use_jsx.get() {
38            "view! macro (JSX-like)"
39        } else {
40            "Builder pattern"
41        };
42
43        View::vstack()
44            .child(
45                View::styled_text("Syntax Comparison")
46                    .color(Color::Cyan)
47                    .bold()
48                    .build(),
49            )
50            .child(
51                View::styled_text("Same UI, two ways to write it")
52                    .dim()
53                    .build(),
54            )
55            .child(View::gap(1))
56            .child(
57                View::hstack()
58                    .child(View::text("Current syntax: "))
59                    .child(
60                        View::styled_text(syntax_name)
61                            .color(Color::Yellow)
62                            .bold()
63                            .build(),
64                    )
65                    .build(),
66            )
67            .child(View::gap(1))
68            .child(
69                View::boxed()
70                    .border(true)
71                    .padding(1)
72                    .child(if use_jsx.get() {
73                        counter_jsx(cx.clone())
74                    } else {
75                        counter_builder(cx.clone())
76                    })
77                    .build(),
78            )
79            .child(View::gap(1))
80            .child(
81                View::button()
82                    .label("Toggle Syntax")
83                    .on_press(toggle)
84                    .build(),
85            )
86            .child(View::gap(1))
87            .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
88            .child(
89                View::modal()
90                    .visible(show_help.get())
91                    .title("Example 09: Syntax Comparison")
92                    .on_dismiss(with!(show_help => move || show_help.set(false)))
93                    .child(
94                        View::vstack()
95                            .child(View::styled_text("What you're seeing").bold().build())
96                            .child(View::text("• Two syntaxes that produce identical output"))
97                            .child(View::text("• Builder: View::vstack().child(...).build()"))
98                            .child(View::text("• Macro: view! { <VStack>...</VStack> }"))
99                            .child(View::gap(1))
100                            .child(View::styled_text("Key concepts").bold().build())
101                            .child(View::text("• Builder is Rust-native, IDE-friendly"))
102                            .child(View::text("• view! macro is JSX-like, less boilerplate"))
103                            .child(View::text("• Choose based on your preference"))
104                            .child(View::gap(1))
105                            .child(View::styled_text("Try this").bold().build())
106                            .child(View::text("• Toggle between syntaxes"))
107                            .child(View::text("• Notice the output is identical"))
108                            .child(View::text("• Check the source code to see both styles"))
109                            .child(View::gap(1))
110                            .child(View::styled_text("Next up").bold().build())
111                            .child(View::text("→ 10_state_explained: deep dive into state"))
112                            .child(View::gap(1))
113                            .child(View::styled_text("Press Escape to close").dim().build())
114                            .build(),
115                    )
116                    .build(),
117            )
118            .build()
119    }
120}
121
122// =============================================================================
123// Builder Pattern
124// =============================================================================
125// Rust-native, explicit, IDE-friendly. Each method call is clear.
126// Good for: Complex conditional logic, learning the API, debugging.
127
128fn counter_builder(cx: Scope) -> View {
129    let count = state!(cx, || 0i32);
130
131    // with! macro clones the handle for you - much cleaner!
132    let increment = with!(count => move || count.update(|n| *n += 1));
133    let decrement = with!(count => move || count.update(|n| *n -= 1));
134
135    View::vstack()
136        .child(
137            View::styled_text("// Built with builder pattern")
138                .color(Color::DarkGrey)
139                .build(),
140        )
141        .child(View::gap(1))
142        .child(
143            View::styled_text(format!("Count: {}", count.get()))
144                .bold()
145                .build(),
146        )
147        .child(View::gap(1))
148        .child(
149            View::hstack()
150                .child(View::button().label(" - ").on_press(decrement).build())
151                .child(View::text(" "))
152                .child(View::button().label(" + ").on_press(increment).build())
153                .build(),
154        )
155        .build()
156}

Trait Implementations§

Source§

impl Debug for TextBuilder

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for TextBuilder

Source§

fn default() -> TextBuilder

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.