pub struct Elements { /* private fields */ }Expand description
A list of component descriptions for declarative tree building.
Elements is what view functions return and what the framework
reconciles against the existing component tree. Build one with the
element! macro or the imperative API:
// With the element! macro (preferred):
fn my_view(state: &MyState) -> Elements {
element! {
"Hello"
#(if state.loading {
Spinner(key: "spinner", label: "Loading...")
})
}
}
// Imperative API:
fn my_view(state: &MyState) -> Elements {
let mut els = Elements::new();
els.add(TextBlock::new().unstyled("Hello"));
if state.loading {
els.add(Spinner::new("Loading...")).key("spinner");
}
els
}Implementations§
Source§impl Elements
impl Elements
Sourcepub fn new() -> Self
pub fn new() -> Self
Create an empty element list.
Examples found in repository?
112fn task_view(state: &AppState) -> Elements {
113 let mut els = Elements::new();
114
115 els.add(
116 TextBlock::new().line(
117 format!("Tasks ({})", state.tasks.len()),
118 Style::default()
119 .fg(Color::White)
120 .add_modifier(Modifier::BOLD),
121 ),
122 );
123
124 for task in &state.tasks {
125 els.add(StatusLog::new(task)).key(task.clone());
126 }
127
128 if state.processing {
129 els.add(Spinner::new("Processing...")).key("spinner");
130 }
131
132 els.add(TextBlock::new().line("---", Style::default().fg(Color::DarkGray)));
133
134 els
135}More examples
41fn chat_view(state: &AppState) -> Elements {
42 let mut els = Elements::new();
43
44 // Render all messages with stable keys
45 for (i, msg) in state.messages.iter().enumerate() {
46 els.add(Markdown::new(msg)).key(format!("msg-{i}"));
47 }
48
49 // Show thinking spinner if active (auto-animates via tick registration)
50 if state.thinking {
51 els.add(Spinner::new("Thinking...")).key("thinking");
52 }
53
54 // Show tool call spinner if active (auto-animates via tick registration)
55 if let Some(ref tool) = state.tool_running {
56 els.add(Spinner::new(format!("Running {}...", tool)))
57 .key("tool");
58 }
59
60 // Separator at the bottom
61 if !state.messages.is_empty() || state.thinking || state.tool_running.is_some() {
62 els.add(TextBlock::new().line("---", Style::default().fg(Color::DarkGray)));
63 }
64
65 els
66}225fn chat_view(state: &AppState) -> Elements {
226 let mut els = Elements::new();
227
228 for msg in &state.messages {
229 let key = format!("msg-{}", msg.id);
230 match &msg.kind {
231 MessageKind::User(text) => {
232 els.add(
233 TextBlock::new().line(
234 format!("> {}", text),
235 Style::default()
236 .fg(Color::Cyan)
237 .add_modifier(Modifier::BOLD),
238 ),
239 )
240 .key(key);
241 }
242 MessageKind::Assistant { content, done } => {
243 if *done {
244 els.add(Markdown::new(content)).key(key);
245 } else if content.is_empty() {
246 els.add(StreamingDots).key(key);
247 } else {
248 // Show content with a blinking cursor
249 els.add(Markdown::new(format!("{}▌", content))).key(key);
250 }
251 }
252 }
253 }
254
255 // Separator
256 els.add(TextBlock::new());
257
258 // Input box
259 els.add(InputBox {
260 text: state.input.clone(),
261 cursor: state.cursor,
262 prompt: "You".into(),
263 })
264 .key("input");
265
266 els
267}Sourcepub fn add<C: Component>(&mut self, component: C) -> ElementHandle<'_>
pub fn add<C: Component>(&mut self, component: C) -> ElementHandle<'_>
Add a component to the list.
Returns an ElementHandle that can be used to set a key
for stable identity across rebuilds.
Examples found in repository?
112fn task_view(state: &AppState) -> Elements {
113 let mut els = Elements::new();
114
115 els.add(
116 TextBlock::new().line(
117 format!("Tasks ({})", state.tasks.len()),
118 Style::default()
119 .fg(Color::White)
120 .add_modifier(Modifier::BOLD),
121 ),
122 );
123
124 for task in &state.tasks {
125 els.add(StatusLog::new(task)).key(task.clone());
126 }
127
128 if state.processing {
129 els.add(Spinner::new("Processing...")).key("spinner");
130 }
131
132 els.add(TextBlock::new().line("---", Style::default().fg(Color::DarkGray)));
133
134 els
135}More examples
41fn chat_view(state: &AppState) -> Elements {
42 let mut els = Elements::new();
43
44 // Render all messages with stable keys
45 for (i, msg) in state.messages.iter().enumerate() {
46 els.add(Markdown::new(msg)).key(format!("msg-{i}"));
47 }
48
49 // Show thinking spinner if active (auto-animates via tick registration)
50 if state.thinking {
51 els.add(Spinner::new("Thinking...")).key("thinking");
52 }
53
54 // Show tool call spinner if active (auto-animates via tick registration)
55 if let Some(ref tool) = state.tool_running {
56 els.add(Spinner::new(format!("Running {}...", tool)))
57 .key("tool");
58 }
59
60 // Separator at the bottom
61 if !state.messages.is_empty() || state.thinking || state.tool_running.is_some() {
62 els.add(TextBlock::new().line("---", Style::default().fg(Color::DarkGray)));
63 }
64
65 els
66}225fn chat_view(state: &AppState) -> Elements {
226 let mut els = Elements::new();
227
228 for msg in &state.messages {
229 let key = format!("msg-{}", msg.id);
230 match &msg.kind {
231 MessageKind::User(text) => {
232 els.add(
233 TextBlock::new().line(
234 format!("> {}", text),
235 Style::default()
236 .fg(Color::Cyan)
237 .add_modifier(Modifier::BOLD),
238 ),
239 )
240 .key(key);
241 }
242 MessageKind::Assistant { content, done } => {
243 if *done {
244 els.add(Markdown::new(content)).key(key);
245 } else if content.is_empty() {
246 els.add(StreamingDots).key(key);
247 } else {
248 // Show content with a blinking cursor
249 els.add(Markdown::new(format!("{}▌", content))).key(key);
250 }
251 }
252 }
253 }
254
255 // Separator
256 els.add(TextBlock::new());
257
258 // Input box
259 els.add(InputBox {
260 text: state.input.clone(),
261 cursor: state.cursor,
262 prompt: "You".into(),
263 })
264 .key("input");
265
266 els
267}Sourcepub fn add_with_children<C: Component>(
&mut self,
component: C,
children: Elements,
) -> ElementHandle<'_>
pub fn add_with_children<C: Component>( &mut self, component: C, children: Elements, ) -> ElementHandle<'_>
Add a component with nested children.
The component is created first, then children are built as its
descendants. The component’s children() method receives
these as the slot parameter.
Sourcepub fn group(&mut self, children: Elements) -> ElementHandle<'_>
pub fn group(&mut self, children: Elements) -> ElementHandle<'_>
Add a VStack wrapper around the given children.
Equivalent to add_with_children(VStack, children).
Sourcepub fn hstack(&mut self, children: Elements) -> ElementHandle<'_>
pub fn hstack(&mut self, children: Elements) -> ElementHandle<'_>
Add an HStack wrapper around the given children.
Children default to WidthConstraint::Fill.
Use .width(WidthConstraint::Fixed(n)) for fixed-width children.
Trait Implementations§
Source§impl<C: Component> AddTo<Elements> for ComponentWithSlot<C>
impl<C: Component> AddTo<Elements> for ComponentWithSlot<C>
Source§type Handle<'a> = ElementHandle<'a>
type Handle<'a> = ElementHandle<'a>
.key() / .width() chaining.Source§fn add_to(self, els: &mut Elements) -> ElementHandle<'_>
fn add_to(self, els: &mut Elements) -> ElementHandle<'_>
.key() and .width().Source§impl SpliceInto<Elements> for Elements
impl SpliceInto<Elements> for Elements
Source§fn splice_into(self, collector: &mut Elements)
fn splice_into(self, collector: &mut Elements)
Auto Trait Implementations§
impl Freeze for Elements
impl !RefUnwindSafe for Elements
impl Send for Elements
impl !Sync for Elements
impl Unpin for Elements
impl UnsafeUnpin for Elements
impl !UnwindSafe for Elements
Blanket Implementations§
Source§impl<C> AddTo<Elements> for Cwhere
C: Component,
impl<C> AddTo<Elements> for Cwhere
C: Component,
Source§type Handle<'a> = ElementHandle<'a>
type Handle<'a> = ElementHandle<'a>
.key() / .width() chaining.Source§fn add_to(self, els: &mut Elements) -> ElementHandle<'_>
fn add_to(self, els: &mut Elements) -> ElementHandle<'_>
.key() and .width().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
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more