Rendering in Kael is declarative and frame-oriented. Each frame, Kael callsDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Augani/kael/llms.txt
Use this file to discover all available pages before exploring further.
render() on the root view of every dirty window. That method returns a tree of elements — lightweight value types that describe what should appear on screen. Kael then runs the tree through a layout pass powered by Taffy, and finally paints each element to the GPU. Because the entire element tree is rebuilt and dropped every frame, elements are cheap to construct and you never have to worry about stale references.
The Render trait
Any entity that represents a window’s root (or a subtree within it) implements the Render trait:
render method receives a mutable reference to your entity’s state and a Context<Self> that gives you access to the full app. It must return something that implements IntoElement — typically a call to div() or another built-in element function.
render takes &mut self, so you can freely read and mutate your entity’s state when producing the element tree. The Context<Self> gives you access to other entities, globals, and window APIs.IntoElement and the element tree
The IntoElement trait is the core conversion interface. Anything that can be turned into an Element implements it:
Vec of heterogeneous children — call .into_any_element() to get an AnyElement.
AnyElement for type-erased elements
AnyElement is the dynamically-typed envelope that Kael uses internally to store a mixed element tree. You rarely need to construct one manually; ParentElement::child() and ParentElement::children() call into_any_element() for you. It is, however, the type you work with when implementing your own low-level Element.
Composing children
Any element that implementsParentElement exposes .child() and .children() for building a subtree:
self and return Self, making them suitable for chaining:
Built-in elements
Kael ships a rich set of ready-to-use element constructors. The most common ones are:| Constructor | Description |
|---|---|
div() | The universal container element, analogous to HTML <div> |
label(text) | A styled text label |
img(source) | An image element supporting remote URLs and local assets |
svg(path) | An SVG renderer element |
canvas(paint_fn) | An imperative GPU canvas for custom drawing |
Element and Styled, so you can chain layout and style methods directly:
The Element trait
When you need full control over layout and painting — for example, to implement a code editor or a custom chart — you can implement Element directly:
request_layout → prepaint → paint) matches the browser’s layout model. In request_layout you describe your size constraints to Taffy and return any state you need later. In prepaint you commit hitboxes and prepare paint state. In paint you issue draw calls to the GPU.
RenderOnce for reusable components
RenderOnce is the idiomatic way to build reusable, stateless UI components. Unlike Render (which holds state across frames inside an entity), RenderOnce consumes self and is rebuilt on every frame:
#[derive(IntoElement)] macro generates the IntoElement implementation that wraps your component in a Component<Badge> and routes it through the element tree.
The #[derive(Render)] macro
For very simple views that don’t need full manual control, the #[derive(Render)] macro generates a boilerplate Render implementation. It is most useful for views whose render output is computed entirely from their fields with a single expression.
The render cycle and dirty tracking
Kael does not re-render every view on every frame. Instead it tracks which entities have been marked dirty — either becausecx.notify() was called or because a subscribed-to entity changed — and only re-renders the views that actually need updating. This dirty-tracking approach means Kael uses 0% CPU at idle: no entity is dirty, so no rendering occurs.
Entity marks itself dirty
Your entity calls
cx.notify() from within an update, or Kael marks it dirty automatically when a subscribed entity emits an event.Window schedules a repaint
The window associated with the dirty view is scheduled for a repaint on the next display refresh.
render() is called
Kael calls
render() on the dirty entity, producing a fresh element tree. The previous frame’s tree is discarded.Caching subtrees
For expensive subtrees that rarely change, you can opt into frame-level caching withAnyView::cached(). When a cached view has not been notified since the last frame, Kael recycles its previous layout and paint output:
cx.notify() is called on that entity, or whenever Window::refresh() is triggered.