Components

Date Picker

A date picker combines a button, a popover and a calendar so users can select a date or a range of dates.

Overview

按钮触发器 + Popover 内嵌 Calendar:「Pick a date」占位,选中后回显长格式日期并关闭弹层。

GPUI · Live previewGPUI WASM

Installation

Date Picker 是单个 Rust 文件(src/date_picker.rs),复用 calendar.rs 的日期数学 —— 不依赖 chrono。弹层定位用 deferred(..) overlay pass + on_children_prepainted 捕获触发器 bounds,嵌在任何布局里都能锚定。

Download runnable example

Terminal
# Download the runnable example crate, then:cargo run --locked -- --date-picker# Other demos:cargo run --locked -- --date-picker rangecargo run --locked -- --date-picker dobcargo run --locked -- --date-picker inputcargo run --locked -- --date-picker timecargo run --locked -- --date-picker natural

Usage

DatePicker 是一个 entity:把(可选的)Calendar entity 交给它托管,订阅 DatePickerEvent 拿选中态。Calendar 自身的能力(Range / dropdown caption / disabled dates / months(2))原样透出。

Example.rs
use justdo_command::calendar::{Calendar, CalendarMode};use justdo_command::date_picker::{DatePick, DatePicker, DatePickerEvent};// DatePicker wraps a Calendar entity in a popover behind a trigger.let calendar = cx.new(|_| Calendar::new());let picker = cx.new(|cx| {    DatePicker::new(Some(calendar), window, cx)        .placeholder("Pick a date")});cx.subscribe(&picker, |_, _, ev: &DatePickerEvent, cx| {    // ev.selection — Option<DatePick::Single(Date) | DatePick::Range{..}>    // ev.time      — Option<(hour, minute)> when .time_input(..) is wired    cx.notify();}).detach();// in render(): .child(picker.clone())

网页预览与桌面端运行同一份 Rust / GPUI 组件。

Composition

结构对齐 shadcn/ui 的 PopoverTrigger → Button + Popover → Calendar。

Structure
DatePicker                entity — owns open state + echoed selection├── trigger               button row: calendar icon + label + chevron ⌄│     label               "Pick a date" → "September 12, 2025"│     variant             text span, typed InputState, or natural input└── deferred popover      absolute, anchored under the trigger      ├── Calendar        entity — same one used standalone      └── Time row        .time_input(..) adds a "Time  [9:00]" footerDatePick                  Single(Date) | Range { start, end }DatePickerEvent           { selection, time } — emitted on every change

Input & parsing

三个变体共用一套手写 parser(零依赖):ISO/US 日期、12/24 小时时间、自然语言短语。

Example.rs
// Three parsers ship in date_picker.rs — no external crate:parse_date("2026-09-30")  // ISO — also YYYY/M/Dparse_date("9/30/2026")   // US — also M-D-YYYYparse_time("9:00")        // → (9, 0)parse_time("9:30 pm")     // → (21, 30); "12 am" → (0, 0)parse_natural("tomorrow")       // today + 1parse_natural("in 3 days")      // today + 3 (days/weeks/months)parse_natural("next Friday")    // nearest future Fridayparse_natural("2026-09-30")     // falls through to parse_date

Notes

Open/close semantics. 单选模式下点日期即关弹层(Radix 同款);Range 模式点起点后弹层保持,点终点才关。点击弹层外的遮罩也关闭。

Typed input. .date_input(input, cx) 把触发器的文案换成真实单行编辑器 —— 解析成功即高亮日历对应日期;反向从日历选中会把 ISO 日期写回输入框(subscribe 回调拿不到 Window,回写在 render 里应用 pending 值)。

Natural language. .natural_input(..) 不挂日历 —— Enter 解析 "tomorrow" / "in 3 days" / "next Friday" / ISO 日期,并在下方回显 "Your post will be published on …" 式确认语。

Anchoring. 弹层宽度按 mode 取 296/560px,水平方向钳在组件根 bounds 内,永远贴着触发器下沿 +6px。

Accessibility

Pointer semantics

触发器整行可点;输入变体里只有图标格触发开关,输入框点击不会冒泡成 toggle。弹层外有全幅遮罩承接 "点击外部关闭"。

Calendar internals

弹层内的日历复用 Calendar entity —— 每天是 gpui_base::Button(Tab/Enter/Space 完备),翻月按钮带 a11y label。

API Reference

DatePicker entity 的 builder API、读取方法与事件。

APISignatureNotes
DatePicker::new(..)Option<Entity<Calendar>>, window, cxHosts the calendar; None = input-only.
.placeholder(..)impl Into<SharedString>Trigger text before a pick.
.label(..)impl Into<SharedString>Field caption above the trigger.
.date_input(..)Entity<InputState>, cxTyped ISO/US date field.
.natural_input(..)Entity<InputState>, cxNatural-language parse on Enter.
.time_input(..)Entity<InputState>, cxTime row inside the popover.
.disabled(..)boolMuted + click-inert trigger.
set_open(..)bool, cxProgrammatic open/close.
date() / range()Option<..>Read the echoed selection.
DatePickerEvent{ selection, time }DatePick::Single | ::Range; Option<(h, m)>.

Source & inspiration

结构与视觉参考 shadcn/ui Date Picker (React Aria) 。本页交互由 Rust / GPUI 绘制,基础样式来自 gpui-kit 。