For an AI

Desktop UI APIs

Small helpers on __resuma: announce, measure, keyboard vs pointer, text zoom, presence, storage, online, and a focus queue.

LIVE

__resuma.announce / measure

Accessibility.announce

js! {
    await __resuma.action("save", []);
    __resuma.announce("Saved");
}

Every interactive page gets a polite #r-live region (role="status"). Prefer this over per-widget aria-live.

measure / keyboard / text zoom

js! {
    const box = __resuma.measure(event.currentTarget); // { x, y, width, height }
    const kb = __resuma.isNavigatingWithKeyboard();     // html[data-r-nav=keyboard]
    const zoom = __resuma.contentSizeMultiplier();      // html font-size / 16
}

Presence (idle vs active)

__resuma.presence() is { idle, hidden }. Idle after 60s without pointer/key/scroll, or when the tab is hidden. loader_poll skips ticks while idle so live dashboards do not burn the network. Listen for resuma:presence on document.

Online + Storage (SSR-safe)

js! {
    if (!__resuma.online()) { /* offline PWA */ }
    __resuma.storage.set("theme", "dark"); // no-op if localStorage throws
    const t = __resuma.storage.get("theme");
}

There is no Rust localStorage during SSR — keep reads/writes in js! / visible tasks. Pair with PWA. Document palettes (html[data-theme]) use HtmlTheme, not storage.set("theme").

RTL layout

FlowApp::new().with_dir("rtl")

// or per request in #[load] / page:
set_page_dir("rtl");
set_page_theme("slate"); // SSR html[data-theme] for this response

This sets <html dir>. Use logical CSS (margin-inline-start, inset-inline-end) instead of left/right. Fluent strings in #[load] do not flip flex by themselves — see i18n.

Focus arbitrator

__resuma.focus(el) queues focus() for the next microtask so SPA swaps, popups, and dialogs do not steal focus from each other. focusMain() after navigation uses the same queue.