Slint Kit Documentation

Files

Directory Picker for Slint

KitDirectoryPicker · Slint Kit 0.3.0

Browse and clear actions for one selected directory.

Browse and clear actions for one selected directory.
Native app built from the example below.

File dialogs and OS drag-and-drop require the native application 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.

Choose a real folder asynchronously, then clear the selection. Rust retains a DirectoryHandle and handles cancellation or unsupported platforms.

ui/app.slint

export { KitFormValidation, HtmlInputKind, NumberInputFormat, KitInputConstraints, KitValidationResult, KitValidityState } from "@kit/kit.slint";
import {KitDirectoryPicker,KitThemes,HostRequestPresentation} from "@kit/kit.slint";
export {HostRequestPresentation}
export component App inherits Window{
 title:"Directory picker";preferred-width:540px;preferred-height:320px;max-width:100000px;max-height:100000px;background:KitThemes.light.canvas;
 in property <string> selected;in property <string> error;in property <HostRequestPresentation> request-state;callback browse();callback clear();
 VerticalLayout{padding:24px;spacing:16px;alignment:start;control:=KitDirectoryPicker{label:"Project folder";selected-name:root.selected;error:root.error;request-state:root.request-state;browse-requested=>{root.browse();}clear-requested=>{root.clear();}}}
}

src/main.rs

use slint::ComponentHandle;
use slint_kit::{
    DirectoryHandle, DirectoryRequest, HostCapability, HostError, HostRequestController,
    SelectionOutcome,
};
use std::{cell::RefCell, rc::Rc};
mod ui {
    slint::include_modules!();
}
fn fail(app: &ui::App, error: HostError) {
    app.set_request_state(if error == HostError::Unsupported {
        ui::HostRequestPresentation::Unsupported
    } else {
        ui::HostRequestPresentation::Failed
    });
    app.set_error(format!("{error:?}").into());
}
fn main() -> Result<(), slint::PlatformError> {
    let app = ui::App::new()?;
    slint_kit::init_form_validation!(ui, app);
    let selected = Rc::new(RefCell::new(None::<DirectoryHandle>));
    let requests = Rc::new(RefCell::new(
        HostRequestController::<DirectoryHandle>::default(),
    ));
    if slint_kit::native::capabilities().directories == HostCapability::Unsupported {
        app.set_request_state(ui::HostRequestPresentation::Unsupported);
    }
    let weak = app.as_weak();
    let shared = requests.clone();
    let folder = selected.clone();
    app.on_browse(move || {
        let Some(app) = weak.upgrade() else {
            return;
        };
        let ticket = shared.borrow_mut().begin();
        app.set_request_state(ui::HostRequestPresentation::Pending);
        app.set_error("".into());
        let weak_async = weak.clone();
        let shared_async = shared.clone();
        let folder = folder.clone();
        if slint::spawn_local(async move {
            let outcome = slint_kit::native::pick_directory(DirectoryRequest {
                title: Some("Choose a project folder".into()),
            })
            .await;
            let Some(app) = weak_async.upgrade() else {
                return;
            };
            let mut request = shared_async.borrow_mut();
            if !request.finish(ticket, outcome) {
                return;
            }
            match request.take_result().unwrap() {
                SelectionOutcome::Selected(value) => {
                    app.set_selected(value.display_name.as_str().into());
                    *folder.borrow_mut() = Some(value);
                    app.set_request_state(ui::HostRequestPresentation::Idle);
                }
                SelectionOutcome::Cancelled => {
                    app.set_request_state(ui::HostRequestPresentation::Cancelled)
                }
                SelectionOutcome::Failed(error) => fail(&app, error),
            }
        })
        .is_err()
        {
            shared.borrow_mut().cancel();
            fail(&app, HostError::Unavailable);
        }
    });
    let weak = app.as_weak();
    app.on_clear(move || {
        if let Some(app) = weak.upgrade() {
            requests.borrow_mut().cancel();
            *selected.borrow_mut() = None;
            app.set_selected("".into());
            app.set_error("".into());
            app.set_request_state(ui::HostRequestPresentation::Idle);
        }
    });
    app.run()
}

Cargo.toml and build.rs

Cargo.toml

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

[dependencies]
slint-kit = { version = "=0.3.0", features = ["native"] }
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

Enable the kit’s native feature and await native::pick_directory. Store DirectoryHandle in Rust and publish its display name.

Cancellation preserves the accepted directory. Clear removes the selection; unsupported platforms show an explicit state.

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
Browse and clear actions for one selected directory.
Native screenshot of the same example, rendered with Skia.
// SPDX-License-Identifier: GPL-3.0-or-later
import { KitDirectoryPicker, KitTheme, KitThemes } from "@kit/kit.slint";

export component Example inherits Window {
    title: "KitDirectoryPicker example";
    preferred-width: 520px;
    preferred-height: 260px;
    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: "Directory Picker"; color: root.theme.text-primary; font-size: 20px * root.theme.text-scale; font-weight: 600; }
        KitDirectoryPicker { theme: root.theme; label: "Export folder"; selected-name: "Documents/Project exports"; browse-requested => { root.status = "Host folder request"; } }
        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 Rectangle.

Properties

Name Type Direction
required bool in
required-message string in
custom-validity string in-out
validity KitValidityState out
will-validate bool out
validation-message string out
theme KitTheme in
control-size ControlSize in
access FieldAccess in
request-state HostRequestPresentation in
label string in
selected-name string in
error string in

Types and variants

Type Declaration
enum ControlSize compact, medium, comfortable
enum FieldAccess editable, read-only, disabled
enum HostRequestPresentation idle, pending, cancelled, failed, unsupported
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,

Callbacks

Functions

See also