Skip to content

Latest commit

 

History

History
183 lines (148 loc) · 7.3 KB

File metadata and controls

183 lines (148 loc) · 7.3 KB

Getting Started

Operad's default path is the runtime path. It should be the first thing a new application tries before building a custom host.

Native App

Use operad::run for a stateless document, or operad::run_app when widget actions should update application state.

use operad::{root_style, widgets, LayoutStyle, NativeWindowResult, UiDocument, UiSize};

fn main() -> NativeWindowResult {
    operad::run("app", view)
}

fn view(viewport: UiSize) -> UiDocument {
    let mut ui = UiDocument::new(root_style(viewport.width, viewport.height));
    widgets::button(
        &mut ui,
        ui.root,
        "run",
        "Run",
        widgets::ButtonOptions::new(LayoutStyle::size(140.0, 36.0)),
    );
    ui
}

Run the smallest checked template with:

cargo run --example minimal_native

Stateful App

Stateful apps use the same runtime. The update function receives widget actions; the view function rebuilds the retained document from the current state.

operad::run_app("app", state, update, view)?;

Use examples/simple_form.rs as the smallest stateful text-input example.

Platform Services

Apps should request OS/browser behavior through the runtime instead of calling platform APIs directly. Use PlatformServiceClient in app state, drain its requests through the runtime hook, and handle responses from the matching response hook.

let hooks = operad::NativeWindowHooks::new()
    .with_platform_service_requests(|state: &mut AppState, _metrics| {
        state.platform.drain_requests()
    })
    .with_platform_responses(|state: &mut AppState, responses| {
        state.platform.record_responses(responses.iter().cloned());
    });

state.platform.write_clipboard_text("copied text");
state.platform.open_url("https://docs.rs/operad");

The same hook names are available on operad::web::WebRuntimeHooks. Native responses are usually immediate. Browser clipboard responses may arrive in a later frame because the browser APIs are asynchronous.

Web App

Enable web-runtime and export a wasm entry point that calls operad::web. The runtime owns canvas lookup or creation, WebGPU setup, real text measurement through cosmic-text, resize handling, input routing, scroll persistence, animation ticking, and status/failure reporting. If WebGPU startup fails, the runtime writes the failing operation, consequence, and next step into the configured status element before returning the error. Browser clipboard read/write requests are serviced asynchronously and delivered back through the normal platform response queue.

#[cfg(target_arch = "wasm32")]
#[wasm_bindgen::prelude::wasm_bindgen]
pub async fn start() -> Result<(), wasm_bindgen::JsValue> {
    operad::web::run("app", view).await
}

Build the minimal web template with:

cargo build --release --target wasm32-unknown-unknown \
  --no-default-features --features web-runtime --example minimal_web

wasm-bindgen --target web --out-dir web/minimal/pkg \
  --out-name minimal_web \
  target/wasm32-unknown-unknown/release/examples/minimal_web.wasm

Then serve web/minimal from a local static file server.

Checked Templates

The maintained starter examples are ordinary examples, so cargo check --all-features --examples and CI keep them from drifting:

  • minimal_native: smallest native runtime app.
  • minimal_web: smallest WASM/WebGPU runtime app.
  • simple_form: state, text input, and actions.
  • canvas_app: WGPU canvas with runtime ticking.
  • command_palette_hotkeys: command metadata, shortcuts, and palette UI.
  • docked_workspace: docked panels with public workspace widgets.
  • theme_customization: theme snapshot/editor surface.
  • animation_state_machine: state-machine input and scene morphing.

Escape Hatches

The default runtime is not the only way to use Operad. Advanced applications can still own lower-level pieces:

  • Use run_app_with to configure window size, minimum size, UI scale, and tick actions.
  • Use run_app_with_canvas_renderers when a canvas needs custom WGPU rendering.
  • Use the host, platform, renderer, and diagnostics modules directly for custom hosts or test harnesses.
  • Query BackendCapabilities before depending on platform behavior such as pointer lock, raw mouse motion, cursor grab, clipboard, IME, WebGPU, or native child windows.
  • Query BackendCapabilityProfile for product-level needs such as command hotkeys, text editing, canvas pointer editing, 3D flycam controls, docked workspaces, OS/platform drag-drop, and accessibility support. Profiles expand to the same BackendCapabilityDiagnostic records as lower-level capability checks.
  • Use the built-in capability profiles from BackendCapabilities::native_window(), BackendCapabilities::web_runtime(), and test_host_capabilities() when checking the default native runner, web runner, and deterministic test harness behavior.

Prefer the default runtime unless the application has a concrete host or renderer requirement that the runtime cannot own. The native runtime applies standard platform services such as text clipboard, open URL, cursor, text IME, and repaint requests itself; custom hosts can still consume the same PlatformRequest records directly.

Regression Checks

Applications can use Operad's renderer-neutral diagnostics in their own tests:

  • JustWorkAssertions checks the blocking layout, clipping, scroll, scrollbar range, geometry, hit-target, naming, and paint warnings that cause edge-falloff bugs. Failures include the responsible node, reason, measured values, and a remediation hint.
  • run_ui_state_matrix runs the same audit across multiple viewports and interaction states.
  • EventReplay::long_wheel_scroll can stress scroll containers and then assert that the target reaches the exact scroll end.
  • EventReplayReport::require_consumed_by can assert that a visually topmost node intentionally consumed input, even when no scroll offset changed.
  • ScenarioHarness runs document, input, render, platform-request, and timing checks without a native or web host.
  • FrameTimingSeries::dominant_section() summarizes the slowest frame subsystem across repeated frames, and timing budget failures include that dominant section in their diagnostic message.
  • runtime_error_overlay turns an ErrorReport into an accessible debug overlay, so recoverable runtime, renderer, resource, and platform failures can be shown with the operation, consequence, next step, and fallback.
  • classify_platform_service_response turns unsupported, denied, or failed platform service responses into actionable ErrorReport values with the request id, subsystem, consequence, next step, and fallback decision.
  • PlatformAssertions includes those platform diagnostics in unsupported or failed response assertions so host-capability regressions fail with a next step instead of only a response enum.
  • scripts/test-fast.sh and scripts/test-full.sh mirror the locked local gates used for release handoff; the full gate includes the supported WASM showcase check for wasm32-unknown-unknown.
  • scripts/check-web-showcase.mjs runs the built Pages artifact in headless Chrome/WebGPU and fails on browser-only startup panics, missing assets, console errors, and shader warnings.

These helpers live outside showcase code so downstream apps can keep the same failure modes under test.