This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
rui is an experimental declarative UI library for Rust, inspired by SwiftUI. It focuses on GPU-rendered UIs that update reactively when state changes, without a retained view tree or DOM diffing. The entire UI is re-rendered when state changes, under the assumption that this is fast enough for good performance.
cargo build- Build the projectcargo test- Run testscargo check- Check for compilation errors without building
cargo run --example <example_name>- Run a specific example (e.g.,counter,shapes,canvas,slider,gallery)cd examples/<example_name> && cargo run- For examples with their own Cargo.toml (calculator, synth, flip_cards)
Key examples:
cargo run --example counter- Basic counter democargo run --example gallery- Widget gallery showing all componentscargo run --example shapes- Basic shapes renderingcargo run --example canvas- GPU vector graphics with vgercd examples/calculator && cargo run- Calculator app
Examples serve as both demos and integration tests. Test by running them and verifying they work correctly.
View System: The fundamental building block is the View trait, which represents immutable UI components. Views are composed hierarchically to build complex UIs.
Context: Stores all mutable UI state, keyed by ViewIds. The Context manages:
- Layout information for all views
- User state created by
statefunctions - Touch/mouse interaction state
- Environment values
- Dirty tracking for reactive updates
ViewId System: Each view gets a unique identifier (u64) formed by hashing the traversal path down the view tree. This enables efficient state storage and retrieval.
Reactive Updates: The entire UI re-renders when state changes. Multiple state changes in a single event cycle are coalesced for efficiency.
Views: Immutable components that define UI structure. Examples: text(), button(), vstack(), hstack(), canvas()
State: Managed through the state function and StateHandle. State changes trigger UI updates.
Bindings: Provide read/write access to application state via the Binding trait. Used to connect UI controls to state.
Modifiers: Chainable methods on views (via the Modifiers trait) that add functionality like .padding(), .tap(), .background(), .size()
Layout: Automatic layout system similar to SwiftUI. Uses stacks (vstack, hstack, zstack) for arrangement.
src/lib.rs- Main library entry point and exportssrc/view.rs- CoreViewandDynViewtraitssrc/context.rs- Context for managing state and layoutsrc/views/- Individual view implementations (button, text, shapes, etc.)src/modifiers.rs- Common view modifierssrc/binding.rs- State binding systemsrc/lens.rs- Lens system for focusing into stateexamples/- Example applications demonstrating usage
State is managed through a combination of:
- Local State: Using
state(initial_value, |state, cx| view) - Bindings: Read/write access to state via
Binding<T> - Environment: Shared values propagated down the view tree
- Context: Central storage for all state, indexed by ViewId
- Event Processing: Handle user input and update state
- Layout: Compute view sizes and positions (cached until state changes)
- Drawing: Render using vger (GPU vector graphics)
- Dirty Tracking: Only re-render when state actually changes
- Desktop: macOS, Windows, Linux (via winit)
- Mobile: iOS support available separately
- Web: WASM support (work in progress)
- Implement the
Viewtrait (which requiresDynView + Clone) - Use composition over direct trait implementation when possible
- Follow existing naming conventions (lowercase function names)
- Use
state()for component-local state - Use
Binding<T>for two-way data flow - Leverage the lens system for accessing nested state
- Examples serve as integration tests
- Unit tests exist for core functionality (bindings, lenses)
- Test by running examples and ensuring they work correctly
- Layout is cached and only recomputed when state changes
- Rendering assumes 2D UI graphics are trivial for modern GPUs
- Avoid complex state dependencies that cause excessive re-renders