Calendar
A calendar displays a grid of days organized into weeks and months. Users can select a single date by clicking on a day cell. Calendars are useful for date selection in scheduling, booking, and form contexts.
Import
import { Calendar } from '@proyecto-viviana/solid-spectrum';
import { CalendarDateClass as CalendarDate } from '@proyecto-viviana/solid-stately';Basic Date Selection
A simple calendar that allows users to pick a date. The selected date is tracked via a signal and displayed below the calendar.
Selected date: None
const [selectedDate, setSelectedDate] = createSignal<DateValue | null>(null);
<Calendar
aria-label="Event date"
value={selectedDate()}
onChange={setSelectedDate}
/>
<p>Selected: {selectedDate()?.toString() ?? "None"}</p>Disabled Dates
Use the isDateUnavailable callback to prevent specific dates from being selected. Unavailable dates appear visually muted and cannot be clicked.
Feb 14-16 are unavailable
const unavailableDates = [
new CalendarDate(2026, 2, 14),
new CalendarDate(2026, 2, 15),
new CalendarDate(2026, 2, 16),
];
const isDateUnavailable = (date: DateValue) =>
unavailableDates.some(
(d) => d.year === date.year && d.month === date.month && d.day === date.day
);
<Calendar
aria-label="Appointment date"
isDateUnavailable={isDateUnavailable}
defaultValue={new CalendarDate(2026, 2, 1)}
/>Min/Max Date Constraints
Restrict the selectable date range by providing minValue and maxValue props. Dates outside the range are disabled and months beyond the range cannot be navigated to.
Only dates in 2026 are selectable
const minDate = new CalendarDate(2026, 1, 1);
const maxDate = new CalendarDate(2026, 12, 31);
<Calendar
aria-label="Date within 2026"
minValue={minDate}
maxValue={maxDate}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | DateValue | null | — | The currently selected date (controlled) |
onChange | (date: DateValue) => void | — | Handler called when the selected date changes |
defaultValue | DateValue | — | The default selected date (uncontrolled) |
minValue | DateValue | — | The minimum selectable date |
maxValue | DateValue | — | The maximum selectable date |
isDisabled | boolean | false | Whether the calendar is disabled |
isDateUnavailable | (date: DateValue) => boolean | — | Callback that returns whether a specific date is unavailable |
aria-label | string | — | Accessible label for the calendar |
size | 'sm' | 'md' | 'lg' | 'md' | The visual size of the calendar |
locale | string | — | The locale to use for formatting month and day names |
Accessibility
- Uses a
gridrole with propergridcellroles for each day - Full keyboard navigation: Arrow keys move between days, Page Up/Down change months
- Today's date is visually indicated and announced to screen readers
- Disabled and unavailable dates are announced as such via
aria-disabled - Previous/next month buttons include descriptive
aria-labelattributes - Selected date is communicated via
aria-selected