Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Date and time

Date Picker

A date field with a calendar popover.

Rust
use herogpui::components::date_picker::DatePicker;

DatePicker on docs.rsSource at v0.14.0

Usage

Showing International Calendar, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

International Calendar

The field and the popover grid share the locale override. Segment order follows that locale; selected values stay Gregorian ISO dates. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::DatePicker;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DatePicker::new(
        self.demo_calendar("dp-indian", cx),
    )
    .label("Date")
    .locale("en-US-u-ca-indian")
    .into_any_element()])

Disabled

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::DatePicker;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DatePicker::new(
        self.demo_calendar("dp-disabled", cx),
    )
    .label("Date")
    .is_disabled(true)
    .into_any_element()])

Controlled

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Date, DatePicker};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, px};
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        DatePicker::new(self.demo_calendar("dp-controlled", cx))
            .label("Date")
            .on_change(cx.listener(
                |this, d: &Option<Date>, _, cx| {
                    this.cal_picked = *d;
                    cx.notify();
                },
            ))
            .into_any_element(),
        para(
            &match self.cal_picked {
                Some(d) => format!("Value: {}", d.format_iso()),
                None => "No value".to_owned(),
            },
            cx,
        ),
    ])

Also calls para (included when you copy).

Validation

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Date, DatePicker};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DatePicker::new(
        self.demo_calendar("dp-invalid", cx),
    )
    .label("Date")
    // `minValue`/`maxValue` bound the calendar: everything
    // outside the range is unselectable.
    .min_value(Date::new(2025, 12, 1))
    .max_value(Date::new(2026, 6, 30))
    .is_invalid(true)
    .into_any_element()])

Format Options

The trigger follows the operating system's regional date order, separators, and numeric padding. Its state and submitted value stay ISO-formatted. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::DatePicker;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        DatePicker::new(self.demo_calendar("dp-format", cx))
            .label("Date")
            .into_any_element(),
    ])

Form Example

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Button, DatePicker, Form};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Form::new()
        .child(
            DatePicker::new(self.demo_calendar("dp-form", cx))
                .label("Start date"),
        )
        .child(Button::new("date-picker-form-submit").label("Save"))
        .into_any_element()])

Custom Indicator

A custom indicator replaces the default calendar glyph; this example uses a check without changing the trigger behavior. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, DatePicker, icons};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        DatePicker::new(self.demo_calendar("dp-indicator", cx))
            .label("Date")
            .trigger_indicator(gpui::svg()
                                   .size(px(16.))
                                   .path(icons::CHECK)
                                   .text_color(cx.colors().foreground)
                                   .into_any_element())
            .into_any_element(),
    ])

Render Function

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Button, DatePicker};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let is_open = self.date_picker_open;
let render_props_gallery = cx.entity().downgrade();

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DatePicker::new(
        self.demo_calendar("dp-render-props", cx)
    )
    .is_open(is_open)
    .is_required(true)
    .content(move |state| {
        let gallery = render_props_gallery.clone();
        gpui::div()
            .flex()
            .flex_col()
            .items_start()
            .gap(px(8.))
            .child(format!(
                "{} · {} · {}",
                if state.is_required {
                    "required"
                } else {
                    "optional"
                },
                if state.is_invalid { "invalid" } else { "valid" },
                if state.is_open { "open" } else { "closed" },
            ))
            .child(
                Button::new("date-picker-render-props-toggle")
                    .label(if state.is_open { "Close" } else { "Open" })
                    .on_press(move |_, _, cx| {
                        if let Some(gallery) = gallery.upgrade() {
                            gallery.update(cx, |gallery, cx| {
                                gallery.date_picker_open =
                                    !gallery.date_picker_open;
                                cx.notify();
                            });
                        }
                    }),
            )
            .into_any_element()
    })
    .into_any_element()])

Usage

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Date, DatePicker};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let is_open = self.date_picker_open;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DatePicker::new(self.demo_calendar("dp-usage", cx))
        // v3's Usage seeds the picker with `defaultValue`.
        .default_value(Date::new(2025, 12, 25))
        .label("Due date")
        .is_open(is_open)
        .on_open_change(cx.listener(|this, open: &bool, _, cx| {
            this.date_picker_open = *open;
            cx.notify();
        }))
        .on_change(cx.listener(
        |this, d: &Option<Date>, _, cx| {
                this.cal_picked = *d;
                this.date_picker_open = false;
                cx.notify();
            },
        ))
        .into_any_element()])

Placement

The calendar popover accepts the shared 22-value placement vocabulary. Defaults to a centered bottom popover; this specimen opts into top placement. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{DatePicker, Placement};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![
        DatePicker::new(self.demo_calendar("dp-placement", cx))
            .label("Top placement")
            .placement(Placement::Top)
            .default_open(true)
            .into_any_element(),
    ])

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

para
fn para(text: &str, cx: &App) -> gpui::AnyElement {
    let colors = cx.colors();
    gpui::div()
        .text_size(px(14.5))
        .line_height(px(24.))
        .text_color(colors.foreground)
        .max_w(px(720.))
        .child(text.to_owned())
        .into_any_element()
}

Anatomy

Rust types

DatePicker

Date Picker is assembled from these builders. The API reference lists each one.

Customization

Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Date Picker looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.

Styling

Date Picker styling
MethodValuesDescription
placement(Placement)PlacementThe full 22-value union renders through the shared vocabulary with default eight-pixel popover offset: physical and aligned spellings plus the logical start/end aliases, which share their left/right side's pixels in this LTR-only port. The centered bottom value matches default.
Rust
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
    el.bg(gpui::rgba(0xffa500ff))             // background
        .text_color(gpui::rgba(0x000000ff))   // text
        .w(gpui::px(13.))                     // size
        .h(gpui::px(12.))
})

API reference

Against HeroUI v3.2.6: 29 entries ported, 5 partial, 2 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Date Picker builders
BuilderValuesDefaultDescription
value(date)DateValue | null—Seeds the controlled date into the caller-owned CalendarState on the first render.
default_value(date)DateValue | null—Seeds the uncontrolled date once without fighting later edits.
on_change(callback)Fn(value: DateValue | null) -> ()—Reports valid field edits and calendar selections.
is_open(bool)true | false—Controls the calendar popover without mutating local open state.
default_open(bool)true | falsefalseSeeds uncontrolled popover state.
on_open_change(callback)Fn(isOpen: bool) -> ()—Reports trigger, selection, Escape, outside-press and focus-departure changes.
is_disabled(bool)true | falsefalseRemoves the field and trigger from interaction and form submission.
is_read_only(bool)true | falsefalseKeeps the date focusable while suppressing edits, opening and selection.
is_required(bool)true | falsefalseBlocks native form submission while empty and focuses the editable field.
is_invalid(bool)true | false—Forces invalid field and calendar state.
validate(callback)PartialFn(value: DateValue | null) -> ValidationError | true | null—A callback supplies one optional validation message; does not expose structured ValidationError object.
validation_behavior(ValidationBehavior)ValidationBehavior::Native | ValidationBehavior::AriaValidationBehavior::NativeSelects blocking native validation or non-blocking ARIA-style validation.
validation_errors(errors)Partialstring[]—Server messages take precedence and mark the field invalid; independently composed FieldError message content is unavailable.
min_value(date)DateValue—Earliest valid field and calendar date.
max_value(date)DateValue—Latest valid field and calendar date.
is_date_unavailable(predicate)Fn(date: DateValue) -> bool—Rejects individual dates inside the range.
first_day_of_week(Weekday)stringWeekday::LocaleThe calendar grid defaults from the operating system's regional date preferences through CLDR week data; the local Weekday enum provides an explicit override.
should_close_on_select(bool)Partialtrue | falsetrueThe boolean form controls whether a calendar selection dismisses the popover; callback-valued policy is not represented.
auto_focus(bool)true | falsefalseFocuses the editable date field on first render.
name(text)string—Submits the displayed date text under this name.
content(render)AnyElement | Fn(values: DatePickerRenderProps) -> AnyElement—Replacement content receives disabled, invalid, read-only, required, focus and open state.
trigger_indicator(element)AnyElementAnyElement::CalendarIconReplaces the glyph inside the existing trigger geometry and behavior.
placement(Placement)PlacementPlacement::BottomThe full 22-value union renders through the shared vocabulary with default eight-pixel popover offset: physical and aligned spellings plus the logical start/end aliases, which share their left/right side's pixels in this LTR-only port. The centered bottom value matches default.
Not ported2 HeroUI entries not ported
Date Picker builders not ported
HeroUI v3Why it is not ported
DatePicker.className / styleBrowser styles and inline styles are unavailable.
DatePicker.renderRoot-element substitution has no GPUI equivalent.

Parts

Date Picker parts
PartDescription
DatePickerRoot state owner and focus-within scope with a system-regionally formatted DateField. Each picker keeps its own CalendarState identity.
DatePickerPartialSeparate keyboard and pointer action inside the date field suffix.
DatePickerDefault or caller-supplied 16px trigger glyph.
DatePickerPartialCalendar overlay positioned by the shared Placement vocabulary.

States

Date Picker states
StateBuilderDescription
Opencontrolled/open overlay stateMounts the calendar overlay and hands open state to replacement content.
Focus withinclose_on_blur focus scopeTracks focus across the editable field, trigger and calendar.
Focus visibletrigger focus ringDraws the trigger ring and hands keyboard-visible root focus to replacement content.
Disabledis_disabled(bool)Applies disabled opacity and removes editing, opening and submission.
Read onlyis_read_only(bool)Keeps the field focusable while making field, trigger and calendar inert.
Requiredis_required(bool)Marks the label and blocks empty native submission.
Invalidresolved DatePicker validityCombines controlled, server, custom, syntax and date-constraint validation.