| Crates.io | waterui |
| lib.rs | waterui |
| version | 0.2.1 |
| created_at | 2025-12-14 10:05:21.379377+00 |
| updated_at | 2025-12-14 11:31:57.855094+00 |
| description | A modern UI framework for Rust |
| homepage | |
| repository | https://github.com/water-rs/waterui |
| max_upload_size | |
| id | 1984132 |
| size | 1,476,063 |
A modern, cross-platform UI framework for Rust that renders to native platform widgets (UIKit/AppKit on Apple, Android View on Android) rather than drawing its own pixels. Build reactive, declarative UIs with Rust's type safety and performance.
WaterUI combines declarative, component-based architecture with fine-grained reactivity to deliver truly native user interfaces across platforms. Unlike traditional Rust UI frameworks that implement custom rendering, WaterUI translates your Rust view tree into platform-native UI components through an FFI bridge, ensuring your apps look and feel native on every platform.
The framework is built on three core principles:
nami crate, UI updates are surgical and automatic—only affected components re-render when state changes.WaterUI is ideal for building production mobile apps, cross-platform tools, and native desktop applications where performance and platform integration matter.
Add WaterUI to your Cargo.toml:
[dependencies]
waterui = "0.2"
waterui-ffi = "0.2" # Required for FFI export
Enable the graphics feature for GPU rendering capabilities:
[dependencies]
waterui = { version = "0.2", features = ["graphics"] }
The fastest way to experience WaterUI is through the CLI's playground mode, which handles native backend setup automatically:
cargo install waterui-cli
water create --playground --name my-app
cd my-app
water run
Your app launches with hot reload enabled. Edit src/lib.rs and watch changes appear instantly.
use waterui::prelude::*;
use waterui::app::App;
#[hot_reload]
fn main() -> impl View {
vstack((
text("Hello, WaterUI!").size(24.0).bold(),
text("Build native UIs with Rust"),
))
.spacing(12.0)
.padding()
}
pub fn app(env: Environment) -> App {
App::new(main, env)
}
waterui_ffi::export!();
Every UI component implements the View trait, which defines how it renders:
use waterui_core::Environment;
pub trait View: 'static {
fn body(self, env: &Environment) -> impl View;
}
Views compose recursively—complex interfaces are built from simple building blocks. The framework handles type erasure, rendering, and updates automatically.
WaterUI uses Binding<T> for mutable state and Computed<T> for derived values. Views automatically update when reactive values change:
use waterui::prelude::*;
#[hot_reload]
fn counter() -> impl View {
let count = Binding::int(0);
vstack((
waterui::text!("Count: {}", count),
button("Increment")
.action({
let count = count.clone();
move || count.set(count.get() + 1)
}),
))
}
The Environment provides dependency injection for themes, fonts, and custom services. Values propagate down the view tree without explicit passing:
use waterui::app::App;
use waterui::prelude::*;
use waterui_core::Environment;
use waterui_text::font::{ResolvedFont, FontWeight};
pub fn app(mut env: Environment) -> App {
let theme = Theme::new()
.color_scheme(ColorScheme::Dark)
.fonts(FontSettings::new().body(ResolvedFont::new(16.0, FontWeight::Normal)));
env.install(theme);
App::new(main, env)
}
WaterUI provides a fluent API for styling and layout through the ViewExt trait:
use waterui::prelude::*;
use waterui_color::Color;
text("Styled Text")
.size(18.0)
.bold()
.foreground(Color::srgb(100, 150, 255))
.padding()
.background(Color::srgb_hex("#f0f0f0"))
.on_tap(|| println!("Tapped!"));
use waterui::prelude::*;
#[form]
struct Settings {
username: String,
dark_mode: bool,
volume: f64,
}
#[hot_reload]
fn settings_view() -> impl View {
let settings = Settings::binding();
vstack((
text("Settings").size(24.0),
form(&settings),
Divider,
waterui::text!("Dark mode: {}", settings.project().dark_mode),
waterui::text!("Volume: {:.0}%", settings.project().volume.map(|v| v * 100.0)),
))
.padding()
}
use waterui::prelude::*;
use waterui::gesture::{TapGesture, DragGesture, LongPressGesture};
#[hot_reload]
fn gestures() -> impl View {
let tap_count = Binding::int(0);
vstack((
waterui::text!("Taps: {}", tap_count),
text("Tap Me")
.padding()
.background(Color::srgb_hex("#2196F3").with_opacity(0.3))
.gesture(TapGesture::new(), {
let tap_count = tap_count.clone();
move || tap_count.set(tap_count.get() + 1)
}),
text("Long Press")
.padding()
.background(Color::srgb_hex("#FF9800").with_opacity(0.3))
.gesture(LongPressGesture::new(500), || {
println!("Long press detected");
}),
))
}
use waterui::prelude::*;
use waterui::component::list::{List, ListItem};
#[derive(Clone)]
struct Contact {
id: u64,
name: &'static str,
role: &'static str,
}
impl Identifiable for Contact {
type Id = u64;
fn id(&self) -> Self::Id {
self.id
}
}
fn contacts_list() -> impl View {
let contacts = vec![
Contact { id: 1, name: "Alice Chen", role: "Software Engineer" },
Contact { id: 2, name: "Bob Smith", role: "Product Manager" },
Contact { id: 3, name: "Carol Williams", role: "Designer" },
];
List::for_each(contacts, |contact| ListItem {
content: AnyView::new(
vstack((
text(contact.name).size(17.0).bold(),
text(contact.role)
.size(14.0)
.foreground(Color::srgb(128, 128, 128)),
))
.padding_with(EdgeInsets::symmetric(12.0, 16.0)),
),
on_delete: None,
})
}
vstack(), hstack(), zstack() - Vertical, horizontal, and depth stacks with configurable spacing and alignmentscroll() - Scrollable container with automatic content overflow handlingspacer() - Flexible space filler for pushing elements apartpadding() - Add insets around views with EdgeInsets configurationFrame - Fixed, minimum, and maximum sizing constraintsButton - Tappable button with action handler and style variantsTextField - Single-line text input with label and placeholderToggle - Boolean switch control with reactive bindingSlider - Continuous value selector within a rangeStepper - Discrete value adjuster with step incrementPicker - Selection control for choosing from multiple optionsText - Styled text with font, size, weight, and color configurationtext!() macro - Reactive text with format string interpolationstyled() - Rich text with multiple style runsVideoPlayer - Native video playback with controls and event handlinginclude_markdown!() - Compile-time markdown to view conversion#[form] derive macro - Automatic form generation from structsTextField, Toggle, Slider - Form-compatible controls with labelsNavigationView - Hierarchical navigation with title barTabView - Tab-based navigation container.title() modifier - Set navigation bar titleDynamic::watch() - Observe reactive signals and rebuild views on changeAnyView - Type-erased view container for heterogeneous collectionsEnvironment - Dependency injection and context propagationViewExt - Extension trait providing modifier methods for all viewsThe base waterui crate includes layout, controls, text, media, navigation, and form components with native rendering backends.
graphics - Enables GPU rendering with canvas drawing primitives and GpuSurface (requires waterui-graphics)graphics-minimal - GPU surface only, without canvas (smaller binary size)Every WaterUI app follows this pattern:
use waterui::prelude::*;
use waterui::app::App;
// Initialize environment (called once at app startup)
pub fn init() -> Environment {
Environment::new()
}
// Root view (called on every render)
pub fn main() -> impl View {
text("Your app content here")
}
// Alternative: App with custom environment setup
pub fn app(mut env: Environment) -> App {
// Install plugins, themes, etc.
env.install(Theme::new().color_scheme(ColorScheme::Dark));
App::new(main, env)
}
// Export FFI entry points for native backends
waterui_ffi::export!();
The waterui_ffi::export!() macro generates C-compatible functions that native backends (Swift/Kotlin) call to render your UI.
waterui-core - Foundation types: View trait, Environment, AnyView, reactivity primitiveswaterui-ffi - C FFI bridge with export!() macro for native backend integrationwaterui-layout - Layout containers and geometrywaterui-controls - Buttons, toggles, sliders, text fieldswaterui-text - Text rendering, fonts, and stylingwaterui-form - Form builder with #[form] derive macrowaterui-media - Video/audio playback componentswaterui-navigation - Navigation containers and routingwaterui-graphics - Canvas drawing and GPU rendering (optional)waterui-cli - Command-line tool for creating, building, and running appsThe water CLI provides a complete development workflow:
# Create new project
water create --name "My App" --backend apple --backend android
# Create playground (auto-configured backends)
water create --playground --name my-playground
# Run with hot reload
water run --platform ios --device "iPhone 15 Pro"
water run --platform android
# Build Rust library for specific target
water build ios
water build android
# Check development environment
water doctor
# List available devices
water devices
Contributions are welcome! Please submit pull requests to the dev branch. The main branch is reserved for releases.
License under Apache 2.0 OR MIT license.