Non-invasive by default
Components are plain GPUI elements that can be placed directly in existing Views. Your app keeps using GPUI Application, Window, View, and Context<T>.
- No Vektra Root
- No Provider
- No vektra::init(cx)
Drop them into existing Views without a Root, Provider, or init flow. Unified lazy data access, viewport rendering, bounded caches, keyboard behavior, and accessible semantics are built in.
Vektra is in early development. GPUI has published pre-1.0 releases, but its API is still moving quickly and may introduce breaking changes. Vektra currently pins a specific GPUI revision and has not committed to stable compatibility with crates.io GPUI, so there is no production-ready Vektra crate release yet. Use a Git workspace or path dependency, and expect Vektra public APIs to change in breaking ways.
The vektra 0.0.1 package on crates.io only reserves the project name. It does not contain the current component library implementation and must not be used as the formal dependency.
Vektra is a pure GPUI component library for applications that already have their own lifecycle, windows, and state model.
Components are plain GPUI elements that can be placed directly in existing Views. Your app keeps using GPUI Application, Window, View, and Context<T>.
Button and IconButton implement concrete interaction behavior instead of leaving it as an example-page convention.
The default theme is parsed once and cached as Arc<ResolvedTheme>. Rendering reuses the resolved result and stays on GPUI's native SVG and asset path.
The supporting pieces stay useful without competing with the core positioning.
Variants, sizes, Light/Dark, System mode, and interaction states come from Vektra theme tokens.
Props, callbacks, Context<T>, Window, and the asset pipeline stay in the shape your GPUI app already uses.
The buttons below are compiled from Rust and GPUI to WASM, not a separate HTML recreation.
A compact preview that gives direct evidence for Vektra's first component surface. The ordinary variant buttons use the default MD size; the separate size row intentionally shows XS, SM, MD, and LG, so its height differences are deliberate.
Button::new("save")
.label("Save")
.start_icon(IconName::Settings)
.on_click_in(cx, |this, _, _, cx| {
this.save_count += 1;
cx.notify();
});
Button::new("delete")
.label("Delete")
.variant(ButtonVariant::Destructive)
.disabled(is_locked);Finish the local dependency setup first, then use the Button docs to understand the component API, sizes, icon slots, and accessibility conventions.