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

Date and time

Date Field

Enter a date segment by segment.

Rust
use herogpui::components::date_picker::DateField;

DateField on docs.rsSource at v0.14.0

Usage

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

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::{ActiveTheme, Date, DateField};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, px};
use herogpui::gpui;

let iso = self.date_iso;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![
        DateField::new(self.date_input.clone())
            // v3's Usage seeds the field with `defaultValue`.
            .default_value(Date::new(2025, 12, 25))
            .label("Start date")
            .radius(px(4.))
            .on_change(cx.listener(
                |this, d: &Option<Date>, _, cx| {
                    this.date_iso = *d;
                    cx.notify();
                },
            ))
            .into_any_element(),
        para(
            &match iso {
                Some(d) => format!("Parsed: {}", d.format_iso()),
                None => {
                    "Type digits, or step a segment with the arrow keys".to_owned()
                }
            },
            cx,
        ),
    ])

Also calls para (included when you copy).

Box Customisation

`height`, `padding_x` and `is_bare` resize the box in one call. A 28px bare box with an 8px inset. 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::DateField;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DateField::new(self.demo_text("df-custom-box", "", cx))
        .label("Compact")
        .height(px(28.))
        .padding_x(px(8.))
        .is_bare(true)
        .font_family(MONO_FONT)
        .into_any_element()])

Also calls MONO_FONT (included when you copy).

Granularity

`granularity` sets the smallest unit the field shows. Below `day` it grows the time segments -- the same ones a `TimeField` has, so the arrows step them and digits type into them -- and the bound state holds an ISO date-and-time. 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::{DateField, Granularity, HourCycle};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

{
    let mut examples = vec![gpui::div()
                                .flex()
                                .flex_wrap()
                                .items_center()
                                .justify_center()
                                .gap(px(12.))
                                .children(Granularity::ALL
                                            .iter()
                                            .copied()
                                            .map(|granularity| {
                                                let key = match granularity {
                                                    Granularity::Day => "df-gran-day",
                                                    Granularity::Hour => "df-gran-hour",
                                                    Granularity::Minute => "df-gran-minute",
                                                    Granularity::Second => "df-gran-second",
                                                };
                                                DateField::new(self.demo_text(
                                                    key,
                                                    "2025-02-03T08:45:09",
                                                    cx,
                                                ))
                                                .granularity(granularity)
                                                    .into_any_element()
                                            }))
                                .into_any_element()];
    examples.push(DateField::new(self.demo_text(
                          "df-gran-12h",
                          "2025-02-03T20:45",
                          cx,
                      ))
                      .label("Twelve-hour clock")
                      .granularity(Granularity::Minute)
                      .hour_cycle(HourCycle::H12)
                      .into_any_element());
    gpui::div()
        .flex()
        .flex_col()
        .items_start()
        .justify_center()
        .gap(px(12.))
        .children(examples)
        .into_any_element()
}

Forced Leading Zeros

The system locale controls date and time segment order, separators, padding, and day-period names. The prop forces month, day, and hour segments to two digits. 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::{DateField, Granularity, HourCycle};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![
        DateField::new(self.demo_text(
            "df-leading-locale",
            "2025-02-03T08:05:07",
            cx,
        ))
        .label("System locale")
        .granularity(Granularity::Second)
        .hour_cycle(HourCycle::H12)
        .into_any_element(),
        DateField::new(self.demo_text(
            "df-leading-forced",
            "2025-02-03T08:05:07",
            cx,
        ))
        .label("Forced two-digit fields")
        .granularity(Granularity::Second)
        .hour_cycle(HourCycle::H12)
        .should_force_leading_zeros(true)
        .into_any_element(),
    ])

With Icons

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, DateField, icons};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DateField::new(self.demo_text("df-icon", "", cx))
        .label("Date")
        .prefix(gpui::svg()
                    .size(px(16.))
                    .path(icons::MOON)
                    .text_color(cx.colors().foreground)
                    .into_any_element())
        .into_any_element()])

Variants

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::{DateField, FieldVariant};
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![
        DateField::new(self.demo_text("df-primary", "", cx))
            .label("Primary")
            .into_any_element(),
        DateField::new(self.demo_text("df-secondary", "", cx))
            .label("Secondary")
            .variant(FieldVariant::Secondary)
            .into_any_element(),
    ])

In Surface

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::{DateField, FieldVariant, Surface};
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![Surface::new()
        .padding(px(24.))
        .gap(px(16.))
        .child(
            DateField::new(self.demo_text("df-surface", "", cx))
                .label("Date")
                .variant(FieldVariant::Secondary),
        )
        .into_any_element()])

With Description

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::DateField;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DateField::new(self.demo_text("df-desc", "", cx))
        .label("Date")
        .description("Month, day and year")
        .into_any_element()])

Required Field

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::DateField;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DateField::new(self.demo_text("df-req", "", cx))
        .label("Date")
        .is_required(true)
        .into_any_element()])

Disabled State

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::DateField;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DateField::new(self.demo_text(
        "df-dis",
        "2025-12-25",
        cx,
    ))
    .label("Date")
    .is_disabled(true)
    .into_any_element()])

Full Width

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::DateField;
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![DateField::new(self.demo_text("df-full", "", cx))
        .label("Date")
        .full_width(true)
        .into_any_element()])

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::DateField;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DateField::new(self.demo_text(
        "df-invalid",
        "",
        cx,
    ))
    .label("Date")
    .is_required(true)
    .is_invalid(true)
    .validation_errors(["Pick a date"])
    .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, DateField};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, px};
use herogpui::gpui;

let iso = self.date_iso;

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

Also calls para (included when you copy).

With 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, DateField};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .w(px(256.))
    .gap(px(12.))
    .children(vec![DateField::new(self.demo_text(
        "df-validate",
        "",
        cx,
    ))
    .label("Date")
    .min_value(Date::new(2025, 1, 1))
    .max_value(Date::new(2025, 12, 31))
    .description("Must fall in 2025")
    .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, DateField, Form, FormField};
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![{
        let field = self.demo_text("df-form", "", cx);
        Form::new()
            .field(FormField::text(field.clone()).name("start"))
            .child(
                DateField::new(field)
                    .label("Start date")
                    .is_required(true),
            )
            .child(Button::new("date-field-form-submit").label("Save"))
            .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()
}
MONO_FONT
const MONO_FONT: &str = if cfg!(target_arch = "wasm32") {
    // The web shell bundles JetBrains Mono; the literal family "monospace"
    // resolves to nothing there and panics text resolution.
    "JetBrains Mono"
} else if cfg!(target_os = "macos") {
    "Menlo"
} else {
    "Consolas"
};

Anatomy

Rust types

DateField

Date Field 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 Field 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 Field styling
MethodValuesDescription
full_width(bool)true | falseExpands the root and input group to the available width.
variant(FieldVariant)FieldVariant::Primary | FieldVariant::SecondarySelects shadowed field or lower-emphasis default surface chrome.
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: 32 entries ported, 14 partial, 6 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Date Field builders
BuilderValuesDefaultDescription
content(render)PartialAnyElement | Fn(values: DateFieldRenderProps) -> AnyElement—Built-in field composition or a replacement content closure with complete field state.
full_width(bool)true | falsefalseExpands the root and input group to the available width.
focus_ring(bool)true | falsetrueGPUI extension: hides only the segmented field's visual focus ring while retaining focus and editing.
new(state)Partialstring—The bound InputState entity supplies stable internal identity rather than a caller element id.
value(Option<Date>)PartialDateValue | null—Seeds the bound InputState's ISO text with the controlled Gregorian date on the first render; InputState::set_value updates it afterwards.
default_value(Date)PartialDateValue | null—Seeds an uncontrolled Gregorian date once.
on_change(callback)PartialFn(value: DateValue | null) -> ()—Reports the date portion; time and zone value types are not surfaced.
placeholder_value(Date)PartialDateValue | null—Seeds empty-field keyboard edits with a Gregorian date.
is_required(bool)true | falsefalseMarks the field required and blocks empty native form submission.
is_invalid(bool)true | falsefalseForces invalid chrome and validation reporting.
min_value(Date)PartialDateValue | null—Inclusive minimum Gregorian date.
max_value(Date)PartialDateValue | null—Inclusive maximum Gregorian date.
is_date_unavailable(callback)PartialFn(date: DateValue) -> bool—Rejects individual Gregorian dates.
validate(callback)PartialFn(value: DateValue) -> ValidationError | true | null—Custom validation returns one optional GPUI message.
validation_behavior(ValidationBehavior)ValidationBehavior::Native | ValidationBehavior::AriaValidationBehavior::NativeChooses blocking native or non-blocking ARIA-style form validation.
granularity(Granularity)Granularity::Day | Granularity::Hour | Granularity::Minute | Granularity::SecondGranularity::DayAdds time segments through the selected smallest unit.
hour_cycle(HourCycle)12 | 24HourCycle::LocaleDefaults to the system regional time format; an explicit cycle overrides it.
should_force_leading_zeros(bool)true | falselocaleForces two-digit month, day and hour segments; otherwise numeric padding follows the system regional date and time patterns.
is_disabled(bool)true | falsefalseDims the whole field, removes it from interaction and form data.
is_read_only(bool)true | falsefalseKeeps segment navigation and focus while blocking edits.
name(value) + form_field()string—Registers a live ISO-formatted FormField.
auto_focus(bool)true | falsefalseFocuses the segmented input on first render.
variant(FieldVariant)FieldVariant::Primary | FieldVariant::SecondaryFieldVariant::PrimarySelects shadowed field or lower-emphasis default surface chrome.
segment(render)PartialDateSegment—Hands custom content each supported Gregorian date or plain-time segment and its generated text. Date and time segments follow the operating system's regional order, separators, padding, and day-period names; era and time-zone segment kinds require value models does not expose.
prefix(element)AnyElement—Inert content before the segmented input.
suffix(element)AnyElement—Inert content after the segmented input.
Not ported5 HeroUI entries not ported
Date Field builders not ported
HeroUI v3Why it is not ported
DateField.classNameBrowser styles are unavailable.
DateField.styleBrowser inline styles are unavailable.
DateField.renderRoot-element substitution has no GPUI equivalent.
DateField.hideTimeZoneHas no zoned date-time value or time-zone segment.
DateField.autoCompleteGPUI has no browser autofill channel.

Parts

Date Field parts
PartDescription
DateFieldField state, validation and form owner.
DateFieldOptional built-in label with required, invalid and disabled state.
DateFieldFocusable field chrome around input, prefix and suffix.
DateFieldPartialBuilt-in segmented input using the operating system's regional date order and separators rather than an independently composable part.
DateFieldPartialKeyboard-editable Gregorian date and optional plain-time segment with custom rendering and regional date order; era and time-zone kinds are unavailable with the current value model.
DateFieldInert leading content.
DateFieldInert trailing content.
DateFieldHelp text or generated format hint, hidden when invalid.
DateFieldPartialResolved validation message; uses ErrorMessage as its built-in equivalent.
Not ported1 HeroUI entry not ported
Date Field parts not ported
HeroUI v3Why it is not ported
DateField.InputContainerHas one clipped input row and no public scrollable multi-input container.

States

Date Field states
StateBuilderDescription
Hoveredhover field backgroundInteractive group uses the field-hover fill outside focus.
Focus withinfocus_handleFocused segments ring the field and use focus chrome.
Invalidvalidation::resolveDanger field and segment styling replaces the description with an error.
Disabledis_disabledThe entire field is dimmed and inert.
Read onlyis_read_only gates editsSegments remain navigable but cannot change.
Requiredis_requiredLabel marker and form validation reflect required state.
Segment focusedfocused_segThe active segment uses accent-soft selection chrome.
Segment placeholderDateFieldDisplay cleared/empty stateIncomplete segments use muted placeholder text.