XenGui (pronounced /ˈzɛn.ɡuː.aɪ/) is a retained-mode rendering GUI implementation in pure Rust, built on the wgpu graphics API and winit window management. It combines a hooks-based retained-mode model with a Flexbox/Grid layout engine (powered by taffy) and a batched wgpu rendering pipeline, running natively on Windows, macOS, and Linux, as well as in the browser via WebAssembly.
Important
XenGui is currently an early development release. APIs are still evolving and may change without notice between versions. Use with caution in production projects and expect breaking changes until a stable 1.0.0 release.
View::new()
.display(Display::Flex)
.flex_direction(FlexDirection::Column)
.align_items(Align::Center)
.justify_content(JustifyContent::Center)
.width(Length::Percent(100.0))
.height(Length::Percent(100.0))
.background(Color::WHITE)
.child(
Label::new()
.label(format!("Count: {counter}"))
.font_size(20)
.color(Color::NEUTRAL_700)
)
.child(
Button::new()
.label("Increment")
.padding(Edges::symmetric(12, 8))
.background(Color::NEUTRAL_200)
.on_click(move |_ctx| set_counter.update(|v| *v += 1))
);- Retained-mode state - React-style hooks (
use_state,component) drive re-renders without a virtual DOM diffing framework bolted on top. - Flexbox & Grid layout - Layout system via
taffy, including flex direction, wrapping, alignment, gaps, and grid tracks. - GPU-accelerated rendering - Rects, text, and images are batched and drawn through dedicated
wgpupipelines. - Declarative styling -
Style/StyleBuilderAPI covering colors (including OKLCH), borders, typography, spacing, and more. - Built-in widgets -
View,Label,Button,Link,TextBox,Image,Svg, andContextMenu, each with hover/pressed/focus/disabled style variants. - Interaction system - Unified handling of hover, click, focus, and keyboard events across widgets.
- Cross-platform - Native targets (Windows, macOS, Linux) and WebAssembly from a single codebase.
XenGui is split across several focused crates:
| Crate | Description |
|---|---|
xengui |
The core retained-mode GUI library: widget tree, hooks, layout, styling, and reconciler. |
xenframe |
Platform runtime: window creation, event loop, and input integration via winit. |
xengui-wgpu |
The wgpu render backend implementing xengui's RenderBackend trait. |
xen-animation |
Framework-agnostic animation and transition library. |
xen-clipboard |
Cross-platform clipboard library. |
xen-svg |
Platform-agnostic SVG parser and triangle tessellator. |
xengui-icons |
Prebuilt Lucide icon widgets for XenGui. |
Cargo.toml
[dependencies]
xengui = "0.2.7"
xenframe = "0.1.1"
xengui-wgpu = "0.1.1"use xengui::*;
use xenframe::{App, AppConfig, WindowPosition};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = AppConfig {
title: "My XenGui App".into(),
width: 640,
height: 480,
position: WindowPosition::Center,
..Default::default()
};
let mut app = App::new(config);
app.render(|| {
let (counter, set_counter) = use_state::<i32>(0);
Box::new(
View::new()
.display(Display::Flex)
.flex_direction(FlexDirection::Column)
.align_items(Align::Center)
.justify_content(JustifyContent::Center)
.width(Length::Percent(100.0))
.height(Length::Percent(100.0))
.background(Color::WHITE)
.child(
Label::new()
.label(format!("Count: {counter}"))
.font_size(20)
.color(Color::NEUTRAL_700)
)
.child(
Button::new()
.label("Increment")
.padding(Edges::symmetric(12, 8))
.background(Color::NEUTRAL_200)
.on_click(move |_ctx| set_counter.update(|v| *v += 1))
)
)
});
if let Err(e) = app.run() {
eprintln!("Error running app: {:?}", e);
}
Ok(())
}Run it with:
cargo runFor WebAssembly targets, build and serve with Trunk:
trunk serveDocs are available at: https://xengui.vercel.app/docs
Apache License 2.0 © 2026 randseas. See LICENSE for details.