Calendar
A state-driven date grid with selection matchers and custom item rendering.
Like every gpui-base primitive, Calendar supplies behavior and semantic structure without imposing a product visual language. Apply GPUI styles and compose the exported parts to match your design system.
#Example
The single native Cargo entrypoint selects this primitive from the shared showcase implementation. The same showcase is compiled once for the WASM preview above.
cargo run -p gpui-base --example components -- calendar
#Import
use gpui_kit::base::{Calendar, CalendarState};
#Anatomy and API
The example composes Calendar, CalendarState. GPUI’s standard styling and event traits provide presentation; these base types provide the interaction structure.
The authoritative module is components/calendar.rs. Native and browser previews compile this same file.
#State and events
Selection lives in CalendarState; configure matching and update the state from calendar item interaction.
Keep controlled state on the parent render type or in a GPUI entity. Update it in callbacks and call cx.notify(); do not recreate persistent entities during every render.
#Complete Rust example
The complete implementation used by the runnable showcase is embedded directly from Rust source:
use super::*;
impl BaseShowcase {
pub(in super::super) fn calendar(&self) -> impl IntoElement {
Calendar::new("example-calendar", &self.calendar)
// 7 × 32px cells + 12px padding on each side + 1px borders.
.w(px(250.))
.p_3()
.border_1()
.border_color(super::example_rgb(0xd4d4d4))
.item(|item, state, _, _| {
match state.kind() {
CalendarItemKind::Previous | CalendarItemKind::Next => item
.size_7()
.flex()
.items_center()
.justify_center()
.hover(|s| s.bg(super::example_rgb(0xf5f5f5))),
CalendarItemKind::MonthToggle | CalendarItemKind::YearToggle => item
.px_1()
.h_7()
.flex()
.items_center()
.justify_center()
.text_xs()
.hover(|s| s.bg(super::example_rgb(0xf5f5f5))),
CalendarItemKind::Weekday => item
.size_8()
.flex()
.items_center()
.justify_center()
.text_xs()
.text_color(super::example_rgb(0x737373)),
CalendarItemKind::Day => item
.size_8()
.flex()
.items_center()
.justify_center()
.text_xs()
.when(state.is_muted(), |s| {
s.text_color(super::example_rgb(0xa3a3a3))
})
.when(state.is_today() && !state.is_active(), |s| {
s.border_1().border_color(super::example_rgb(0xd4d4d4))
})
.when(state.is_active(), |s| {
s.bg(super::example_rgb(0x171717))
.text_color(super::example_rgb(0xffffff))
})
.when(!state.is_disabled() && !state.is_active(), |s| {
s.hover(|s| s.bg(super::example_rgb(0xf5f5f5)))
}),
CalendarItemKind::Month | CalendarItemKind::Year => item
.w(px(74.))
.h_7()
.flex()
.items_center()
.justify_center()
.text_xs()
.when(state.is_active(), |s| {
s.bg(super::example_rgb(0x171717))
.text_color(super::example_rgb(0xffffff))
})
.when(!state.is_active(), |s| {
s.hover(|s| s.bg(super::example_rgb(0xf5f5f5)))
}),
}
.into_any_element()
})
.label(|kind, value| match kind {
CalendarItemKind::Previous => "‹".into(),
CalendarItemKind::Next => "›".into(),
CalendarItemKind::MonthToggle | CalendarItemKind::Month => [
"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec",
][value as usize]
.into(),
CalendarItemKind::Weekday => {
["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"][value as usize].into()
}
_ => value.to_string().into(),
})
}
}
The command above supplies application initialization, window creation, and shared BaseShowcase state.
#Accessibility
Label dates and selected, disabled, and today states; retain arrow-key navigation.
#Notes
Use stable element IDs where accepted. Verify focus, hover, active, selected, disabled, reduced-motion, and high-contrast appearances in the consuming design system.