Date Field
Enter a date segment by segment.
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.
Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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).
`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>.
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` 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>.
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()
}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>.
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(),
])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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(),
])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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).
Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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.
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()
}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
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
| Method | Values | Description |
|---|---|---|
full_width(bool) | true | false | Expands the root and input group to the available width. |
variant(FieldVariant) | FieldVariant::Primary | FieldVariant::Secondary | Selects shadowed field or lower-emphasis default surface chrome. |
// 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
| Builder | Values | Default | Description |
|---|---|---|---|
content(Partial | AnyElement | | — | Built-in field composition or a replacement content closure with complete field state. |
full_width( | true | | false | Expands the root and input group to the available width. |
focus_ring( | true | | true | GPUI extension: hides only the segmented field's visual focus ring while retaining focus and editing. |
new(Partial | string | — | The bound InputState entity supplies stable internal identity rather than a caller element id. |
value(Partial | DateValue | | — | Seeds the bound InputState's ISO text with the controlled Gregorian date on the first render; InputState::set_value updates it afterwards. |
default_value(Partial | DateValue | | — | Seeds an uncontrolled Gregorian date once. |
on_change(Partial | Fn( | — | Reports the date portion; time and zone value types are not surfaced. |
placeholder_value(Partial | DateValue | | — | Seeds empty-field keyboard edits with a Gregorian date. |
is_required( | true | | false | Marks the field required and blocks empty native form submission. |
is_invalid( | true | | false | Forces invalid chrome and validation reporting. |
min_value(Partial | DateValue | | — | Inclusive minimum Gregorian date. |
max_value(Partial | DateValue | | — | Inclusive maximum Gregorian date. |
is_date_unavailable(Partial | Fn( | — | Rejects individual Gregorian dates. |
validate(Partial | Fn( | — | Custom validation returns one optional GPUI message. |
validation_behavior( | ValidationBehavior:: | ValidationBehavior:: | Chooses blocking native or non-blocking ARIA-style form validation. |
granularity( | Granularity:: | Granularity:: | Adds time segments through the selected smallest unit. |
hour_cycle( | 12 | | HourCycle:: | Defaults to the system regional time format; an explicit cycle overrides it. |
should_force_leading_zeros( | true | | locale | Forces two-digit month, day and hour segments; otherwise numeric padding follows the system regional date and time patterns. |
is_disabled( | true | | false | Dims the whole field, removes it from interaction and form data. |
is_read_only( | true | | false | Keeps segment navigation and focus while blocking edits. |
name( | string | — | Registers a live ISO-formatted FormField. |
auto_focus( | true | | false | Focuses the segmented input on first render. |
variant( | FieldVariant:: | FieldVariant:: | Selects shadowed field or lower-emphasis default surface chrome. |
segment(Partial | DateSegment | — | 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( | AnyElement | — | Inert content before the segmented input. |
suffix( | AnyElement | — | Inert content after the segmented input. |
Not ported5 HeroUI entries not ported
| HeroUI v3 | Why it is not ported |
|---|---|
DateField.className | Browser styles are unavailable. |
DateField.style | Browser inline styles are unavailable. |
DateField.render | Root-element substitution has no GPUI equivalent. |
DateField.hideTimeZone | Has no zoned date-time value or time-zone segment. |
DateField.autoComplete | GPUI has no browser autofill channel. |
Parts
| Part | Description |
|---|---|
DateField | Field state, validation and form owner. |
DateField | Optional built-in label with required, invalid and disabled state. |
DateField | Focusable field chrome around input, prefix and suffix. |
DateFieldPartial | Built-in segmented input using the operating system's regional date order and separators rather than an independently composable part. |
DateFieldPartial | Keyboard-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. |
DateField | Inert leading content. |
DateField | Inert trailing content. |
DateField | Help text or generated format hint, hidden when invalid. |
DateFieldPartial | Resolved validation message; uses ErrorMessage as its built-in equivalent. |
Not ported1 HeroUI entry not ported
| HeroUI v3 | Why it is not ported |
|---|---|
DateField.InputContainer | Has one clipped input row and no public scrollable multi-input container. |
States
| State | Builder | Description |
|---|---|---|
Hovered | hover field background | Interactive group uses the field-hover fill outside focus. |
Focus within | focus_handle | Focused segments ring the field and use focus chrome. |
Invalid | validation::resolve | Danger field and segment styling replaces the description with an error. |
Disabled | is_disabled | The entire field is dimmed and inert. |
Read only | is_read_only gates edits | Segments remain navigable but cannot change. |
Required | is_required | Label marker and form validation reflect required state. |
Segment focused | focused_seg | The active segment uses accent-soft selection chrome. |
Segment placeholder | DateFieldDisplay cleared/empty state | Incomplete segments use muted placeholder text. |