pub struct Panel {
pub title: Option<String>,
pub border: BorderStyle,
pub shadow: bool,
}Expand description
A bordered container panel with optional title and shadow.
Fields§
§title: Option<String>§border: BorderStyle§shadow: boolImplementations§
Source§impl Panel
impl Panel
pub fn new() -> Self
Sourcepub fn titled(title: impl Into<String>) -> Self
pub fn titled(title: impl Into<String>) -> Self
Examples found in repository?
examples/fancyui.rs (line 37)
24fn setup(world: &mut World) {
25 world.insert_resource(FrameCount(0));
26
27 // Root container fills the terminal
28 let root = world.spawn((
29 Node::new(0, 0, 0, 0),
30 Container,
31 Anchor::fill(),
32 ));
33
34 // ═══ Header Panel ═══
35 let header = world.spawn((
36 Node::new(0, 0, 0, 0),
37 Panel::titled("\u{2726} Decay Fancy UI").border(BorderStyle::Double).shadow(),
38 UiStyle::fg(90, 130, 220),
39 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 1, -2, 4) },
40 Parent(root),
41 ));
42
43 // Subtitle inside panel
44 world.spawn((
45 Node::new(0, 0, 0, 0),
46 Text::new("zero-dependency TUI framework"),
47 UiStyle { fg: Some((130, 130, 145)), italic: true, ..UiStyle::new() },
48 TextAlign::Center,
49 Anchor { min: (0.0, 0.0), max: (1.0, 1.0), offset: (2, 1, -2, -1) },
50 Parent(header),
51 ));
52
53 // ─── System Monitor ───
54 world.spawn((
55 Node::new(0, 0, 0, 0),
56 Separator::labeled("System Monitor"),
57 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 4, -2, 5) },
58 Parent(root),
59 ));
60
61 // Progress bar labels
62 world.spawn((
63 Node::new(0, 0, 0, 0), Text::new("CPU"), UiStyle::dim(),
64 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 5, 11, 6) },
65 Parent(root),
66 ));
67 world.spawn((
68 Node::new(0, 0, 0, 0), Text::new("Memory"), UiStyle::dim(),
69 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 6, 11, 7) },
70 Parent(root),
71 ));
72 world.spawn((
73 Node::new(0, 0, 0, 0), Text::new("Disk"), UiStyle::dim(),
74 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 7, 11, 8) },
75 Parent(root),
76 ));
77 world.spawn((
78 Node::new(0, 0, 0, 0), Text::new("Network"), UiStyle::dim(),
79 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 8, 11, 9) },
80 Parent(root),
81 ));
82
83 // Progress bars (proportional width)
84 let cpu = world.spawn((
85 Node::new(0, 0, 0, 0),
86 ProgressBar::new(0.64).with_gradient((255, 100, 80)).with_label(),
87 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 5, 0, 6) },
88 Parent(root),
89 ));
90 let mem = world.spawn((
91 Node::new(0, 0, 0, 0),
92 ProgressBar::new(0.78)
93 .with_gradient((100, 180, 255))
94 .with_label()
95 .with_colors((60, 160, 240), (40, 40, 50)),
96 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 6, 0, 7) },
97 Parent(root),
98 ));
99 let disk = world.spawn((
100 Node::new(0, 0, 0, 0),
101 ProgressBar::new(0.21).with_label(),
102 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 7, 0, 8) },
103 Parent(root),
104 ));
105 let net = world.spawn((
106 Node::new(0, 0, 0, 0),
107 ProgressBar::classic(0.45)
108 .with_colors((200, 180, 60), (50, 50, 60))
109 .with_label(),
110 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 8, 0, 9) },
111 Parent(root),
112 ));
113 world.insert_resource(Bars { cpu, mem, disk, net });
114
115 // ─── Controls ───
116 world.spawn((
117 Node::new(0, 0, 0, 0),
118 Separator::labeled("Controls"),
119 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 10, -2, 11) },
120 Parent(root),
121 ));
122
123 // Buttons (2x2 grid, proportional width)
124 world.spawn((
125 Node::new(0, 0, 0, 0),
126 Text::new("Dashboard"), Button, Interaction::None,
127 Anchor { min: (0.0, 0.0), max: (0.48, 0.0), offset: (3, 11, 0, 14) },
128 Parent(root),
129 ));
130 world.spawn((
131 Node::new(0, 0, 0, 0),
132 Text::new("Reports"), Button, Interaction::None,
133 Anchor { min: (0.5, 0.0), max: (1.0, 0.0), offset: (0, 11, -2, 14) },
134 Parent(root),
135 ));
136 world.spawn((
137 Node::new(0, 0, 0, 0),
138 Text::new("Settings"), Button, Interaction::None,
139 Anchor { min: (0.0, 0.0), max: (0.48, 0.0), offset: (3, 14, 0, 17) },
140 Parent(root),
141 ));
142 world.spawn((
143 Node::new(0, 0, 0, 0),
144 Text::new("Exit"), Button, Interaction::None,
145 Anchor { min: (0.5, 0.0), max: (1.0, 0.0), offset: (0, 14, -2, 17) },
146 Parent(root),
147 ));
148
149 // ─── Activity ───
150 world.spawn((
151 Node::new(0, 0, 0, 0),
152 Separator::labeled("Activity"),
153 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 17, -2, 18) },
154 Parent(root),
155 ));
156
157 // Spinner
158 world.spawn((
159 Node::new(0, 0, 0, 0),
160 Spinner::new(SpinnerStyle::Dots).with_label("Processing data..."),
161 UiStyle::fg(100, 200, 255),
162 Anchor { min: (0.0, 0.0), max: (0.5, 0.0), offset: (3, 18, 0, 19) },
163 Parent(root),
164 ));
165
166 // Animated typewriter text
167 world.spawn((
168 Node::new(0, 0, 0, 0),
169 AnimatedText::new("The quick brown fox jumps over the lazy dog", 15.0),
170 UiStyle::fg(180, 180, 195),
171 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 19, 0, 20) },
172 Parent(root),
173 ));
174
175 // Status
176 let status = world.spawn((
177 Node::new(0, 0, 0, 0),
178 Text::new("Select a button and press Enter..."),
179 UiStyle::dim(),
180 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 21, 0, 22) },
181 Parent(root),
182 ));
183 world.insert_resource(StatusLabel(status));
184
185 // Footer
186 world.spawn((
187 Node::new(0, 0, 0, 0),
188 Text::new("\u{2191}\u{2193}/Tab Navigate Enter/Space Click q Quit"),
189 UiStyle::dim(),
190 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 22, 0, 23) },
191 Parent(root),
192 ));
193}Sourcepub fn border(self, style: BorderStyle) -> Self
pub fn border(self, style: BorderStyle) -> Self
Examples found in repository?
examples/fancyui.rs (line 37)
24fn setup(world: &mut World) {
25 world.insert_resource(FrameCount(0));
26
27 // Root container fills the terminal
28 let root = world.spawn((
29 Node::new(0, 0, 0, 0),
30 Container,
31 Anchor::fill(),
32 ));
33
34 // ═══ Header Panel ═══
35 let header = world.spawn((
36 Node::new(0, 0, 0, 0),
37 Panel::titled("\u{2726} Decay Fancy UI").border(BorderStyle::Double).shadow(),
38 UiStyle::fg(90, 130, 220),
39 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 1, -2, 4) },
40 Parent(root),
41 ));
42
43 // Subtitle inside panel
44 world.spawn((
45 Node::new(0, 0, 0, 0),
46 Text::new("zero-dependency TUI framework"),
47 UiStyle { fg: Some((130, 130, 145)), italic: true, ..UiStyle::new() },
48 TextAlign::Center,
49 Anchor { min: (0.0, 0.0), max: (1.0, 1.0), offset: (2, 1, -2, -1) },
50 Parent(header),
51 ));
52
53 // ─── System Monitor ───
54 world.spawn((
55 Node::new(0, 0, 0, 0),
56 Separator::labeled("System Monitor"),
57 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 4, -2, 5) },
58 Parent(root),
59 ));
60
61 // Progress bar labels
62 world.spawn((
63 Node::new(0, 0, 0, 0), Text::new("CPU"), UiStyle::dim(),
64 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 5, 11, 6) },
65 Parent(root),
66 ));
67 world.spawn((
68 Node::new(0, 0, 0, 0), Text::new("Memory"), UiStyle::dim(),
69 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 6, 11, 7) },
70 Parent(root),
71 ));
72 world.spawn((
73 Node::new(0, 0, 0, 0), Text::new("Disk"), UiStyle::dim(),
74 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 7, 11, 8) },
75 Parent(root),
76 ));
77 world.spawn((
78 Node::new(0, 0, 0, 0), Text::new("Network"), UiStyle::dim(),
79 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 8, 11, 9) },
80 Parent(root),
81 ));
82
83 // Progress bars (proportional width)
84 let cpu = world.spawn((
85 Node::new(0, 0, 0, 0),
86 ProgressBar::new(0.64).with_gradient((255, 100, 80)).with_label(),
87 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 5, 0, 6) },
88 Parent(root),
89 ));
90 let mem = world.spawn((
91 Node::new(0, 0, 0, 0),
92 ProgressBar::new(0.78)
93 .with_gradient((100, 180, 255))
94 .with_label()
95 .with_colors((60, 160, 240), (40, 40, 50)),
96 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 6, 0, 7) },
97 Parent(root),
98 ));
99 let disk = world.spawn((
100 Node::new(0, 0, 0, 0),
101 ProgressBar::new(0.21).with_label(),
102 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 7, 0, 8) },
103 Parent(root),
104 ));
105 let net = world.spawn((
106 Node::new(0, 0, 0, 0),
107 ProgressBar::classic(0.45)
108 .with_colors((200, 180, 60), (50, 50, 60))
109 .with_label(),
110 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 8, 0, 9) },
111 Parent(root),
112 ));
113 world.insert_resource(Bars { cpu, mem, disk, net });
114
115 // ─── Controls ───
116 world.spawn((
117 Node::new(0, 0, 0, 0),
118 Separator::labeled("Controls"),
119 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 10, -2, 11) },
120 Parent(root),
121 ));
122
123 // Buttons (2x2 grid, proportional width)
124 world.spawn((
125 Node::new(0, 0, 0, 0),
126 Text::new("Dashboard"), Button, Interaction::None,
127 Anchor { min: (0.0, 0.0), max: (0.48, 0.0), offset: (3, 11, 0, 14) },
128 Parent(root),
129 ));
130 world.spawn((
131 Node::new(0, 0, 0, 0),
132 Text::new("Reports"), Button, Interaction::None,
133 Anchor { min: (0.5, 0.0), max: (1.0, 0.0), offset: (0, 11, -2, 14) },
134 Parent(root),
135 ));
136 world.spawn((
137 Node::new(0, 0, 0, 0),
138 Text::new("Settings"), Button, Interaction::None,
139 Anchor { min: (0.0, 0.0), max: (0.48, 0.0), offset: (3, 14, 0, 17) },
140 Parent(root),
141 ));
142 world.spawn((
143 Node::new(0, 0, 0, 0),
144 Text::new("Exit"), Button, Interaction::None,
145 Anchor { min: (0.5, 0.0), max: (1.0, 0.0), offset: (0, 14, -2, 17) },
146 Parent(root),
147 ));
148
149 // ─── Activity ───
150 world.spawn((
151 Node::new(0, 0, 0, 0),
152 Separator::labeled("Activity"),
153 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 17, -2, 18) },
154 Parent(root),
155 ));
156
157 // Spinner
158 world.spawn((
159 Node::new(0, 0, 0, 0),
160 Spinner::new(SpinnerStyle::Dots).with_label("Processing data..."),
161 UiStyle::fg(100, 200, 255),
162 Anchor { min: (0.0, 0.0), max: (0.5, 0.0), offset: (3, 18, 0, 19) },
163 Parent(root),
164 ));
165
166 // Animated typewriter text
167 world.spawn((
168 Node::new(0, 0, 0, 0),
169 AnimatedText::new("The quick brown fox jumps over the lazy dog", 15.0),
170 UiStyle::fg(180, 180, 195),
171 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 19, 0, 20) },
172 Parent(root),
173 ));
174
175 // Status
176 let status = world.spawn((
177 Node::new(0, 0, 0, 0),
178 Text::new("Select a button and press Enter..."),
179 UiStyle::dim(),
180 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 21, 0, 22) },
181 Parent(root),
182 ));
183 world.insert_resource(StatusLabel(status));
184
185 // Footer
186 world.spawn((
187 Node::new(0, 0, 0, 0),
188 Text::new("\u{2191}\u{2193}/Tab Navigate Enter/Space Click q Quit"),
189 UiStyle::dim(),
190 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 22, 0, 23) },
191 Parent(root),
192 ));
193}Sourcepub fn shadow(self) -> Self
pub fn shadow(self) -> Self
Examples found in repository?
examples/fancyui.rs (line 37)
24fn setup(world: &mut World) {
25 world.insert_resource(FrameCount(0));
26
27 // Root container fills the terminal
28 let root = world.spawn((
29 Node::new(0, 0, 0, 0),
30 Container,
31 Anchor::fill(),
32 ));
33
34 // ═══ Header Panel ═══
35 let header = world.spawn((
36 Node::new(0, 0, 0, 0),
37 Panel::titled("\u{2726} Decay Fancy UI").border(BorderStyle::Double).shadow(),
38 UiStyle::fg(90, 130, 220),
39 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 1, -2, 4) },
40 Parent(root),
41 ));
42
43 // Subtitle inside panel
44 world.spawn((
45 Node::new(0, 0, 0, 0),
46 Text::new("zero-dependency TUI framework"),
47 UiStyle { fg: Some((130, 130, 145)), italic: true, ..UiStyle::new() },
48 TextAlign::Center,
49 Anchor { min: (0.0, 0.0), max: (1.0, 1.0), offset: (2, 1, -2, -1) },
50 Parent(header),
51 ));
52
53 // ─── System Monitor ───
54 world.spawn((
55 Node::new(0, 0, 0, 0),
56 Separator::labeled("System Monitor"),
57 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 4, -2, 5) },
58 Parent(root),
59 ));
60
61 // Progress bar labels
62 world.spawn((
63 Node::new(0, 0, 0, 0), Text::new("CPU"), UiStyle::dim(),
64 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 5, 11, 6) },
65 Parent(root),
66 ));
67 world.spawn((
68 Node::new(0, 0, 0, 0), Text::new("Memory"), UiStyle::dim(),
69 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 6, 11, 7) },
70 Parent(root),
71 ));
72 world.spawn((
73 Node::new(0, 0, 0, 0), Text::new("Disk"), UiStyle::dim(),
74 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 7, 11, 8) },
75 Parent(root),
76 ));
77 world.spawn((
78 Node::new(0, 0, 0, 0), Text::new("Network"), UiStyle::dim(),
79 Anchor { min: (0.0, 0.0), max: (0.0, 0.0), offset: (3, 8, 11, 9) },
80 Parent(root),
81 ));
82
83 // Progress bars (proportional width)
84 let cpu = world.spawn((
85 Node::new(0, 0, 0, 0),
86 ProgressBar::new(0.64).with_gradient((255, 100, 80)).with_label(),
87 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 5, 0, 6) },
88 Parent(root),
89 ));
90 let mem = world.spawn((
91 Node::new(0, 0, 0, 0),
92 ProgressBar::new(0.78)
93 .with_gradient((100, 180, 255))
94 .with_label()
95 .with_colors((60, 160, 240), (40, 40, 50)),
96 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 6, 0, 7) },
97 Parent(root),
98 ));
99 let disk = world.spawn((
100 Node::new(0, 0, 0, 0),
101 ProgressBar::new(0.21).with_label(),
102 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 7, 0, 8) },
103 Parent(root),
104 ));
105 let net = world.spawn((
106 Node::new(0, 0, 0, 0),
107 ProgressBar::classic(0.45)
108 .with_colors((200, 180, 60), (50, 50, 60))
109 .with_label(),
110 Anchor { min: (0.15, 0.0), max: (0.55, 0.0), offset: (0, 8, 0, 9) },
111 Parent(root),
112 ));
113 world.insert_resource(Bars { cpu, mem, disk, net });
114
115 // ─── Controls ───
116 world.spawn((
117 Node::new(0, 0, 0, 0),
118 Separator::labeled("Controls"),
119 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 10, -2, 11) },
120 Parent(root),
121 ));
122
123 // Buttons (2x2 grid, proportional width)
124 world.spawn((
125 Node::new(0, 0, 0, 0),
126 Text::new("Dashboard"), Button, Interaction::None,
127 Anchor { min: (0.0, 0.0), max: (0.48, 0.0), offset: (3, 11, 0, 14) },
128 Parent(root),
129 ));
130 world.spawn((
131 Node::new(0, 0, 0, 0),
132 Text::new("Reports"), Button, Interaction::None,
133 Anchor { min: (0.5, 0.0), max: (1.0, 0.0), offset: (0, 11, -2, 14) },
134 Parent(root),
135 ));
136 world.spawn((
137 Node::new(0, 0, 0, 0),
138 Text::new("Settings"), Button, Interaction::None,
139 Anchor { min: (0.0, 0.0), max: (0.48, 0.0), offset: (3, 14, 0, 17) },
140 Parent(root),
141 ));
142 world.spawn((
143 Node::new(0, 0, 0, 0),
144 Text::new("Exit"), Button, Interaction::None,
145 Anchor { min: (0.5, 0.0), max: (1.0, 0.0), offset: (0, 14, -2, 17) },
146 Parent(root),
147 ));
148
149 // ─── Activity ───
150 world.spawn((
151 Node::new(0, 0, 0, 0),
152 Separator::labeled("Activity"),
153 Anchor { min: (0.0, 0.0), max: (1.0, 0.0), offset: (2, 17, -2, 18) },
154 Parent(root),
155 ));
156
157 // Spinner
158 world.spawn((
159 Node::new(0, 0, 0, 0),
160 Spinner::new(SpinnerStyle::Dots).with_label("Processing data..."),
161 UiStyle::fg(100, 200, 255),
162 Anchor { min: (0.0, 0.0), max: (0.5, 0.0), offset: (3, 18, 0, 19) },
163 Parent(root),
164 ));
165
166 // Animated typewriter text
167 world.spawn((
168 Node::new(0, 0, 0, 0),
169 AnimatedText::new("The quick brown fox jumps over the lazy dog", 15.0),
170 UiStyle::fg(180, 180, 195),
171 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 19, 0, 20) },
172 Parent(root),
173 ));
174
175 // Status
176 let status = world.spawn((
177 Node::new(0, 0, 0, 0),
178 Text::new("Select a button and press Enter..."),
179 UiStyle::dim(),
180 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 21, 0, 22) },
181 Parent(root),
182 ));
183 world.insert_resource(StatusLabel(status));
184
185 // Footer
186 world.spawn((
187 Node::new(0, 0, 0, 0),
188 Text::new("\u{2191}\u{2193}/Tab Navigate Enter/Space Click q Quit"),
189 UiStyle::dim(),
190 Anchor { min: (0.0, 0.0), max: (0.8, 0.0), offset: (3, 22, 0, 23) },
191 Parent(root),
192 ));
193}Trait Implementations§
Auto Trait Implementations§
impl Freeze for Panel
impl RefUnwindSafe for Panel
impl Send for Panel
impl Sync for Panel
impl Unpin for Panel
impl UnsafeUnpin for Panel
impl UnwindSafe for Panel
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