Slint Kit Documentation

Dates

Calendrier pour Slint

KitCalendar · Slint Kit 0.3.1

Grille mensuelle pour choisir une date civile.

Grille mensuelle pour choisir une date civile.
Application native de l’exemple ci-dessous.

Essayer le composant

Télécharger le projet complet, le décompresser et lancer cargo run --locked dans son dossier. Rust 1.92+ ; Slint Kit 0.3.0 depuis crates.io. Vous pouvez aussi copier les quatre fichiers ci-dessous.

Naviguez entre les mois ou choisissez un jour. Rust valide la date civile et régénère la grille du calendrier.

ui/app.slint

export { KitFormValidation, HtmlInputKind, NumberInputFormat, KitInputConstraints, KitValidationResult, KitValidityState } from "@kit/kit.slint";
import { KitCalendar,KitThemes,CalendarDay,CalendarNavigation,CivilDateView,DateRangePhase } from "@kit/kit.slint";
export {CalendarDay,CalendarNavigation,CivilDateView,DateRangePhase}
export component App inherits Window {
 title:"calendar";preferred-width:480px;preferred-height:520px;max-width:100000px;max-height:100000px;background:KitThemes.light.canvas;
 in property <[CalendarDay]> days;in property <int> active;in property <string> calendar-title;in property <string> accepted;
 callback navigate(CalendarNavigation);callback choose(CalendarDay);callback cancel();
 VerticalLayout {padding:24px;spacing:16px;alignment:start;
 control:=KitCalendar{days:root.days;weekdays:["M","T","W","T","F","S","S"];active-index:root.active;title:root.calendar-title;navigate(step)=>{root.navigate(step);}choose(day)=>{root.choose(day);}cancelled=>{root.cancel();}}
 Text{text:"Accepted: "+root.accepted;color:KitThemes.light.text-primary;wrap:word-wrap;}
 }
}

src/main.rs

use slint::ComponentHandle;
use slint_kit::{CalendarController, CalendarMove, CivilDate, WeekStart};
use std::{cell::RefCell, rc::Rc};
mod ui {
    slint::include_modules!();
}
struct State {
    calendar: CalendarController,
    accepted: CivilDate,
}
fn movement(step: ui::CalendarNavigation) -> CalendarMove {
    match step {
        ui::CalendarNavigation::PreviousDay => CalendarMove::PreviousDay,
        ui::CalendarNavigation::NextDay => CalendarMove::NextDay,
        ui::CalendarNavigation::PreviousWeek => CalendarMove::PreviousWeek,
        ui::CalendarNavigation::NextWeek => CalendarMove::NextWeek,
        ui::CalendarNavigation::WeekStart => CalendarMove::WeekStart,
        ui::CalendarNavigation::WeekEnd => CalendarMove::WeekEnd,
        ui::CalendarNavigation::PreviousMonth => CalendarMove::PreviousMonth,
        ui::CalendarNavigation::NextMonth => CalendarMove::NextMonth,
        ui::CalendarNavigation::PreviousYear => CalendarMove::PreviousYear,
        ui::CalendarNavigation::NextYear => CalendarMove::NextYear,
    }
}
fn publish(app: &ui::App, state: &State) {
    let slots = state.calendar.grid_slots();
    let days = slots
        .iter()
        .map(|slot| {
            slot.map_or_else(ui::CalendarDay::default, |cell| ui::CalendarDay {
                year: cell.date.year(),
                month: cell.date.month() as i32,
                day: cell.date.day() as i32,
                label: cell.date.day().to_string().into(),
                accessible_label: cell.date.iso_string().into(),
                enabled: cell.enabled,
                selected: cell.selected,
                in_range: false,
                today: false,
            })
        })
        .collect::<Vec<_>>();

    app.set_days(slint::ModelRc::new(slint::VecModel::from(days)));
    app.set_active(
        slots
            .iter()
            .position(|s| s.is_some_and(|cell| cell.focused))
            .unwrap_or(0) as i32,
    );
    let month = state.calendar.displayed();
    app.set_calendar_title(format!("{:04}-{:02}", month.year(), month.month()).into());
    app.set_accepted(state.accepted.iso_string().into());
}
fn main() -> Result<(), slint::PlatformError> {
    let app = ui::App::new()?;
    slint_kit::init_form_validation!(ui, app);
    let date = CivilDate::new(2026, 10, 17).unwrap();
    let state = Rc::new(RefCell::new(State {
        calendar: CalendarController::new(Some(date), date.year_month(), None, WeekStart::Monday),
        accepted: date,
    }));
    publish(&app, &state.borrow());
    let weak = app.as_weak();
    let shared = state.clone();
    app.on_navigate(move |step| {
        if let Some(app) = weak.upgrade() {
            let mut state = shared.borrow_mut();
            if state.calendar.navigate(movement(step)).is_ok() {
                publish(&app, &state);
            }
        }
    });
    let weak = app.as_weak();
    let shared = state.clone();
    app.on_choose(move |day| {
        if !day.enabled {
            return;
        }
        if let (Some(app), Ok(date)) = (
            weak.upgrade(),
            CivilDate::new(day.year, day.month as u32, day.day as u32),
        ) {
            let mut state = shared.borrow_mut();
            if state.calendar.choose(date).is_ok() {
                state.accepted = date;
                publish(&app, &state);
            }
        }
    });
    let weak = app.as_weak();
    let shared = state.clone();
    app.on_cancel(move || {
        if let Some(app) = weak.upgrade() {
            publish(&app, &shared.borrow());
        }
    });

    app.run()
}

Cargo.toml et build.rs

Cargo.toml

[package]
name = "slint-kit-calendar-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");
}

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

Construisez le modèle des jours avec CalendarController puis connectez sélection et navigation CalendarNavigation.

L’exemple reconstruit la grille lors de la navigation et affiche le CivilDate sélectionné. La semaine commence le lundi.

Choisir entre une option intégrée et une composition personnalisée

Options partagées

Composition visuelle

Le fichier ci-dessous produit la capture. Pour les composants pilotés par un contrôleur, il montre l’état affiché sans fournir le branchement Rust. Créer un projet.

Afficher le fichier de la capture
Grille mensuelle pour choisir une date civile.
Capture native du même exemple, moteur Skia.
// Public label overrides localize this fixture; toolkit/host defaults keep their language.
// SPDX-License-Identifier: GPL-3.0-or-later
// Display projections are fixtures. Validate accepted domain values in Rust.
import { KitCalendar, KitTheme, KitThemes } from "@kit/kit.slint";

export component Example inherits Window {
    title: "KitCalendar — exemple";
    preferred-width: 360px;
    preferred-height: 440px;
    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: "Calendrier"; color: root.theme.text-primary; font-size: 20px * root.theme.text-scale; font-weight: 600; }
        KitCalendar { previous-month-label: "Mois précédent"; next-month-label: "Mois suivant"; label: "Choisir une date"; weekdays: ["L", "M", "M", "J", "V", "S", "D"]; theme: root.theme; title: "Octobre 2026"; days: [{ year: 2026, month: 9, day: 28, label: "28", accessible-label: "28 septembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 9, day: 29, label: "29", accessible-label: "29 septembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 9, day: 30, label: "30", accessible-label: "30 septembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 1, label: "1", accessible-label: "1er octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 2, label: "2", accessible-label: "2 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 3, label: "3", accessible-label: "3 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 4, label: "4", accessible-label: "4 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 5, label: "5", accessible-label: "5 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 6, label: "6", accessible-label: "6 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 7, label: "7", accessible-label: "7 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 8, label: "8", accessible-label: "8 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 9, label: "9", accessible-label: "9 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 10, label: "10", accessible-label: "10 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 11, label: "11", accessible-label: "11 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 12, label: "12", accessible-label: "12 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 13, label: "13", accessible-label: "13 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 14, label: "14", accessible-label: "14 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 15, label: "15", accessible-label: "15 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 16, label: "16", accessible-label: "16 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 17, label: "17", accessible-label: "17 octobre 2026", enabled: true, selected: true, today: true, in-range: false }, { year: 2026, month: 10, day: 18, label: "18", accessible-label: "18 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 19, label: "19", accessible-label: "19 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 20, label: "20", accessible-label: "20 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 21, label: "21", accessible-label: "21 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 22, label: "22", accessible-label: "22 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 23, label: "23", accessible-label: "23 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 24, label: "24", accessible-label: "24 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 25, label: "25", accessible-label: "25 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 26, label: "26", accessible-label: "26 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 27, label: "27", accessible-label: "27 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 28, label: "28", accessible-label: "28 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 29, label: "29", accessible-label: "29 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 30, label: "30", accessible-label: "30 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 10, day: 31, label: "31", accessible-label: "31 octobre 2026", enabled: true, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 1, label: "1", accessible-label: "1er novembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 2, label: "2", accessible-label: "2 novembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 3, label: "3", accessible-label: "3 novembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 4, label: "4", accessible-label: "4 novembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 5, label: "5", accessible-label: "5 novembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 6, label: "6", accessible-label: "6 novembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 7, label: "7", accessible-label: "7 novembre 2026", enabled: false, selected: false, today: false, in-range: false }, { year: 2026, month: 11, day: 8, label: "8", accessible-label: "8 novembre 2026", enabled: false, selected: false, today: false, in-range: false }];  choose(day) => { root.status = "Jour demandé " + day.day; } }
        if root.status != "": Text { text: root.status; color: root.theme.text-secondary; font-size: 12px * root.theme.text-scale; wrap: word-wrap; }
    }
}

Télécharger cet exemple

API publique

Hérite de Rectangle.

Propriétés

Nom Type Sens
min string in
max string in
step string in
default-value string in
theme KitTheme in
control-size ControlSize in
access FieldAccess in
days [CalendarDay] in
weekdays [string] in
active-index int in
title string in
label string in
previous-month-label string in
next-month-label string in
request-focus bool in
has-focus bool out

Types et variantes

Type Déclaration
struct CalendarDay year: int, month: int, day: int, label: string, accessible-label: string, enabled: bool, selected: bool, in-range: bool, today: bool,
enum CalendarNavigation previous-day, next-day, previous-week, next-week, week-start, week-end, previous-month, next-month, previous-year, next-year
enum ControlSize compact, medium, comfortable
enum FieldAccess editable, read-only, disabled

Signaux

Fonctions

Voir aussi