repose-ui 0.25.4

UI widgets and libs for Repose
Documentation

Views, Modifiers, and Layout

Repose UI is built around three core ideas:

  • View: an immutable description of a UI node (cheap to rebuild every frame).
  • Modifier: layout, styling, and interaction hints attached to a View.
  • Incremental layout + paint via a persistent engine: composition produces a new View tree each frame; LayoutEngine reconciles it into a persistent ViewTree (repose-tree) and runs incremental Taffy layout + paint (with scopes, dirty sets, and paint caches).

Views

A View is a lightweight value that describes what to show, not how it is rendered. It is cheap to create; you rebuild the description each frame (Compose-style). Identity and layout state live in the persistent tree, not in the View values themselves.

use repose_core::*;
use repose_ui::*;

fn Counter(count: i32, on_inc: impl Fn() + 'static) -> View {
    Column(Modifier::new().padding(16.0)).child((
        Text(format!("Count = {count}")),
        Button("Increment".into_children(), on_inc),
    ))
}

Internally, a View has:

  • id: ViewId - assigned during composition / layout.
  • kind: ViewKind - which widget it is (Text, Button, etc.).
  • modifier: Modifier - layout/styling/interaction metadata.
  • children: Vec<View> - owned child views.

Views are pure data: they do not hold state or platform handles. State lives in signals / remember_*; platform integration is in repose-platform / repose-app.

Modifiers

Modifier describes how a view participates in layout and hit-testing:

  • Size: size, width, height, min_*, max_*, fill_max_*
  • Box model: padding, padding_values, margins
  • Visuals: background, border, clip_rounded, alpha, transform, layers
  • Flex / grid: flex_*, align_*, justify_*, grid, grid_span
  • Positioning: absolute(), offset(..)
  • Scroll: vertical_scroll / horizontal_scroll / scrollable, nested_scroll_connection
  • Interaction: clickable(), pointer callbacks, semantics
  • Custom paint: painter (used by repose-canvas)
  • Incremental helpers: key, repaint_boundary, scope! (core)

Modifiers are mapped to Taffy Style inside LayoutEngine. Values are in density-independent pixels (dp) and converted to physical px via Density.

Layout + paint

Public entry:

pub fn layout_and_paint(
    root: &View,
    size_px: (u32, u32),
    textfield_states: &HashMap<u64, Rc<RefCell<TextFieldState>>>,
    interactions: &Interactions,
    focused: Option<u64>,
) -> (Scene, Vec<HitRegion>, Vec<SemNode>);

This is a thin thread-local wrapper around LayoutEngine::layout_frame, which:

  1. Reconciles root into the persistent ViewTree (stable NodeIds, content + subtree hashes, dirty set, generation GC).
  2. Syncs dual Taffy trees (root + per-scope! ScopeLayoutTrees).
  3. Computes layout (measure callbacks, constraint equality skip for scopes).
  4. Walks the tree to emit SceneNodes, HitRegions, and SemNodes, with paint-cache hits on repaint_boundary / scopes, culling, nested scroll, etc.

Prefer scope!, stable keys, and repaint_boundary on expensive subtrees so the incremental engine can skip work.