Hi! I've been working on zaxis, an immediate-mode GUI library for desktop tools built on winit and wgpu. 0.0.5 is on crates.io. It's an early development release and the API will still change, so I'd like feedback while that's cheap.
crates.io: crates.io: Rust Package Registry
Docs: zaxis · zaxis
Source (MIT): GitHub - nihmadev/zaxis · GitHub
What it is
zaxis::run(app) owns the event loop, repaint scheduling and GPU recovery. You implement App::update and build the UI inside it:
use zaxis::{App, Context, Frame, Window};
#[derive(Default)]
struct Counter(u64);
impl App for Counter {
fn update(&mut self, context: &mut Context, _frame: &mut Frame<'_>) {
Window::new("Counter").show(context, |ui| {
if ui.button("Increment").clicked() {
self.0 += 1;
}
ui.label(format!("Count: {}", self.0));
});
}
}
fn main() -> Result<(), zaxis::RunError> {
zaxis::run(Counter::default())
}
It's event-driven: it repaints only when something needs it, and animations schedule their own next repaint.
Why not egui?
It's the same niche, and egui is far more mature. zaxis is a smaller, independent library with a different packaging of everyday tasks:
built-in motion: hover/reveal transitions, plus tweens, springs and keyframes with automatic repaint deadlines
images and SVG load asynchronously with no loader registration
a larger set of widgets out of the box, including Dock, TreeView, Table, virtualized ListBox, nested popups, PanZoom, an actions/keymap registry
AccessKit integration, with screen-reader checks done on Windows only so far
user WGSL fragment shaders for rectangles ("materials"), and optional iOS-style glass/backdrop blur
The part I'd most like feedback on: embedding
EmbeddedRenderer works over a wgpu::Device/Queue you already own. You can prepare + record into your own render pass, or render_to a texture, with no window involved. Input goes through Context::on_input(InputEvent). See examples/embed.rs (zaxis inside a host's own wgpu scene) and the docs page "Embedding in a wgpu host".
There's also an experimental crate, z-hook, that draws a zaxis UI over another process's frames (a debug overlay, a mod menu, a tool inside a 3D editor) via a Vulkan implicit layer. It's meant for processes you control or that allow it, and it does not inject itself into anything.
Honest status
z-hook: run and checked only for Vulkan on Linux (Mesa) with X11 input. The Windows DXGI/D3D11/D3D12 paths compile but have never been run. No OpenGL, no macOS, no Wayland hosts.
Embedding: pixel-tested on Vulkan (Mesa, Intel) only. Metal, DX12 and a real engine's frame graph were not tried.
Browser: the same zaxis::run builds for wasm32-unknown-unknown (WebGPU, WebGL2 fallback), but only Chrome has been checked.
Accessibility: UI Automation tested with Narrator on Windows 11. NVDA, JAWS, VoiceOver and Orca have not been tried.
Text: complex shaping and bidi work, but no italic, no variable-font axes, and the multi-line TextEdit has no search or completion.
The full list is in the docs under "Limitations".
What I'd like to hear
Is the App::update + zaxis::run shape reasonable, or would you want something different?
If you embed immediate-mode UIs in your own wgpu renderer, what is missing from EmbeddedRenderer?
If you have a Windows/macOS GPU setup, running cargo run --example demo and cargo run --release --example embed and telling me what breaks would help a lot.
Issues and PRs are welcome on GitHub. Thanks for reading!
(Disclosure: parts of the code and documentation were written with AI assistance and reviewed by me.)
1 post - 1 participant
Read full topic
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | [Project] sol: A self-contained browser kernel written in Rust | 0 | 9.76 | 18-10-2026 |
| 2 | I made a Vibe-Coded Reusable Application Runtime For Any Digital Domain (Office apps, Digital Painter, Graph nodes based apps..etc) | 0 | 17.83 | 12-10-2026 |
| 3 | Hotcode: easy to use hot-reload | 0 | 9.84 | 09-10-2026 |
| 4 | I wrote a small library for exclusive component filtering in bevy | 0 | 14.93 | 13-10-2026 |
| 5 | Multi_bimap - many-to-many bimap freely made of two arbitrary maps | 0 | 13.1 | 16-10-2026 |
| 6 | FerroProve - C-to-Rust lifter emitting #![forbid(unsafe_code)] crates with a differential oracle | 0 | 15.51 | 17-10-2026 |
| 7 | Sping 1.5.5 — a cross-platform network diagnostics CLI written in Rust | 0 | 9.19 | 10-10-2026 |
| 8 | Loole 0.6.0: Improved correctness, performance and Flume compatibility | 0 | 9.4 | 14-10-2026 |
| 9 | Announcing virtual-file-transfer 0.1.0: Windows virtual-file drag-and-drop and clipboard support | 0 | 10.34 | 16-10-2026 |
| 10 | Crossync - a super fast Rust concurrency library | 0 | 8 | 13-10-2026 |