Documentation 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.
Every form control in Kael is a controlled element: you own the value in your view’s state, pass it in each frame, and receive the next value through an on_change callback. This mirrors React’s controlled-component model. All built-in controls also integrate with Kael’s window-scoped undo/redo manager — users get Cmd-Z / Cmd-Shift-Z for free without any extra wiring on your part.
text_input()
A fully featured single-line or multiline editable text field with platform IME support, clipboard integration, and word-boundary navigation.
Signature
pub fn text_input(id: impl Into<ElementId>, text: impl Into<SharedString>) -> TextInput
id must be stable across frames. text is the current field value (you own it).
Methods on TextInput
// Placeholder text displayed when the field is empty
pub fn placeholder(self, placeholder: impl Into<SharedString>) -> Self
// Enable wrapped multiline editing
pub fn multi_line(self) -> Self
// Limit visible height of a multiline field to N lines
pub fn max_lines(self, max_lines: usize) -> Self
// Mask the displayed content (password field)
pub fn password(self) -> Self
// Apply a custom InputMask to normalize edits before they are committed
pub fn mask(self, mask: impl InputMask) -> Self
// Called on every content change with (new_value, window, cx)
pub fn on_change(
self,
listener: impl Fn(SharedString, &mut Window, &mut App) + 'static,
) -> Self
// Called when the user presses Enter (single-line) or Cmd-Enter (multiline)
pub fn on_submit(
self,
listener: impl Fn(SharedString, &mut Window, &mut App) + 'static,
) -> Self
// Replace the entire paint surface with a custom renderer
pub fn render_with(
self,
renderer: impl Fn(TextInputRenderState, &mut Window, &mut App) + 'static,
) -> Self
TextInputRenderState (for custom renderers)
When you supply .render_with(), Kael calls your closure each frame with a TextInputRenderState snapshot:
| Field | Type | Description |
|---|
value | SharedString | The underlying field value |
display_text | SharedString | Text as displayed (masked or placeholder) |
placeholder | Option<SharedString> | The configured placeholder |
showing_placeholder | bool | True when placeholder is visible |
focused | bool | Whether the field owns keyboard focus |
hovered | bool | Whether the pointer hovers the hitbox |
multi_line | bool | Whether multiline mode is active |
lines | Vec<TextInputRenderLine> | Shaped lines and their paint origins |
selection_bounds | Vec<Bounds<Pixels>> | Selection rectangles in render space |
cursor_bounds | Option<Bounds<Pixels>> | Caret rectangle, when visible |
The snapshot also provides three convenience paint methods:
state.paint_text(window, cx);
state.paint_selection(color, window);
state.paint_cursor(color, window);
state.paint_default_contents(window, cx); // all three with default colors
Keyboard actions
The following actions are bound inside the TextInput key context automatically:
Backspace, Delete, DeleteWordBackward, DeleteWordForward, MoveLeft, MoveRight, MoveWordLeft, MoveWordRight, SelectLeft, SelectRight, SelectWordLeft, SelectWordRight, MoveToStart, MoveToEnd, SelectToStart, SelectToEnd, SelectAll, Paste, Copy, Cut, Undo, Redo, InsertNewline, Submit
Example
text_input("search-field", self.query.clone())
.placeholder("Search…")
.on_change(|value, _window, cx| {
cx.update_view(self_entity, |view, _cx| {
view.query = value;
});
})
.on_submit(|value, _window, cx| {
cx.dispatch_action(SearchAction { query: value });
})
.w_full()
.px(px(12.0))
.py(px(8.0))
.bg(theme.input_bg)
.rounded_md()
checkbox()
A controlled tri-state checkbox with built-in indeterminate support.
Signature
pub fn checkbox(id: impl Into<ElementId>, checked: bool) -> Checkbox
Methods on Checkbox
// Visible label rendered next to the indicator
pub fn label(self, label: impl Into<SharedString>) -> Self
// Put the checkbox into an indeterminate visual state
pub fn indeterminate(self, indeterminate: bool) -> Self
// Disable the checkbox, preventing user interaction
pub fn disabled(self) -> Self
// Called with the next checked value after user interaction
pub fn on_change(
self,
listener: impl Fn(&bool, &mut Window, &mut App) + 'static,
) -> Self
// Replace the default indicator + label with a custom element
pub fn render_with(
self,
renderer: impl Fn(CheckboxRenderState, &Window, &App) -> AnyElement + 'static,
) -> Self
CheckboxRenderState exposes checked, indeterminate, label, focused, and disabled.
Example
checkbox("notifications-enabled", self.notifications_enabled)
.label("Enable notifications")
.on_change(|&checked, _window, cx| {
cx.update_view(self_entity, |view, _| {
view.notifications_enabled = checked;
});
})
When the checkbox is in the indeterminate state, the first click always transitions it to checked: true, regardless of the previous checked value.
toggle()
A binary on/off toggle switch — semantically equivalent to a checkbox but rendered as a sliding pill.
Signature
pub fn toggle(id: impl Into<ElementId>, on: bool) -> Toggle
Methods on Toggle
// Visible label
pub fn label(self, label: impl Into<SharedString>) -> Self
// Disable the toggle
pub fn disabled(self) -> Self
// Called with the next on/off state
pub fn on_change(
self,
listener: impl Fn(&bool, &mut Window, &mut App) + 'static,
) -> Self
// Replace the default pill with a custom element
pub fn render_with(
self,
renderer: impl Fn(ToggleRenderState, &Window, &App) -> AnyElement + 'static,
) -> Self
ToggleRenderState exposes on, label, focused, and disabled.
Example
toggle("dark-mode", self.dark_mode)
.label("Dark mode")
.on_change(|&on, _window, cx| {
cx.update_view(self_entity, |view, _| view.dark_mode = on);
})
slider()
A continuous or discrete range input rendered as a draggable track.
Signature
pub fn slider(id: impl Into<ElementId>, value: f64) -> Slider
Methods on Slider
// Set the minimum value (default: 0.0)
pub fn min(self, min: f64) -> Self
// Set the maximum value (default: 100.0)
pub fn max(self, max: f64) -> Self
// Set the keyboard step increment and drag snap interval
pub fn step(self, step: f64) -> Self
// Snap drag interactions to discrete step boundaries
pub fn discrete(self) -> Self
// Render the slider vertically (default size becomes 24 × 160 px)
pub fn vertical(self) -> Self
// Disable the slider
pub fn disabled(self) -> Self
// Called continuously during drag and on keyboard input
pub fn on_change(
self,
listener: impl Fn(&f64, &mut Window, &mut App) + 'static,
) -> Self
// Replace the default track + thumb with a custom renderer
pub fn render_with(
self,
renderer: impl Fn(SliderRenderState, Bounds<Pixels>, &mut Window, &mut App) + 'static,
) -> Self
SliderRenderState exposes value, min, max, percentage (0.0–1.0), dragging, focused, and disabled.
The undo entry is recorded once per drag gesture (on mouse up), not on every intermediate movement.
Example
slider("volume", self.volume)
.min(0.0)
.max(1.0)
.step(0.01)
.on_change(|&value, _window, cx| {
cx.update_view(self_entity, |view, _| view.volume = value);
})
.w_full()
select()
A popup-backed combo box for selecting a single value from a labeled option list.
Signature
pub fn select<T, I, O>(id: impl Into<ElementId>, value: T, options: I) -> Select<T>
where
T: Clone + PartialEq + 'static,
I: IntoIterator<Item = O>,
O: Into<SelectOption<T>>
Options can be supplied as SelectOption<T> values or as (T, label) tuples (both implement Into<SelectOption<T>>).
Methods on Select<T>
// Placeholder text shown when no option matches the current value
pub fn placeholder(self, placeholder: impl Into<SharedString>) -> Self
// Enable text filtering inside the popup
pub fn searchable(self) -> Self
// Called with the newly selected value
pub fn on_change(
self,
listener: impl Fn(&T, &mut Window, &mut App) + 'static,
) -> Self
// Replace the trigger element with a custom renderer
pub fn render_with(
self,
renderer: impl Fn(SelectRenderState, &Window, &App) -> AnyElement + 'static,
) -> Self
// Replace individual option rows with a custom renderer
pub fn render_options_with(
self,
renderer: impl Fn(SelectOptionRenderState<T>, &Window, &App) -> AnyElement + 'static,
) -> Self
// Replace the popup shell with a custom renderer
pub fn render_popup_with(
self,
renderer: impl Fn(SelectPopupRenderState, Vec<AnyElement>, &Window, &App) -> AnyElement + 'static,
) -> Self
// Replace the in-popup search field with a custom renderer
pub fn render_search_with(
self,
renderer: impl Fn(SelectSearchRenderState, AnyElement, &Window, &App) -> AnyElement + 'static,
) -> Self
Example
#[derive(Clone, PartialEq)]
enum Language { Rust, TypeScript, Python }
select(
"language-select",
self.language.clone(),
[
(Language::Rust, "Rust"),
(Language::TypeScript, "TypeScript"),
(Language::Python, "Python"),
],
)
.placeholder("Choose a language")
.searchable()
.on_change(|lang, _window, cx| {
cx.update_view(self_entity, |view, _| view.language = lang.clone());
})
.min_w(px(200.0))
All form controls support Styled because they render via div() internally. Chain layout methods (.w_full(), .mt_2(), etc.) directly on the control builder.