| Crates.io | iris-ui |
| lib.rs | iris-ui |
| version | 0.1.0 |
| created_at | 2025-10-08 17:39:23.355116+00 |
| updated_at | 2025-10-08 17:39:23.355116+00 |
| description | UI toolkit for no_std embedded Rust |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1874261 |
| size | 171,460 |

This is a new GUI library for no_std embedded Rust. I currently have it running on the ESP32-S3 based Lilygo T-Deck, but it should run on anything that uses the embedded_graphics traits. It focuses on bandwidth limited devices, such as SPI displays.
Build the library with cargo build.
Run the simulator example with cargo run --example simulator --features std. Note that
the simulator needs
SDL2. Install instructions.
Run the unit tests with cargo test --features std.
The library has not yet been released as a published crate because I still need a name and need to fix some bugs.
Views are rendered using a Theme which can be customized for different
colors and font sizes. Views carry their own internal state using an
optional state struct. Application state should remain outside the scene/view structure
and be handled by processing actions emitted from the scene when events happen.
Instead of implementing a trait you create components by
allocating a View is with optional fields for functions to handle
input, state, layout, and drawing. This is the code that creates a button (as implemented in the
library provided make_button):
pub fn make_button(name: &ViewId, title: &str) -> View {
View {
name: name.clone(),
title: title.to_string(),
// the button will determine its own width
h_flex: Intrinsic,
// the button will determine its own height
v_flex: Intrinsic,
// on tap, requested to be focused
input: Some(|e| {
if let EventType::Tap(_pt) = &e.event_type {
e.scene.set_focused(e.target);
return Some(Action::Generic);
}
None
}),
// size self based on the font and the title text
layout: Some(|e| {
if let Some(view) = e.scene.get_view_mut(&e.target) {
view.bounds.size = util::calc_size(e.theme.bold_font, &view.title);
}
}),
// delegate drawing to a draw_button function
draw: Some(draw_button),
..Default::default()
}
}
fn draw_button(e: &mut DrawEvent) {
e.ctx.fill_rect(&e.view.bounds, &e.theme.bg);
e.ctx.stroke_rect(&e.view.bounds, &e.theme.fg);
if let Some(focused) = e.focused {
if focused == &e.view.name {
e.ctx.stroke_rect(&e.view.bounds.contract(2), &e.theme.fg);
}
}
draw_centered_text(
e.ctx,
&e.view.title,
&e.view.bounds,
&e.theme.bold_font,
&e.theme.fg,
);
}
Theme is a struct passed to every View's draw function. It stores the standard colors and fonts for drawing.
However, these are just guidelines. A view can feel free to ignore them and draw whatever it wants.
The theme fields should be used for:
selected_bg.input improvements
text input
focus management
improved custom view support
theme accent colors?