pub struct ModalBuilder { /* private fields */ }Expand description
Builder for Modal views.
Implementations§
Source§impl ModalBuilder
impl ModalBuilder
pub fn new() -> Self
Sourcepub fn visible(self, visible: bool) -> Self
pub fn visible(self, visible: bool) -> Self
Set whether the modal is visible.
Examples found in repository?
examples/01_hello_world.rs (line 40)
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
examples/30_image.rs (line 54)
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 65)
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 62)
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 78)
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 90)
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 }Additional examples can be found in:
- examples/35_slider.rs
- examples/15_markdown.rs
- examples/18_progress_bar.rs
- examples/16_tree.rs
- examples/05_todo_list.rs
- examples/37_error_boundary.rs
- examples/38_custom_widget.rs
- examples/10_state_explained.rs
- examples/32_effects.rs
- examples/13_split_panes.rs
- examples/07_file_browser.rs
- examples/12_text_area.rs
- examples/06_log_viewer.rs
- examples/24_async_data.rs
- examples/34_channels_and_intervals.rs
- examples/08_system_monitor.rs
- examples/39_port.rs
- examples/25_context.rs
- examples/14_tabs.rs
- examples/11_checkbox.rs
- examples/17_table.rs
- examples/29_canvas.rs
- examples/20_menu_bar.rs
- examples/26_radio_buttons.rs
- examples/21_toasts.rs
- examples/36_reducer.rs
- examples/03_theme_switcher.rs
- examples/28_shared_state.rs
- examples/27_keyed_state.rs
- examples/31_animated_canvas.rs
- examples/22_forms.rs
- examples/23_modal.rs
Sourcepub fn title(self, title: impl Into<String>) -> Self
pub fn title(self, title: impl Into<String>) -> Self
Set the title shown in the modal border.
Examples found in repository?
examples/01_hello_world.rs (line 41)
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
examples/30_image.rs (line 55)
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 66)
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 63)
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 79)
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 91)
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 }Additional examples can be found in:
- examples/35_slider.rs
- examples/15_markdown.rs
- examples/18_progress_bar.rs
- examples/16_tree.rs
- examples/05_todo_list.rs
- examples/37_error_boundary.rs
- examples/38_custom_widget.rs
- examples/10_state_explained.rs
- examples/32_effects.rs
- examples/13_split_panes.rs
- examples/07_file_browser.rs
- examples/12_text_area.rs
- examples/06_log_viewer.rs
- examples/24_async_data.rs
- examples/34_channels_and_intervals.rs
- examples/08_system_monitor.rs
- examples/39_port.rs
- examples/25_context.rs
- examples/14_tabs.rs
- examples/11_checkbox.rs
- examples/17_table.rs
- examples/29_canvas.rs
- examples/20_menu_bar.rs
- examples/26_radio_buttons.rs
- examples/21_toasts.rs
- examples/36_reducer.rs
- examples/03_theme_switcher.rs
- examples/28_shared_state.rs
- examples/27_keyed_state.rs
- examples/31_animated_canvas.rs
- examples/22_forms.rs
- examples/23_modal.rs
Sourcepub fn child(self, view: View) -> Self
pub fn child(self, view: View) -> Self
Set the content of the modal.
Examples found in repository?
examples/01_hello_world.rs (lines 43-64)
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
examples/30_image.rs (lines 57-79)
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 (lines 68-89)
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 (lines 65-90)
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 (lines 81-103)
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 (lines 93-115)
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 }Additional examples can be found in:
- examples/35_slider.rs
- examples/15_markdown.rs
- examples/18_progress_bar.rs
- examples/16_tree.rs
- examples/05_todo_list.rs
- examples/37_error_boundary.rs
- examples/38_custom_widget.rs
- examples/10_state_explained.rs
- examples/32_effects.rs
- examples/13_split_panes.rs
- examples/07_file_browser.rs
- examples/12_text_area.rs
- examples/06_log_viewer.rs
- examples/24_async_data.rs
- examples/34_channels_and_intervals.rs
- examples/08_system_monitor.rs
- examples/39_port.rs
- examples/25_context.rs
- examples/14_tabs.rs
- examples/11_checkbox.rs
- examples/17_table.rs
- examples/29_canvas.rs
- examples/20_menu_bar.rs
- examples/26_radio_buttons.rs
- examples/21_toasts.rs
- examples/36_reducer.rs
- examples/03_theme_switcher.rs
- examples/28_shared_state.rs
- examples/27_keyed_state.rs
- examples/31_animated_canvas.rs
- examples/22_forms.rs
- examples/23_modal.rs
Sourcepub fn on_dismiss(self, callback: impl Fn() + 'static) -> Self
pub fn on_dismiss(self, callback: impl Fn() + 'static) -> Self
Set the callback when modal is dismissed (Escape key).
Examples found in repository?
examples/01_hello_world.rs (line 42)
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
examples/30_image.rs (line 56)
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 67)
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 64)
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 80)
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 92)
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 }Additional examples can be found in:
- examples/35_slider.rs
- examples/15_markdown.rs
- examples/18_progress_bar.rs
- examples/16_tree.rs
- examples/05_todo_list.rs
- examples/37_error_boundary.rs
- examples/38_custom_widget.rs
- examples/10_state_explained.rs
- examples/32_effects.rs
- examples/13_split_panes.rs
- examples/07_file_browser.rs
- examples/12_text_area.rs
- examples/06_log_viewer.rs
- examples/24_async_data.rs
- examples/34_channels_and_intervals.rs
- examples/08_system_monitor.rs
- examples/39_port.rs
- examples/25_context.rs
- examples/14_tabs.rs
- examples/11_checkbox.rs
- examples/17_table.rs
- examples/29_canvas.rs
- examples/20_menu_bar.rs
- examples/26_radio_buttons.rs
- examples/21_toasts.rs
- examples/36_reducer.rs
- examples/03_theme_switcher.rs
- examples/28_shared_state.rs
- examples/27_keyed_state.rs
- examples/31_animated_canvas.rs
- examples/22_forms.rs
- examples/23_modal.rs
Sourcepub fn width(self, percent: u16) -> Self
pub fn width(self, percent: u16) -> Self
Set the width as percentage of screen (0-100).
Examples found in repository?
examples/07_file_browser.rs (line 135)
49 fn render(&self, cx: Scope) -> View {
50 let current_path =
51 state!(cx, || std::env::current_dir().unwrap_or_else(|_| PathBuf::from("/")));
52 let selected = state!(cx, || 0usize);
53 let show_file_info = state!(cx, || false);
54 let selected_file_path = state!(cx, String::new);
55 let show_help = state!(cx, || false);
56 let entries = list_directory(¤t_path.get());
57
58 // F1 toggles help
59 cx.use_command(
60 KeyBinding::key(KeyCode::F(1)),
61 with!(show_help => move || show_help.update(|v| *v = !*v)),
62 );
63
64 // Track selection (just updates index, doesn't navigate)
65 let on_select = with!(selected => move |idx: usize| {
66 selected.set(idx);
67 });
68
69 // Dismiss modal
70 let on_dismiss = with!(show_file_info => move || show_file_info.set(false));
71
72 // Open directory or show file info on Enter
73 let entries_for_cmd = entries.clone();
74 cx.use_command(
75 KeyBinding::key(KeyCode::Enter),
76 with!(current_path, selected, show_file_info, selected_file_path => move || {
77 let idx = selected.get();
78 if idx < entries_for_cmd.len() {
79 let entry = &entries_for_cmd[idx];
80 let path = current_path.get();
81
82 if entry == ".." {
83 if let Some(parent) = path.parent() {
84 current_path.set(parent.to_path_buf());
85 selected.set(0);
86 }
87 } else if entry.ends_with('/') {
88 let dir_name = entry.trim_end_matches('/');
89 let new_path = path.join(dir_name);
90 current_path.set(new_path);
91 selected.set(0);
92 } else {
93 // It's a file - show info modal
94 let full_path = path.join(entry);
95 selected_file_path.set(full_path.to_string_lossy().to_string());
96 show_file_info.set(true);
97 }
98 }
99 }),
100 );
101
102 let path_display = current_path.get().to_string_lossy().to_string();
103
104 View::vstack()
105 .child(
106 View::styled_text("File Browser")
107 .color(Color::Cyan)
108 .bold()
109 .build(),
110 )
111 .child(View::gap(1))
112 .child(
113 View::styled_text(&path_display)
114 .color(Color::Yellow)
115 .build(),
116 )
117 .child(View::gap(1))
118 .child(
119 View::list()
120 .items(entries)
121 .selected(selected.get())
122 .on_select(on_select)
123 .build(),
124 )
125 .child(View::gap(1))
126 .child(
127 View::styled_text("↑/↓ navigate • Enter open • F1 help • Ctrl+Q quit")
128 .dim()
129 .build(),
130 )
131 .child(
132 View::modal()
133 .visible(show_file_info.get())
134 .title("File")
135 .width(60)
136 .height(20)
137 .on_dismiss(on_dismiss)
138 .child(
139 View::vstack()
140 .child(View::text(selected_file_path.get()))
141 .child(View::gap(1))
142 .child(View::styled_text("Press Escape to close").dim().build())
143 .build(),
144 )
145 .build(),
146 )
147 .child(
148 View::modal()
149 .visible(show_help.get())
150 .title("Example 07: File Browser")
151 .on_dismiss(with!(show_help => move || show_help.set(false)))
152 .child(
153 View::vstack()
154 .child(View::styled_text("What you're seeing").bold().build())
155 .child(View::text("• Real filesystem navigation"))
156 .child(View::text("• cx.use_command() for keyboard shortcuts"))
157 .child(View::text("• Modal for file details"))
158 .child(View::gap(1))
159 .child(View::styled_text("Key concepts").bold().build())
160 .child(View::text("• std::fs::read_dir for directory listing"))
161 .child(View::text(
162 "• KeyBinding::key(KeyCode::Enter) for Enter handling",
163 ))
164 .child(View::text("• Directories shown with trailing /"))
165 .child(View::gap(1))
166 .child(View::styled_text("Try this").bold().build())
167 .child(View::text("• Navigate into directories with Enter"))
168 .child(View::text("• Go up with '..' entry"))
169 .child(View::text("• Select a file to see its path"))
170 .child(View::gap(1))
171 .child(View::styled_text("Next up").bold().build())
172 .child(View::text(
173 "→ 08_system_monitor: multiple concurrent streams",
174 ))
175 .child(View::gap(1))
176 .child(View::styled_text("Press Escape to close").dim().build())
177 .build(),
178 )
179 .build(),
180 )
181 .build()
182 }More examples
examples/23_modal.rs (line 191)
21 fn render(&self, cx: Scope) -> View {
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 // Modal visibility states
31 let show_confirm = state!(cx, || false);
32 let show_alert = state!(cx, || false);
33 let show_custom = state!(cx, || false);
34
35 // App state that modals can modify
36 let deleted_count = state!(cx, || 0);
37 let custom_input = state!(cx, String::new);
38 let last_action = state!(cx, || "No action yet".to_string());
39
40 // Handlers
41 let open_confirm = with!(show_confirm => move || {
42 show_confirm.set(true);
43 });
44
45 let open_alert = with!(show_alert => move || {
46 show_alert.set(true);
47 });
48
49 let open_custom = with!(show_custom => move || {
50 show_custom.set(true);
51 });
52
53 let on_confirm_yes = with!(show_confirm, deleted_count, last_action => move || {
54 deleted_count.set(deleted_count.get() + 1);
55 last_action.set(format!("Deleted item #{}", deleted_count.get()));
56 show_confirm.set(false);
57 });
58
59 let on_confirm_no = with!(show_confirm, last_action => move || {
60 last_action.set("Cancelled delete".to_string());
61 show_confirm.set(false);
62 });
63
64 let on_alert_dismiss = with!(show_alert, last_action => move || {
65 last_action.set("Dismissed alert".to_string());
66 show_alert.set(false);
67 });
68
69 let on_custom_save = with!(show_custom, custom_input, last_action => move || {
70 let value = custom_input.get();
71 if !value.is_empty() {
72 last_action.set(format!("Saved: {}", value));
73 custom_input.set(String::new());
74 }
75 show_custom.set(false);
76 });
77
78 let on_custom_dismiss = with!(show_custom => move || {
79 show_custom.set(false);
80 });
81
82 View::vstack()
83 .spacing(1)
84 .child(
85 // Header
86 View::boxed()
87 .border(true)
88 .padding(1)
89 .child(
90 View::vstack()
91 .child(View::styled_text("Modal Dialogs Demo").bold().build())
92 .child(
93 View::styled_text("Click buttons to open different modal types")
94 .dim()
95 .build(),
96 )
97 .build(),
98 )
99 .build(),
100 )
101 .child(
102 // Main content
103 View::boxed()
104 .flex(1)
105 .border(true)
106 .padding(1)
107 .child(
108 View::vstack()
109 .spacing(1)
110 .child(View::text("Modal Types:"))
111 .child(
112 View::hstack()
113 .spacing(2)
114 .child(
115 View::button()
116 .label("Confirm Dialog")
117 .on_press(open_confirm)
118 .build(),
119 )
120 .child(
121 View::button()
122 .label("Alert Dialog")
123 .on_press(open_alert)
124 .build(),
125 )
126 .child(
127 View::button()
128 .label("Custom Modal")
129 .on_press(open_custom)
130 .build(),
131 )
132 .build(),
133 )
134 .child(View::spacer())
135 .child(
136 View::styled_text(format!(
137 "Deleted items: {}",
138 deleted_count.get()
139 ))
140 .color(Color::Yellow)
141 .build(),
142 )
143 .child(
144 View::styled_text(format!("Last action: {}", last_action.get()))
145 .dim()
146 .build(),
147 )
148 .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
149 .build(),
150 )
151 .build(),
152 )
153 // Help modal
154 .child(
155 View::modal()
156 .visible(show_help.get())
157 .title("Example 23: Modal")
158 .on_dismiss(with!(show_help => move || show_help.set(false)))
159 .child(
160 View::vstack()
161 .child(View::styled_text("What you're seeing").bold().build())
162 .child(View::text("• Confirm, alert, and custom modals"))
163 .child(View::text("• Modal focus containment"))
164 .child(View::text("• Escape to dismiss"))
165 .child(View::gap(1))
166 .child(View::styled_text("Key concepts").bold().build())
167 .child(View::text("• View::modal() creates overlay"))
168 .child(View::text("• .visible() controls show/hide"))
169 .child(View::text("• .on_dismiss() handles Escape"))
170 .child(View::text("• Focus trapped in open modal"))
171 .child(View::gap(1))
172 .child(View::styled_text("Try this").bold().build())
173 .child(View::text("• Open confirm, click Yes/No"))
174 .child(View::text("• Custom modal has text input"))
175 .child(View::text("• Press Escape to close modals"))
176 .child(View::gap(1))
177 .child(View::styled_text("Next up").bold().build())
178 .child(View::text("→ 24_async_data: async loading"))
179 .child(View::gap(1))
180 .child(View::styled_text("Press Escape to close").dim().build())
181 .build(),
182 )
183 .build(),
184 )
185 // Confirm dialog modal
186 .child(
187 View::modal()
188 .visible(show_confirm.get())
189 .title("Confirm Delete")
190 .on_dismiss(on_confirm_no.clone())
191 .width(40)
192 .height(30)
193 .child(
194 View::vstack()
195 .spacing(1)
196 .child(View::text("Are you sure you want to delete this item?"))
197 .child(View::text("This action cannot be undone."))
198 .child(View::spacer())
199 .child(
200 View::hstack()
201 .spacing(2)
202 .child(
203 View::button()
204 .label("Yes, Delete")
205 .on_press(on_confirm_yes)
206 .build(),
207 )
208 .child(
209 View::button()
210 .label("Cancel")
211 .on_press(on_confirm_no)
212 .build(),
213 )
214 .build(),
215 )
216 .build(),
217 )
218 .build(),
219 )
220 // Alert dialog modal
221 .child(
222 View::modal()
223 .visible(show_alert.get())
224 .title("Alert")
225 .on_dismiss(on_alert_dismiss.clone())
226 .width(50)
227 .height(25)
228 .child(
229 View::vstack()
230 .spacing(1)
231 .child(
232 View::styled_text("Operation completed successfully!")
233 .color(Color::Green)
234 .build(),
235 )
236 .child(View::text("Your changes have been saved."))
237 .child(View::spacer())
238 .child(
239 View::button()
240 .label("OK")
241 .on_press(on_alert_dismiss)
242 .build(),
243 )
244 .build(),
245 )
246 .build(),
247 )
248 // Custom modal with input
249 .child(
250 View::modal()
251 .visible(show_custom.get())
252 .title("Enter Details")
253 .on_dismiss(on_custom_dismiss.clone())
254 .width(50)
255 .height(40)
256 .child(
257 View::vstack()
258 .spacing(1)
259 .child(View::text("Enter a value:"))
260 .child(
261 View::text_input()
262 .value(custom_input.get())
263 .placeholder("Type something...")
264 .on_change(with!(custom_input => move |v: String| {
265 custom_input.set(v);
266 }))
267 .build(),
268 )
269 .child(View::spacer())
270 .child(
271 View::hstack()
272 .spacing(2)
273 .child(
274 View::button()
275 .label("Save")
276 .on_press(on_custom_save)
277 .build(),
278 )
279 .child(
280 View::button()
281 .label("Cancel")
282 .on_press(on_custom_dismiss)
283 .build(),
284 )
285 .build(),
286 )
287 .build(),
288 )
289 .build(),
290 )
291 .build()
292 }Sourcepub fn height(self, percent: u16) -> Self
pub fn height(self, percent: u16) -> Self
Set the height as percentage of screen (0-100).
Examples found in repository?
examples/07_file_browser.rs (line 136)
49 fn render(&self, cx: Scope) -> View {
50 let current_path =
51 state!(cx, || std::env::current_dir().unwrap_or_else(|_| PathBuf::from("/")));
52 let selected = state!(cx, || 0usize);
53 let show_file_info = state!(cx, || false);
54 let selected_file_path = state!(cx, String::new);
55 let show_help = state!(cx, || false);
56 let entries = list_directory(¤t_path.get());
57
58 // F1 toggles help
59 cx.use_command(
60 KeyBinding::key(KeyCode::F(1)),
61 with!(show_help => move || show_help.update(|v| *v = !*v)),
62 );
63
64 // Track selection (just updates index, doesn't navigate)
65 let on_select = with!(selected => move |idx: usize| {
66 selected.set(idx);
67 });
68
69 // Dismiss modal
70 let on_dismiss = with!(show_file_info => move || show_file_info.set(false));
71
72 // Open directory or show file info on Enter
73 let entries_for_cmd = entries.clone();
74 cx.use_command(
75 KeyBinding::key(KeyCode::Enter),
76 with!(current_path, selected, show_file_info, selected_file_path => move || {
77 let idx = selected.get();
78 if idx < entries_for_cmd.len() {
79 let entry = &entries_for_cmd[idx];
80 let path = current_path.get();
81
82 if entry == ".." {
83 if let Some(parent) = path.parent() {
84 current_path.set(parent.to_path_buf());
85 selected.set(0);
86 }
87 } else if entry.ends_with('/') {
88 let dir_name = entry.trim_end_matches('/');
89 let new_path = path.join(dir_name);
90 current_path.set(new_path);
91 selected.set(0);
92 } else {
93 // It's a file - show info modal
94 let full_path = path.join(entry);
95 selected_file_path.set(full_path.to_string_lossy().to_string());
96 show_file_info.set(true);
97 }
98 }
99 }),
100 );
101
102 let path_display = current_path.get().to_string_lossy().to_string();
103
104 View::vstack()
105 .child(
106 View::styled_text("File Browser")
107 .color(Color::Cyan)
108 .bold()
109 .build(),
110 )
111 .child(View::gap(1))
112 .child(
113 View::styled_text(&path_display)
114 .color(Color::Yellow)
115 .build(),
116 )
117 .child(View::gap(1))
118 .child(
119 View::list()
120 .items(entries)
121 .selected(selected.get())
122 .on_select(on_select)
123 .build(),
124 )
125 .child(View::gap(1))
126 .child(
127 View::styled_text("↑/↓ navigate • Enter open • F1 help • Ctrl+Q quit")
128 .dim()
129 .build(),
130 )
131 .child(
132 View::modal()
133 .visible(show_file_info.get())
134 .title("File")
135 .width(60)
136 .height(20)
137 .on_dismiss(on_dismiss)
138 .child(
139 View::vstack()
140 .child(View::text(selected_file_path.get()))
141 .child(View::gap(1))
142 .child(View::styled_text("Press Escape to close").dim().build())
143 .build(),
144 )
145 .build(),
146 )
147 .child(
148 View::modal()
149 .visible(show_help.get())
150 .title("Example 07: File Browser")
151 .on_dismiss(with!(show_help => move || show_help.set(false)))
152 .child(
153 View::vstack()
154 .child(View::styled_text("What you're seeing").bold().build())
155 .child(View::text("• Real filesystem navigation"))
156 .child(View::text("• cx.use_command() for keyboard shortcuts"))
157 .child(View::text("• Modal for file details"))
158 .child(View::gap(1))
159 .child(View::styled_text("Key concepts").bold().build())
160 .child(View::text("• std::fs::read_dir for directory listing"))
161 .child(View::text(
162 "• KeyBinding::key(KeyCode::Enter) for Enter handling",
163 ))
164 .child(View::text("• Directories shown with trailing /"))
165 .child(View::gap(1))
166 .child(View::styled_text("Try this").bold().build())
167 .child(View::text("• Navigate into directories with Enter"))
168 .child(View::text("• Go up with '..' entry"))
169 .child(View::text("• Select a file to see its path"))
170 .child(View::gap(1))
171 .child(View::styled_text("Next up").bold().build())
172 .child(View::text(
173 "→ 08_system_monitor: multiple concurrent streams",
174 ))
175 .child(View::gap(1))
176 .child(View::styled_text("Press Escape to close").dim().build())
177 .build(),
178 )
179 .build(),
180 )
181 .build()
182 }More examples
examples/23_modal.rs (line 192)
21 fn render(&self, cx: Scope) -> View {
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 // Modal visibility states
31 let show_confirm = state!(cx, || false);
32 let show_alert = state!(cx, || false);
33 let show_custom = state!(cx, || false);
34
35 // App state that modals can modify
36 let deleted_count = state!(cx, || 0);
37 let custom_input = state!(cx, String::new);
38 let last_action = state!(cx, || "No action yet".to_string());
39
40 // Handlers
41 let open_confirm = with!(show_confirm => move || {
42 show_confirm.set(true);
43 });
44
45 let open_alert = with!(show_alert => move || {
46 show_alert.set(true);
47 });
48
49 let open_custom = with!(show_custom => move || {
50 show_custom.set(true);
51 });
52
53 let on_confirm_yes = with!(show_confirm, deleted_count, last_action => move || {
54 deleted_count.set(deleted_count.get() + 1);
55 last_action.set(format!("Deleted item #{}", deleted_count.get()));
56 show_confirm.set(false);
57 });
58
59 let on_confirm_no = with!(show_confirm, last_action => move || {
60 last_action.set("Cancelled delete".to_string());
61 show_confirm.set(false);
62 });
63
64 let on_alert_dismiss = with!(show_alert, last_action => move || {
65 last_action.set("Dismissed alert".to_string());
66 show_alert.set(false);
67 });
68
69 let on_custom_save = with!(show_custom, custom_input, last_action => move || {
70 let value = custom_input.get();
71 if !value.is_empty() {
72 last_action.set(format!("Saved: {}", value));
73 custom_input.set(String::new());
74 }
75 show_custom.set(false);
76 });
77
78 let on_custom_dismiss = with!(show_custom => move || {
79 show_custom.set(false);
80 });
81
82 View::vstack()
83 .spacing(1)
84 .child(
85 // Header
86 View::boxed()
87 .border(true)
88 .padding(1)
89 .child(
90 View::vstack()
91 .child(View::styled_text("Modal Dialogs Demo").bold().build())
92 .child(
93 View::styled_text("Click buttons to open different modal types")
94 .dim()
95 .build(),
96 )
97 .build(),
98 )
99 .build(),
100 )
101 .child(
102 // Main content
103 View::boxed()
104 .flex(1)
105 .border(true)
106 .padding(1)
107 .child(
108 View::vstack()
109 .spacing(1)
110 .child(View::text("Modal Types:"))
111 .child(
112 View::hstack()
113 .spacing(2)
114 .child(
115 View::button()
116 .label("Confirm Dialog")
117 .on_press(open_confirm)
118 .build(),
119 )
120 .child(
121 View::button()
122 .label("Alert Dialog")
123 .on_press(open_alert)
124 .build(),
125 )
126 .child(
127 View::button()
128 .label("Custom Modal")
129 .on_press(open_custom)
130 .build(),
131 )
132 .build(),
133 )
134 .child(View::spacer())
135 .child(
136 View::styled_text(format!(
137 "Deleted items: {}",
138 deleted_count.get()
139 ))
140 .color(Color::Yellow)
141 .build(),
142 )
143 .child(
144 View::styled_text(format!("Last action: {}", last_action.get()))
145 .dim()
146 .build(),
147 )
148 .child(View::styled_text("F1 help • Ctrl+Q quit").dim().build())
149 .build(),
150 )
151 .build(),
152 )
153 // Help modal
154 .child(
155 View::modal()
156 .visible(show_help.get())
157 .title("Example 23: Modal")
158 .on_dismiss(with!(show_help => move || show_help.set(false)))
159 .child(
160 View::vstack()
161 .child(View::styled_text("What you're seeing").bold().build())
162 .child(View::text("• Confirm, alert, and custom modals"))
163 .child(View::text("• Modal focus containment"))
164 .child(View::text("• Escape to dismiss"))
165 .child(View::gap(1))
166 .child(View::styled_text("Key concepts").bold().build())
167 .child(View::text("• View::modal() creates overlay"))
168 .child(View::text("• .visible() controls show/hide"))
169 .child(View::text("• .on_dismiss() handles Escape"))
170 .child(View::text("• Focus trapped in open modal"))
171 .child(View::gap(1))
172 .child(View::styled_text("Try this").bold().build())
173 .child(View::text("• Open confirm, click Yes/No"))
174 .child(View::text("• Custom modal has text input"))
175 .child(View::text("• Press Escape to close modals"))
176 .child(View::gap(1))
177 .child(View::styled_text("Next up").bold().build())
178 .child(View::text("→ 24_async_data: async loading"))
179 .child(View::gap(1))
180 .child(View::styled_text("Press Escape to close").dim().build())
181 .build(),
182 )
183 .build(),
184 )
185 // Confirm dialog modal
186 .child(
187 View::modal()
188 .visible(show_confirm.get())
189 .title("Confirm Delete")
190 .on_dismiss(on_confirm_no.clone())
191 .width(40)
192 .height(30)
193 .child(
194 View::vstack()
195 .spacing(1)
196 .child(View::text("Are you sure you want to delete this item?"))
197 .child(View::text("This action cannot be undone."))
198 .child(View::spacer())
199 .child(
200 View::hstack()
201 .spacing(2)
202 .child(
203 View::button()
204 .label("Yes, Delete")
205 .on_press(on_confirm_yes)
206 .build(),
207 )
208 .child(
209 View::button()
210 .label("Cancel")
211 .on_press(on_confirm_no)
212 .build(),
213 )
214 .build(),
215 )
216 .build(),
217 )
218 .build(),
219 )
220 // Alert dialog modal
221 .child(
222 View::modal()
223 .visible(show_alert.get())
224 .title("Alert")
225 .on_dismiss(on_alert_dismiss.clone())
226 .width(50)
227 .height(25)
228 .child(
229 View::vstack()
230 .spacing(1)
231 .child(
232 View::styled_text("Operation completed successfully!")
233 .color(Color::Green)
234 .build(),
235 )
236 .child(View::text("Your changes have been saved."))
237 .child(View::spacer())
238 .child(
239 View::button()
240 .label("OK")
241 .on_press(on_alert_dismiss)
242 .build(),
243 )
244 .build(),
245 )
246 .build(),
247 )
248 // Custom modal with input
249 .child(
250 View::modal()
251 .visible(show_custom.get())
252 .title("Enter Details")
253 .on_dismiss(on_custom_dismiss.clone())
254 .width(50)
255 .height(40)
256 .child(
257 View::vstack()
258 .spacing(1)
259 .child(View::text("Enter a value:"))
260 .child(
261 View::text_input()
262 .value(custom_input.get())
263 .placeholder("Type something...")
264 .on_change(with!(custom_input => move |v: String| {
265 custom_input.set(v);
266 }))
267 .build(),
268 )
269 .child(View::spacer())
270 .child(
271 View::hstack()
272 .spacing(2)
273 .child(
274 View::button()
275 .label("Save")
276 .on_press(on_custom_save)
277 .build(),
278 )
279 .child(
280 View::button()
281 .label("Cancel")
282 .on_press(on_custom_dismiss)
283 .build(),
284 )
285 .build(),
286 )
287 .build(),
288 )
289 .build(),
290 )
291 .build()
292 }Sourcepub fn build(self) -> View
pub fn build(self) -> View
Examples found in repository?
examples/01_hello_world.rs (line 65)
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
examples/30_image.rs (line 80)
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 90)
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 91)
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 104)
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 116)
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 }Additional examples can be found in:
- examples/35_slider.rs
- examples/15_markdown.rs
- examples/18_progress_bar.rs
- examples/16_tree.rs
- examples/05_todo_list.rs
- examples/37_error_boundary.rs
- examples/38_custom_widget.rs
- examples/10_state_explained.rs
- examples/32_effects.rs
- examples/13_split_panes.rs
- examples/07_file_browser.rs
- examples/12_text_area.rs
- examples/06_log_viewer.rs
- examples/24_async_data.rs
- examples/34_channels_and_intervals.rs
- examples/08_system_monitor.rs
- examples/39_port.rs
- examples/25_context.rs
- examples/14_tabs.rs
- examples/11_checkbox.rs
- examples/17_table.rs
- examples/29_canvas.rs
- examples/20_menu_bar.rs
- examples/26_radio_buttons.rs
- examples/21_toasts.rs
- examples/36_reducer.rs
- examples/03_theme_switcher.rs
- examples/28_shared_state.rs
- examples/27_keyed_state.rs
- examples/31_animated_canvas.rs
- examples/22_forms.rs
- examples/23_modal.rs
Trait Implementations§
Source§impl Default for ModalBuilder
impl Default for ModalBuilder
Source§fn default() -> ModalBuilder
fn default() -> ModalBuilder
Returns the “default value” for a type. Read more
Auto Trait Implementations§
impl Freeze for ModalBuilder
impl !RefUnwindSafe for ModalBuilder
impl !Send for ModalBuilder
impl !Sync for ModalBuilder
impl Unpin for ModalBuilder
impl !UnwindSafe for ModalBuilder
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
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>
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)
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)
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.