limn
    ↑↓ ChooseEnter OpenEsc Close
    GitHub

    Components/Inputs

    DatePicker

    A field for a local calendar date as YYYY-MM-DD over a month calendar to choose it from. Use it inline, in a form or a dialog; it does not open or close.

    Native componentGuide source

    Preview

    CodeSource
    fn view(state: &State, palette: ComponentPalette) -> Element {
        let (year, month) = state.shown_month;
        DatePicker::new("due", &state.due, palette).display_month(year, month).render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        match action {
            UiAction::InputChanged { id, value } if id == "due" => state.due = value.clone(),
            UiAction::Clicked { id } => {
                let (year, month) = state.shown_month;
                if let Some(date) = DatePicker::selected_date(id, "due") {
                    state.due = date.to_owned();
                } else if id == "due:month_prev" {
                    state.shown_month = DatePicker::shift_month(year, month, -1);
                } else if id == "due:month_next" {
                    state.shown_month = DatePicker::shift_month(year, month, 1);
                }
            }
            _ => {}
        }
    }

    Examples

    Each one is the library drawing it. Press, type and hover.

    Date picker2 / 2
    CodeSource
    row(vec![DatePicker::new("dates-date-off", "2025-05-14", palette).disabled().render()])

    DatePicker

    A field for a local calendar date as YYYY-MM-DD over a month calendar to choose it from. Use it inline, in a form or a dialog; it does not open or close.

    Import

    use limn::{Component, DatePicker};

    Usage

    A date picker is controlled: pass the date as text each frame, and store what the field and the calendar report. The field reports every edit under the picker’s own ID, and a day under {id}:day:YYYY-MM-DD, which DatePicker::selected_date decodes.

    fn view(state: &State, palette: ComponentPalette) -> Element {
        let (year, month) = state.shown_month;
        DatePicker::new("due", &state.due, palette).display_month(year, month).render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        match action {
            UiAction::InputChanged { id, value } if id == "due" => state.due = value.clone(),
            UiAction::Clicked { id } => {
                let (year, month) = state.shown_month;
                if let Some(date) = DatePicker::selected_date(id, "due") {
                    state.due = date.to_owned();
                } else if id == "due:month_prev" {
                    state.shown_month = DatePicker::shift_month(year, month, -1);
                } else if id == "due:month_next" {
                    state.shown_month = DatePicker::shift_month(year, month, 1);
                }
            }
            _ => {}
        }
    }

    A field keeps the text typed in it, whatever value it is built with again. So after a day is chosen, give the field the new text:

    tree.set_input_value("due", &state.due);

    The text is the host’s, valid or not: a date half typed stays as typed. DatePicker::is_valid_date(value) says whether it is a real date, from year 1 to 9999, written with every digit.

    The month shown

    DatePicker::new("due", &state.due, palette).display_month(2025, 5).render()

    The month shown is separate from the date, so the arrows browse without choosing anything. Without display_month the calendar shows the month of the date, or the current month in UTC when the text is not a valid date. A year outside 1 to 9999 or a month outside 1 to 12 is ignored.

    DatePicker::shift_month(year, month, delta) gives the month delta months away and stops at January of year 1 and December of 9999, where the arrow towards the end is drawn disabled.

    The weeks start on Monday. The days of the months before and after that fill the first and last weeks are muted, and can be chosen like the others.

    Disabled

    DatePicker::new("due", &state.due, palette).disabled().render()
    DatePicker::new("due", &state.due, palette).enabled(state.can_edit).render()

    A disabled picker shows its date and its month in muted ink. The field, the arrows and the days take no pointer or focus and report nothing.

    Keyboard

    The field, the two arrows and every day are tab stops. Enter or Space on an arrow or a day reports its click.

    Actions

    ActionWhen
    UiAction::InputChanged { id, value }The text of the field changes; id is the picker’s.
    UiAction::Clicked { id } with {id}:day:YYYY-MM-DDA day is chosen.
    UiAction::Clicked { id } with {id}:month_prev or {id}:month_nextAn arrow of the calendar is pressed.

    Accessibility

    The field is called “Date”, the library’s own word, unless the picker is given a name of its own:

    DatePicker::new("start", &state.start, palette).accessibility_label("Start date").render()

    Each arrow is a button named by the month it goes to, such as “April 2025”, and each day a button named by its whole date, such as “14 May 2025”, that says whether it is the chosen one. In a disabled picker they are still there, as disabled. The names of the months and the weekdays come from limn::labels().

    API reference

    The guide covers composition, options and actions. Generate the complete Rust type and builder reference from the checkout:

    cargo doc -p limn --open

    Component API overview · State and actions

    The example is drawn by crates/limn-gallery/src/pages/dates.rs.