Keyboard focus: which widget receives key events. A base primitive with no styling of its own — a
focusable widget (e.g. crate::Input) requests focus on tap and consults it in on_event/view.
Window-management calls for UI code. A custom title bar’s buttons call these directly — including from
.rsxon_press handlers (on_press(|| telar::window::close())). Each enqueues a
platform_core::WindowCommand that the runner applies to the OS window right after the current event is
dispatched. On backends without a movable top-level window (layer-shell, headless) they are inert no-ops.
Transpile every .rsx file under src/ and declare the module tree — what app! does, minus the winit
runner. Use this in a crate that drives rsx through a customPlatform (e.g. a Wayland layer-shell
backend) instead of the built-in desktop runner: invoke telar::rsx_modules!() at the crate root, then build
your own App from the transpiled components and run it via telar::run_with_platform /
telar::run_multi_with_platform. Pass a theme type — rsx_modules!(MyTheme) — if your .rsx calls
use_theme; otherwise rsx_modules!().
Wraps a child so its rendered output is clipped to the child’s own layout rect. When the child
collapses to a zero rect (e.g. a section hidden via display:none), the clip is empty, so nothing
inside draws — even a widget left with a stale rect or one that paints at fixed coordinates. Layout
is unchanged: layout_node passes through to the wrapped child.
A live subscription. Dropping it deregisters the effect, so the closure runs once and never again — which
looks exactly like a working binding until the value it derives is expected to move. Bind it to something
that lives as long as the work should: a struct field, a returned value, or a let the reader captures.
A single-line editable text field bound to a RwSignal<String>. A base primitive: unstyled (no
border or background — wrap it in a box for the look) and keyboard-driven. It requests focus on
tap and, while focused, edits the bound signal from key events, drawing a caret at the insertion
point. Selection, clipboard, and IME composition are not yet supported (a single-caret MVP).
Line is designed for use inside Canvas closures where you control absolute coordinates. It does not implement LayoutItem because its p1/p2 points are absolute, not relative to a layout rect. To use Line in a layout context, embed it in a Canvas widget.
A line-number gutter for a code editor: the column “1\n2\n3…” drawn top-aligned with the same line height a
TextArea uses, so line n here sits exactly on line n of the editor. Place it beside
the editor inside the same scroll (so they scroll together) and give both the same font_size. It measures
its own width from the widest number and its height from the line count, re-measuring reactively as the
count changes. Toggle it by collapsing its node (set_display) inside a ClippedItem
so a hidden gutter both takes no width and draws nothing.
A portal layer: its content is laid out out-of-flow, filling the viewport, and hoisted to the top at
compose time — drawn above everything and free of any ancestor clip/transform. A base primitive:
unstyled; wrap content in a box for a scrim/panel, and position it with normal flex (align/justify).
Path is designed for use inside Canvas closures where you control absolute coordinates. It does not implement LayoutItem because its path data uses absolute points, not relative to a layout rect. To use Path in a layout context, embed it in a Canvas widget.
A reactive list: for item in $items key id (or, keyless, for item in $items) in .rsx. Re-runs its
source reactively and reconciles the item widgets — reused keys/positions keep their node/widget, new
ones are built, gone ones are disposed, and the layout children are reordered — instead of rebuilding the
whole block on every change. new/with_gap reconcile by key (identity-stable); positional/
positional_with_gap reconcile by index (no key clause needed, cheap append/truncate).
A paragraph of mixed-style text: a sequence of TextRuns (bold, italic, coloured links) shaped and
wrapped as one, the multi-style counterpart of Text. The shared paragraph metrics — font
size, line height, wrapping, max_lines — come from a base TextStyle; each run overrides only weight,
slant, and colour.
A handle to the enclosing scroll area’s live viewport, handed to the content builder by
LayoutScrollArea::new_with. Because a scroll area lays its content out as its OWN layout root,
every descendant’s tracked rect is already in the same content-local space the scroll offset
indexes into — so visible is a plain rect overlap, no scroll-transform math.
A node emitted by Segment::walk: one mounted component, with its pre-order id, widget name,
nesting depth, and the bounding rect of its own draw commands unioned with all descendants’.
The children a component receives from its call site, grouped by slot. A bare child lands in the
default slot (None); a child written with slot:"name" lands in that named slot. Inside the
component, the children placeholder drains the default slot and children name:"x" drains the
"x" slot — each in call-site order. Draining is one-shot: a slot placeholder consumes its
children, so referencing the same slot twice yields an empty list the second time.
Stroke style for drawing primitives. Includes join to control how corners are rendered in paths and rects; for line segments join is unused and defaults to Miter.
Identifies one surface within a MultiSurfacePlatform run. Assigned by the platform (e.g. one per
monitor for a desktop shell). Opaque and cheap to copy.
A backend-agnostic description of a secondary surface: where it sits, how big it is, and how it
behaves (scrim, outside-dismiss, auto-timeout). The intent lives here; a backend derives its own
surface config from it. Reusable by a windowed app (as an in-window portal) and by a shell (as a real
layer-shell surface) alike.
A full-viewport scaffold that positions a panel against a screen edge, optionally dims the area behind
it, and dismisses on a press outside the panel. It is the reusable body of a drawer/modal: a shell
mounts it as the root of a full-screen layer-shell surface, and a windowed app can mount it in-tree as
an in-window portal — both get the same positioning and dismiss behaviour.
A multi-line editable text area bound to a RwSignal<String> — the multi-line sibling of Input.
A base primitive: unstyled (wrap it in a box for a border/background), keyboard-driven, no soft-wrap (only
\n breaks lines, so long lines overflow horizontally). It requests focus on tap, positions the caret at
the click, edits the bound signal from key events (typing, Enter for a newline, Backspace/Delete joining
lines, arrows in all four directions, Home/End, Tab), and draws a caret. Its measured height grows with the
line count, so wrapping it in a LayoutScrollArea gives a scrolling editor.
Selection, clipboard, and IME are not yet supported (a single-caret MVP, like Input).
One inline run of a rich-text paragraph: a slice of text with its own weight, slant, and colour. Paragraph
metrics (font size, line height, wrapping, alignment) live on the DrawCommand::RichTextbase style,
so a run overrides only what varies inline (bold, italic, a link’s colour).
A 2D affine transform stored as a 2×3 matrix [a, b, c, d, e, f], mapping a
point (x, y) to (a*x + c*y + e, b*x + d*y + f). This is the same [f32; 6]
layout consumed by RenderNode::transform_with, so to_array() plugs in
directly. Compose with Transform::then instead of multiplying matrices by
hand.
One child position in a container: a fixed widget, or a reactive fragment (built lazily once the host
node exists). Produced by ChildSlot::stat / fragment / fragment_positional.
What kind of secondary surface a placement describes. A backend maps the role to its own surface
primitives (a layer-shell backend picks a layer + namespace; a windowed backend a child window or an
in-window portal). Roles carry no behaviour of their own — the explicit SurfacePlacement fields do.
A window-management action requested by UI code (a custom title bar’s buttons) and applied by the runner
to the OS window after event dispatch. Enqueued via push_window_command and drained via
take_window_commands; kept as data (rather than direct Window calls) because widget closures run
deep in the tree walk with no access to the platform window.
The default scrim wash: ~35 % black over the content behind a drawer/modal. Rendered as a fill (not an
opacity layer) so the panel above it stays fully opaque.
Imperative-state components re-render only when on_event returns EventResult::Handled; reactive-state components re-render automatically on signal change.
A platform that drives N independent surfaces from a single run, each with its own
EventHandler — the seam a multi-window app or a desktop shell (a bar/OSD/notification per monitor)
needs. It is separate from Platform so the single-surface contract and every existing single-window
entry point stay exactly as they are.
Builds the affine matrix for a box’s declarative rotate/scale/translate attributes, pivoting
rotation and scale on the box centre. Returns None when every component is identity, so an untransformed
box skips the extra transform node entirely.
Closes the overlay named id. Note this is not the same as a dismissal: it closes exactly this overlay,
where dismiss_top closes whichever is frontmost.
The language subtag of the OS locale, from $LC_ALL / $LC_MESSAGES / $LANG (in POSIX precedence),
lowercased and stripped of any territory/encoding suffix — e.g. es_ES.UTF-8 → "es". None when unset
or the C/POSIX locale. An app can seed the initial language with init_locale(detect_system_locale()?).
Makes the writing direction follow the active locale, so switching to Arabic or Hebrew mirrors the layout
and switching back restores it — no rebuild, the existing nodes are re-resolved on the next layout pass.
Drives the active mode from the OS light/dark preference — light → light, dark → dark — updating live
as the OS scheme changes. Installs a reactive effect (kept alive internally) and designates the pair so
is_dark/toggle_dark stay consistent. Re-calling replaces the effect (hot reload re-runs setup). A
manual set_mode still wins until the next OS change re-drives it.
A keyed reactive region with per-item spacing — for item in $items key <expr> gap:N. The gap is laid
out as a main-axis leading margin between consecutive items (see [reconcile_slot]), so the region
still flows transparently in the host’s direction (horizontal in a row) instead of a boxed list.
Without dev there is no dylib swap to survive, so the key is inert and this degrades to a plain signal.
The bounds match the dev build’s so a type that compiles here cannot fail once hot-reload is on — letting
hand-written app state (a navigation stack, an active locale) be declared once instead of behind a cfg.
Sets default only when no locale is active yet. Called at app start (and after a hot reload) so a
selection restored across a dylib swap is not clobbered by the default.
Selects default only when no mode is active yet. Called at app start and after a hot reload so a
selection restored by the rsx hot-reload bridge is not clobbered by the default.
The current laid-out rects of every interactive widget on the active surface, dropping any not yet laid
out (zero-sized). Read without subscribing (peek), so the platform’s frame loop can call it outside a
reactive scope without accidentally tracking the layout signals.
Reactive: true when the active mode is the designated dark mode. false when it is the light mode, no
pair has been set, or a third (unpaired) mode is active. Read this for a sun/moon toggle’s on/off state.
Enqueue a window-management command from UI code (e.g. a title-bar button’s on_press). The runner drains
the queue after event dispatch and applies each command to the OS window. Lives in a thread-local so it
works from any widget closure without threading a window handle through the tree; each surface owns its
own queue (activated via WindowCommandContext), so commands never cross windows.
Registers a named mode. apply installs the concrete theme when the mode is selected. Re-registering an
id replaces its closure, which is expected: hot reload re-runs the app’s setup and re-registers every mode.
Re-lays out every root that has been computed at least once, picking up any nodes a reactive change
dirtied since the last frame. Each compute_layout early-returns when its root is clean and the space
is unchanged, so this is cheap on a still frame. The runtime calls it once per redraw (after flushing
reactive effects, before rendering) so a data change deep in the tree — e.g. a reactive list adding an
item — is reflected in layout without the app shell knowing about it. Node dirtiness propagates up to
the root through taffy, so a dirtied list container makes its root recompute.
Detaches and frees node (a former list item) from the runtime: removes it from the layout tree and
drops its rect signal and bookkeeping. The caller must have removed it from its parent’s child list
(via set_children) first.
Resets the active surface’s layout runtime to a fresh, empty tree. The single-window app/preview harness
calls this at construction; a multi-surface runner instead gives each surface its own LayoutContext.
Replaces parent’s children with children, in order, marking parent dirty. Operates on the
thread-local runtime; parent must be a container already registered in the runtime.
Shows or hides a node in layout flow. A hidden node takes no space (and lays out none of its subtree); mark an ancestor dirty and recompute for the change to take effect. Used for responsive layouts (e.g. collapsing a sidebar on narrow windows).
Designates which two registered modes form the light/dark pair. A thin, optional convention over the open
mode registry: it does not replace named modes (a third mode like "pastel" stays valid) — it only tells
is_dark/set_dark/toggle_dark which ids to flip between. Both ids should also be registered via
register_mode. Does not itself change the active mode.
Sets the active locale (a BCP-47 tag such as "en" or "es"), re-rendering every translated string that
reads it. The tag should be one of the baked catalog’s locales; an unknown tag simply falls back to the
catalog’s default locale at lookup time.
Sets node’s minimum height to px after the initial layout (dirtying it, which propagates up), so a
content-measured leaf grows to at least px even when its content is shorter. A scrolling editor uses it
to fill its viewport so a click anywhere in the empty area — not just over the text — lands on the leaf.
Selects a mode: runs its registered apply closure (if one is registered) and publishes the id to the
reactive active-mode signal. Setting an unregistered id still updates the signal, so an app may drive the
theme from its own effect on use_mode instead of registering closures.
Pins the overlay host to node — the app’s window-spanning root — so overlays always fill the viewport
even when the app computes several independent layout roots (e.g. a shell with a separate sidebar root
computed after the main one, which the auto-detection would otherwise pick as the host). Call it each
relayout with the current main root (it survives hot-reload rebuilds, which mint a new root node). Once
pinned, auto-detection no longer overrides the host.
Reports the OS light/dark preference into the reactive graph. Called by the runner at window creation and
whenever the OS scheme changes; drives follow_system.
Applies the full affine inverse of matrix to all pointer-coordinate events. Returns None for
non-pointer events or when matrix is degenerate (det ≈ 0), so callers fall back to the original.
Renders every preview component headlessly (build → layout → flatten) and exits with a non-zero code if any panics or returns a layout error. Backs cargo telar test, entered via the TELAR_TEST env var set on the app binary.
Reactive read of the active direction — subscribes the caller, for the rare widget that has to mirror
something layout cannot flip on its own (a chevron glyph, a directional icon).
Reactive read of the active locale — subscribes the caller so translated text re-renders on switch. None
before any locale is set (callers fall back to the catalog’s default locale).
Sets the distribution of space between and around content items.
For Flexbox it controls alignment in the main axis.
For Grid it controls alignment in the inline axis.