Haven handles windowing, layout, rendering, state, and user interaction for native Rust apps.
Built with winit, backer, anyrender, and parley.
This library is functional but experimental. API stability is not a goal at this stage & it is likely you will encounter bugs.
- Declarative API: The code should look like the structure it defines
- Flexible layout: Constraint-based layout powered by backer
- App runtime: Winit integration for running panes
- Multiple windows: Run more than one pane from the same app
- Headless interaction: Drive panes directly for automated testing
- Rendering: Anyrender with Vello by default
- Interaction: Gestures, text editing, scrolling, buttons, toggles, sliders, and dropdowns
Warning
Limitations:
Haven is probably not a good choice right now if you need:
- Accessibility
- Video or gif support
- Rotation
- Robust effects like blurs or complex shadows
- A stable, mature library which will rarely have bugs
Define some state, write a view function, and pass that view into a pane.
use haven::winit::WinitApp;
use haven::*;
#[derive(Clone, Default)]
struct State {
count: i32,
button: ButtonState,
}
fn view<'a>(state: &'a State, app: &mut PaneState) -> View<'a, State> {
column_spaced(
20.,
vec![
text(id!(), format!("Count: {}", state.count))
.fill(Color::WHITE)
.build(app),
button(id!(), binding!(state.button))
.text_label("Increment")
.on_click(|state, _app| state.count += 1)
.build(app),
],
)
.pad(20.)
}
fn main() {
WinitApp::new(State::default())
.pane(
PaneBuilder::new("main", view)
.title("Counter")
.inner_size(320, 180),
)
.run();
}Examples can be run directly with cargo run --example <name>.
buttons: Button styling, labels, and click handlerstext_fields: Text editing, wrapping, alignment, filtering, and focusscroller: Scrollable content with gesture handlinggestures: Click, hover, drag, predicates, and gesture regionsimage: Loading and drawing image contentasync: Waking panes from async callbacksproductivity: A larger app-shaped example
Haven is usable but new! Breaking changes may be relatively frequent as the crate matures.
This project is unlikely to be able to support any substantial volume of contributions as it's just a hobby project maintained during spare time. If you're interested in seeing a change in the library, feel free to open an issue.