Crate waterui

Crate waterui 

Source
Expand description

§WaterUI

Crates.io docs.rs License Coverage

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.

§Overview

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:

  • Native-first rendering: Your UI components compile to UIKit/AppKit views on iOS/macOS and Android View on Android, delivering authentic native behavior and performance.
  • Fine-grained reactivity: Powered by the nami crate, UI updates are surgical and automatic—only affected components re-render when state changes.
  • Hot reload: Changes to your Rust code reload instantly in running apps via dynamic library swapping, providing a development experience similar to web frameworks.

WaterUI is ideal for building production mobile apps, cross-platform tools, and native desktop applications where performance and platform integration matter.

§Installation

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"] }

§Quick Start

The fastest way to experience WaterUI is through the CLI’s playground mode, which handles native backend setup automatically:

§1. Install the CLI

cargo install waterui-cli

§2. Create and Run a Playground

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.

§3. Write Your First View

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!();

§Core Concepts

§The View Trait

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.

§Reactive State

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)
            }),
    ))
}

§Environment

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)
}

§View Modifiers

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!"));

§Examples

§Form with Reactive Bindings

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()
}

§Interactive Gesture Handling

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");
            }),
    ))
}

§Dynamic List Rendering

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,
    })
}

§API Overview

§Layout Components

  • vstack(), hstack(), zstack() - Vertical, horizontal, and depth stacks with configurable spacing and alignment
  • scroll() - Scrollable container with automatic content overflow handling
  • spacer() - Flexible space filler for pushing elements apart
  • padding() - Add insets around views with EdgeInsets configuration
  • Frame - Fixed, minimum, and maximum sizing constraints

§Controls

  • Button - Tappable button with action handler and style variants
  • TextField - Single-line text input with label and placeholder
  • Toggle - Boolean switch control with reactive binding
  • Slider - Continuous value selector within a range
  • Stepper - Discrete value adjuster with step increment
  • Picker - Selection control for choosing from multiple options

§Text & Media

  • Text - Styled text with font, size, weight, and color configuration
  • text!() macro - Reactive text with format string interpolation
  • styled() - Rich text with multiple style runs
  • VideoPlayer - Native video playback with controls and event handling
  • include_markdown!() - Compile-time markdown to view conversion

§Form Components

  • #[form] derive macro - Automatic form generation from structs
  • TextField, Toggle, Slider - Form-compatible controls with labels
  • Automatic field-to-control mapping based on type
  • NavigationView - Hierarchical navigation with title bar
  • TabView - Tab-based navigation container
  • .title() modifier - Set navigation bar title

§Advanced

  • Dynamic::watch() - Observe reactive signals and rebuild views on change
  • AnyView - Type-erased view container for heterogeneous collections
  • Environment - Dependency injection and context propagation
  • ViewExt - Extension trait providing modifier methods for all views

§Features

§Default Features

The base waterui crate includes layout, controls, text, media, navigation, and form components with native rendering backends.

§Optional Features

  • graphics - Enables GPU rendering with canvas drawing primitives and GpuSurface (requires waterui-graphics)
  • graphics-minimal - GPU surface only, without canvas (smaller binary size)

§Application Entry Point

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.

§Core Architecture

  • waterui-core - Foundation types: View trait, Environment, AnyView, reactivity primitives
  • waterui-ffi - C FFI bridge with export!() macro for native backend integration

§Component Libraries

§Tools

  • waterui-cli - Command-line tool for creating, building, and running apps

§CLI Commands

The 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

§Platform Support

  • iOS/macOS: Renders to UIKit/AppKit (requires Xcode)
  • Android: Renders to Android View (requires Android SDK)

§Documentation

§Contributing

Contributions are welcome! Please submit pull requests to the dev branch. The main branch is reserved for releases.

§License

License under Apache 2.0 OR MIT license.

Re-exports§

pub use waterui_color as color;
pub use waterui_form as form;
pub use waterui_layout as layout;
pub use waterui_media as media;
pub use waterui_navigation as navigation;
pub use waterui_text as text;
pub use nami as reactive;
pub use tracing as log;

Modules§

accessibility
Helpers for customizing accessibility metadata when the built-in WaterUI defaults are not enough.
animation
WaterUI Animation System
app
A WaterUI application representation.
background
This module provides types for defining background and foreground colors in a UI.
component
UI components for WaterUI
debug
Debug utilities for WaterUI.
env
Environment management module for sharing data across views.
error
Error handling utilities for converting standard errors into renderable views. Utilities for displaying runtime errors inside WaterUI views.
filter
Filters Module
fullscreen
Full-screen overlay system for WaterUI.
gesture
Declarative gesture descriptors used by WaterUI components.
id
Identity, tagging, and mapping functionality for UI components.
metadata
Metadata definitions for WaterUI.
prelude
A collection of commonly used traits and types for easy importing.
signal
This module provides a framework for reactive computations that can track dependencies and automatically update when their inputs change.
style
This module provides types for working with shadows and vectors in the UI system.
task
Task management utilities and async support.
theme
Theme System
view
Task management utilities and async support. This module provides extension traits and builder patterns for creating and configuring views.
views
Collection of view-related utilities for managing and transforming UI components.
widget
Widget components for building complex UI elements.
window
Module defining the Window struct for UI windows.

Macros§

hot_reloadable_library
Entry point macro for hot-reloadable views.
impl_extractor
Implements the Extractor trait for a type.
include_markdown
Includes a Markdown file as a RichText widget at compile time.
raw_view
Implements a native view that is handled by the platform backend.
s
Function-like procedural macro for creating formatted string signals with automatic variable capture.
text
Creates a reactive text component with formatted content.

Structs§

AnyView
A type-erased wrapper for a View.
Binding
A Binding<T> represents a mutable value of type T that can be observed.
Color
A color value that can be resolved in different color spaces.
Computed
A wrapper around a boxed implementation of the ComputedImpl trait.
Environment
An Environment stores a map of types to values.
Str
A string type that can be either a static reference or a ref-counted owned string.

Traits§

FormBuilder
Trait for types that can be automatically converted to form UI components.
Identifiable
Defines an interface for types that can be uniquely identified.
Signal
The core trait for reactive system.
SignalExt
Extension trait providing additional methods for Signal types.
View
View represents a part of the user interface.
ViewExt
Extension trait for views, adding common styling and configuration methods.

Functions§

entry
Wraps the root view for an application, allowing custom entry pipelines to compose around it in the future.

Attribute Macros§

form
The #[form] attribute macro that automatically derives multiple traits commonly used for forms.
hot_reload
Attribute macro for enabling hot reload on view functions.

Derive Macros§

FormBuilder
Derives the FormBuilder trait for structs, enabling automatic form generation.
Project
Derive macro for implementing the Project trait on structs.