Calendar
A month grid for picking a single date.
1use herogpui::components::calendar::{Calendar, CalendarState};Usage
Indian and Hebrew calendar grids use English labels here. Navigation follows each calendar while selected values remain Gregorian dates.
1use herogpui::prelude::{Calendar, CalendarState, Date};
2use gpui::prelude::*;
3
4row(vec![
5 Calendar::new(self.demo_calendar("cal-indian", cx))
6 .locale("en-US-u-ca-indian")
7 .default_value(Date::new(2026, 1, 15))
8 .into_any_element(),
9 Calendar::new(self.demo_calendar("cal-hebrew", cx))
10 .locale("en-US-u-ca-hebrew")
11 .default_value(Date::new(2024, 3, 25))
12 .into_any_element(),
13])Live HeroGPUI compiled to WebAssembly. Select any example without loading another WASM instance.
Anatomy
Rust types
Calendar
Calendar is assembled from these builders. The API reference lists each one.
Customization
Appearance builders and theme tokens Calendar uses.
Styling
| Style | Description |
|---|---|
CALENDAR_WIDTH = 252px | Single-month width is exact; multiple months use the documented 256px panels, 32px gaps and horizontal scrolling. GPUI has no CSS container-query context. |
VisibleDuration::Weeks + seven 36px circles | Seven fixed circular cells reproduce the week grid geometry through GPUI flex rows. |
week_aligned_rows + visible_start disabled guard | Seven weekday columns, disabled leading dates and trailing blanks match, with 4px between the weekday block and date rows. |
items_center + justify_between + px(2px) + pb(16px) | The header aligns its controls with a 2px horizontal inset and 16px bottom padding. |
text_size(14px) + line_height(20px) + MEDIUM | Month headings use 14px/20px medium text independent of the host line height. |
year_picker_open header branch | The open picker substitutes same-size spacers instead of fading buttons in place. |
24px + soft_radius + hover + ring_if_focused | Geometry, disabled state and focus ring exist; pressed and state transitions are incomplete. |
svg size(16px) | Icon size matches; direction-aware rotation is not available. |
seven flex_1 cells per row + no horizontal gap | All views divide each panel into seven equal columns without horizontal gaps; multi-month panels are 256px wide. |
weekday_header seven flex_1 children | Weekday cells are a separate seven-column flex sibling rather than flattened table contents. |
month_grid flex_col + preceding gap(4px) | Date rows start 4px below the weekday block and remain contiguous. |
text_size(12px) + line_height(16px) + MEDIUM + muted + pb(8px) | Weekday labels use 12px/16px medium muted text with 8px bottom padding. |
cell_size = column_width / 7 + text_size(14px) + line_height(20px) + MEDIUM | Day cells center 14px/20px medium text in a square one seventh of the panel width, including selected, disabled and custom cells. |
anim::pressed on selectable unselected branch | Unselected press geometry animates; selected and focus-shadow interpolation is incomplete. |
is_today border_1(marker) | Uses a border rather than v3's soft fill treatment. |
is_sel accent fill | The selected fill matches; selected press interpolation and accent-hover are absent. |
muted + outer opacity(0.5) | The whole cell subtree, including custom content and indicators, is dimmed. |
unavailable muted + selectable gate | Pointer inertia matches; muted text replaces v3's opacity and not-allowed cursor. |
disabled branch + line_through | Out-of-range dates are muted and struck through; unavailable dates are not struck. |
absolute bottom(2px) + size(3px) + marker color | Size and selected color match; GPUI uses a 2px inset and accent resting color rather than 4px and muted. |
gap(4px) + key_radius + px(6px) py(2px) | The trigger is composed and focusable, with extra GPUI padding and hover fill. |
12px CHEVRON_UP / CHEVRON_DOWN | GPUI swaps muted up/down glyphs instead of rotating and interpolating one indicator. |
absolute inset_0 + retained day layout + ScrollHandle + three-cell rows + gap(4px) + p(4px) | The scrollable three-column year grid occupies the retained day area; opening and keyboard movement reveal the active row. |
h(32px) + px(10px) + control_radius + text_size(14px) + line_height(20px) + MEDIUM | Year geometry and selected/hover/focus treatments are present; transitions are absent. |
API reference
Builders
| Builder | Type | Default | Description |
|---|---|---|---|
selection_mode( | SelectionMode | SelectionMode:: | Whether one or many dates can be selected. |
value( | value, | — | Controlled scalar or multiple selection. |
default_value( | DateValue | | — | Initial uncontrolled scalar or multiple selection. |
on_change( | ( | — | Reports scalar or complete multiple-selection changes. |
focused_value( | Date | — | Controls the constrained focus date and realigns the visible range; movement waits for owner acceptance. |
on_focus_change( | Fn( | — | Reports keyboard or selectable-cell focus movement. |
min_value( | Date | Calendar-aware 1900-01-01 | Defaults to Gregorian 1900-01-01; an explicit minimum overrides it. |
max_value( | Date | Calendar-aware 2099-12-31 | Defaults to Gregorian 2099-12-31; an explicit maximum overrides it. |
weeks_in_month( | usize | — | Overrides the derived number of visible week rows. |
is_date_unavailable( | Fn( | — | Marks real in-month and adjacent-month dates unavailable. |
first_day_of_week( | Weekday | Locale default | Defaults from the operating system's regional date preferences through CLDR week data; an explicit weekday overrides it, with Sunday as the invalid-locale fallback. |
page_behavior( | PageBehavior | PageBehavior:: | Pages by the visible duration or one displayed unit. |
selection_alignment( | SelectionAlignment | SelectionAlignment:: | Aligns the initial visible range around the selection; picking preserves that displayed range. |
is_disabled( | bool | false | Disables navigation, focus and selection and dims the whole calendar. |
is_read_only( | bool | false | Keeps keyboard navigation while preventing pointer and selection changes. |
is_invalid( | bool | false | Marks selected and today treatments with an invalid accent, without v3's browser validation surface. |
visible_duration( | VisibleDuration | {months: 1} | Selects month, week or day view and its visible count. |
default_year_picker_open( | bool | false | Seeds the uncontrolled internal year picker open. |
is_year_picker_open( | bool | — | Controls the internal year picker open state. |
on_year_picker_open_change( | Fn( | — | Reports changes to the internal year picker. |
offset( | i32 | — | Shifts every visible heading globally rather than configuring one composed heading. |
visible_years( | usize | min-max span or 20 | Controls the bounded year window; otherwise the implicit 1900–2099 span is shown. |
cell( | string | — | Hands the day label to custom cell content; it is numeric rather than locale-formatted. |
Parts
| Part | Description |
|---|---|
Calendar | Root state, layout and keyboard-navigation owner. |
Calendar | Header row containing navigation and the visible-range heading. |
Calendar | Formatted heading for one visible month or linear range. |
Calendar | Previous and next section controls with replaceable icons. |
Calendar | One seven-column month, week or day grid. |
Calendar | Weekday header container. |
Calendar | Visible date-row container. |
Calendar | One weekday label. |
Calendar | Focusable date cell with state-driven custom content. |
Calendar | Optional three-pixel metadata indicator inside a cell. |
Calendar | Focusable heading control that toggles year-picker mode. |
Calendar | Heading content inside the year-picker trigger. |
Calendar | Chevron showing the year-picker open state. |
Calendar | Scrollable three-column year surface overlaying the retained day area. |
Calendar | Fragment-style body that maps the visible year window into three-cell rows. |
Calendar | Focusable year option that returns to the day grid after selection. |
States
| Builder | State | Description |
|---|---|---|
eligible membership + accent fill | Selected | Accent fill and foreground on selectable selected dates. |
is_today border | Today | Uses an accent-soft fill; currently draws an accent outline. |
is_unavailable + selectable gate | Unavailable | Keyboard-focusable but pointer-inert date with disabled styling. |
outside_month + opacity(0.5) | Outside month | Real adjacent-month date, -disabled and unselected at half opacity. |
hover(default.soft_hover()) | Hovered | Default fill on selectable cells; v3's today-specific hover token is missing. |
anim::pressed + active(default) | Pressed | Default fill and 0.95 scale on unselected cells; selected press styling is missing. |
grid_focus + with_focus_ring | Focus visible | Roving in-month focus ring driven by the calendar cursor. Month boundaries, paging, alignment and year selection follow the chosen calendar system while focus values stay Gregorian. |
is_disabled / out_of_range | Disabled | Inert calendar or date with disabled opacity and in-month line-through. |
is_read_only + selectable gate | Read only | Pointer-inert cells retain keyboard focus and navigation without selection. |
year_picker_open overlay + invisible day body | Year picker open | The scrollable year grid overlays the retained day layout, without the staggered crossfade. |
active_year accent branch | Year cell selected | Accent fill follows the roving year cursor and closes on activation. |