Calendar
Calendar is the month-view date grid in the authoring widget set.
It is the lower-level calendar surface that powers date-picking flows. Your app provides the current year and month, the optionally selected date, and callbacks for both day selection and month navigation. This explicit model matters because calendars usually mix product rules with user interface rules: what month is shown, what day is selected, and what navigation is allowed.
Example
use chrono::NaiveDate;
use fission::prelude::*;
use std::sync::Arc;
let widget: Widget = Calendar {
year: view.state().visible_year,
month: view.state().visible_month,
selected_date: view.state().selected_day,
on_select: Some(Arc::new(move |date: NaiveDate| ActionEnvelope {
id: set_selected_day_id,
payload: serde_json::to_vec(&SetSelectedDay(date)).unwrap(),
})),
on_navigate: Some(Arc::new(move |year, month| ActionEnvelope {
id: set_visible_month_id,
payload: serde_json::to_vec(&SetVisibleMonth { year, month }).unwrap(),
})),
cell_size: Some(40.0),
padding: Some(16.0),
}
.into();
The reducer usually stores both the selected day and the currently visible month. Those are related, but they are not always the same thing.
Field table
| | | |
|---|
| | Year shown in the current month view. | |
| | Month shown in the current month view. | Required. Expected range is 1..=12. |
| | Currently selected day, if any. | |
| Option<Arc<dyn Fn(NaiveDate) -> ActionEnvelope + Send + Sync>> | Closure that builds the action for a picked day. | Called when the user presses a day cell. |
| Option<Arc<dyn Fn(i32, u32) -> ActionEnvelope + Send + Sync>> | Closure that builds the action for previous or next month. | Called with the new (year, month) pair. |
| | Width and height of each day cell. | Defaults to 36.0. Use smaller sizes in sidebars and larger ones in full panels. |
| | Outer padding around the calendar surface. | |
State ownership and practical limits
Calendar does not compute product rules such as unavailable dates, range constraints, or locale-specific week starts. The checked-in implementation is Sunday-first, uses single-letter weekday headings, and highlights today using the host's local date.
That makes it a good general month picker, but if your product needs Monday-first weeks, blocked dates, or complex business calendars, plan on wrapping or extending the widget rather than assuming those rules are built in.
Specific advice
Keep visible-month state explicit even when a date is selected. Users often need to look at another month without committing a new date yet.
Production checklist
For Calendar, review the fields that change behavior before treating the widget as finished: year, month, selected_date, on_select, on_navigate, cell_size. The goal is to make the product rule visible in state and actions, not hidden inside ad-hoc construction code.
Bind on_select, on_navigate to explicit reducer actions and test that the reducer handles unavailable, duplicate, or invalid input safely.
Check the semantics tree for the user-facing label or role that makes this widget understandable without relying only on pixels.
Prefer parent layout and design-system sizing first; use explicit size or spacing fields when the product layout requires that constraint on this widget specifically.
Add at least one component or harness test that confirms the visible text, semantic role, action dispatch, and layout constraint that matter for this widget in context.
If a screen starts repeating the same Calendar setup, extract a named component around this widget. That keeps the reference API small while making product code easier to read and safer for generated code to copy.
DatePicker, DateRangePicker, TimePicker, and Pagination.