Slint Kit Documentation

Text input

Text Field for Slint

KitTextField · Slint Kit 0.3.1

Single-line native text input with a label and validation feedback.

Single-line native text input with a label and validation feedback.
Native app built from the example below.

Try the component

Download the complete project, extract it and run cargo run --locked in its folder. Rust 1.92+; Slint Kit 0.3.0 from crates.io. You can also copy the four files below.

Type a draft and click Accept to send it to Rust. This example accepts nonempty text; the field purpose does not validate its business meaning.

ui/app.slint

export { KitFormValidation, HtmlInputKind, NumberInputFormat, KitInputConstraints, KitValidationResult, KitValidityState } from "@kit/kit.slint";
import { KitTextField, KitButton, KitThemes, ValidationPresentation } from "@kit/kit.slint";
export component App inherits Window {
    title: "Text field"; preferred-width: 520px; preferred-height: 320px;
    max-width: 100000px; max-height: 100000px; background: KitThemes.light.canvas;
    in-out property <string> draft; in property <string> error; in property <string> accepted;
    callback edited(string); callback commit(); callback blurred(); callback cancel();
    
    VerticalLayout {
        padding: 24px; spacing: 16px; alignment: start;
        control := KitTextField {
            required: true;
            label: "Text field"; text <=> root.draft; error: root.error;
            validation: root.error != "" ? ValidationPresentation.invalid : ValidationPresentation.pristine;
            
            edited(value) => { root.edited(value); }
            commit-requested(value) => { root.commit(); }
            cancelled => { root.cancel(); }
            focus-observed(focused) => { if (!focused) { root.blurred(); } }
            
        }
        KitButton { text: "Accept"; activated => { root.commit(); } }
        Text { text: "Accepted: " + root.accepted; color: KitThemes.light.text-primary; wrap: word-wrap; }
    }
}

src/main.rs

use slint::ComponentHandle;
use slint_kit::*;
slint::include_modules!();
#[derive(Clone, PartialEq)]
struct Value(String);
fn parse(text: &str) -> DraftValue<Value> {
    if text.is_empty() {
        DraftValue::Empty
    } else {
        DraftValue::Parsed(Value(text.into()))
    }
}
fn format(value: &Value) -> String {
    value.0.clone()
}
fn main() -> Result<(), slint::PlatformError> {
    let app = App::new()?;
    slint_kit::init_form_validation!(self, app);
    let initial = Value("Alex Morgan".into());
    app.set_accepted(format(&initial).into());
    let weak = app.as_weak();
    let field = FieldBinding::<Value, ()>::new(
        Some(initial),
        Ownership::Local,
        CommitPolicy::OnBlur,
        AbsencePolicy::Required,
        parse,
        format,
        |_| String::new(),
        move |view| {
            if let Some(app) = weak.upgrade() {
                app.set_draft(view.draft.into());
                app.set_error(view.error.into());
            }
        },
    );
    field.set_html_constraints(slint_kit::HtmlConstraints {
        kind: slint_kit::HtmlInputKind::Text, required: true,
        ..Default::default()
    });
    let weak = app.as_weak();
    field.on_intent(move |intent| {
        if let Some(app) = weak.upgrade() {
            if let FieldIntent::Commit(value) = intent {
                app.set_accepted(format(&value).into());
            }
        }
    });
    let binding = field.clone();
    app.on_edited(move |text| {
        let _ = binding.edited(&text);
    });
    let binding = field.clone();
    app.on_commit(move || {
        let _ = binding.commit(CommitTrigger::Submit);
    });
    let binding = field.clone();
    app.on_blurred(move || {
        let _ = binding.commit(CommitTrigger::Blur);
    });
    let binding = field.clone();
    app.on_cancel(move || binding.cancel());

    app.run()
}

Cargo.toml and build.rs

Cargo.toml

[package]
name = "slint-kit-text-field-example"
version = "0.1.0"
edition = "2024"
rust-version = "1.92"
license = "GPL-3.0-or-later"
publish = false

[dependencies]
slint-kit = "=0.3.0"
slint = { version = "=1.18.1", default-features = false, features = ["std", "compat-1-18", "backend-winit", "renderer-skia", "accessibility"] }

[build-dependencies]
slint-kit-build = "=0.3.0"

[workspace]

build.rs

fn main() {
    slint_kit_build::compile("ui/app.slint").expect("compile component example");
}

Files: Cargo.toml · build.rs · ui/app.slint · src/main.rs

Bind text to a draft and handle edited, commit-requested and cancelled. Use FieldBinding to retain the last accepted value.

The example accepts nonempty text on blur or Accept. Native editing keeps caret, selection and undo.

Choose between built-in options and custom composition

Shared options

Visual composition

The file below produces the screenshot. For controller-driven components, it shows the displayed state without supplying the Rust wiring. Create a project.

Show the screenshot source
Single-line native text input with a label and validation feedback.
Native screenshot of the same example, rendered with Skia.
// SPDX-License-Identifier: GPL-3.0-or-later
import { KitTextField, KitTheme, KitThemes } from "@kit/kit.slint";

export component Example inherits Window {
    title: "KitTextField example";
    preferred-width: 420px;
    preferred-height: 180px;
    max-width: 100000px;
    max-height: 100000px;
    background: root.theme.canvas;
    in-out property <KitTheme> theme: KitThemes.light;
    in-out property <string> status;
    VerticalLayout {
        padding: 24px; spacing: 16px; alignment: start;
        Text { text: "Text Field"; color: root.theme.text-primary; font-size: 20px * root.theme.text-scale; font-weight: 600; }
        KitTextField { theme: root.theme; label: "Project name"; text: "Field notes"; edited(value) => { root.status = "Draft: " + value; } }
        if root.status != "": Text { text: root.status; color: root.theme.text-secondary; font-size: 12px * root.theme.text-scale; wrap: word-wrap; }
    }
}

Download this example

Public API

Inherits KitField.

Properties

Name Type Direction
theme KitTheme in
control-size ControlSize in
access FieldAccess in
validation ValidationPresentation in
purpose TextPurpose in
input-type InputType in
input-kind HtmlInputKind in
validation-twelve-hour bool in
number-format NumberInputFormat in
validation-text string in
display-text string in
intrinsic-error string in
required bool in
multiple bool in
min-length int in
max-length int in
pattern string in
pattern-enabled bool in
min string in
max string in
step string in
default-value string in
validation-timing ValidationTiming in
custom-validity string in-out
required-message string in
email-message string in
url-message string in
pattern-message string in
too-short-message string in
too-long-message string in
underflow-message string in
overflow-message string in
step-message string in
bad-input-message string in
validity KitValidityState out
will-validate bool out
validation-ready bool out
validation-message string out
pattern-error string out
value string out
dirty bool out
touched bool out
secret-visibility SecretVisibility in-out
line-mode TextLineMode in
resize-policy ResizePolicy in
min-lines int in
max-lines int in
label string in
accessible-name string in
input-method-hints InputMethodHints in
show-validation-message bool in
validation-visible bool out
description string in
error string in
placeholder string in
text-letter-spacing length in
text-alignment TextHorizontalAlignment in
prefix string in
suffix string in
text string in-out
show-character-count bool in
character-count int in
reveal-label string in
hide-label string in
clear-label string in
character-count-label string in
checking-label string in
has-focus bool out

Types and variants

Type Declaration
enum ControlSize compact, medium, comfortable
enum FieldAccess editable, read-only, disabled
enum HtmlInputKind text, search, telephone, email, url, password, text-area, number, date, month, week, time, date-time-local, checkbox, radio, select, file, range, color
struct KitValidityState valid: bool, value-missing: bool, type-mismatch: bool, pattern-mismatch: bool, too-long: bool, too-short: bool, range-underflow: bool, range-overflow: bool, step-mismatch: bool, bad-input: bool, custom-error: bool,
enum NumberInputFormat canonical, decimal-comma
enum ResizePolicy fixed, auto-grow
enum SecretVisibility hidden, revealed
enum TextLineMode single-line, multiline
enum TextPurpose plain, email, url, telephone, password, search
enum ValidationPresentation pristine, checking, valid, invalid
enum ValidationTiming on-blur, on-input, on-submit

Callbacks

Functions

See also