Calendar
A date field with a month grid, a typed path, and a value that is a Date.
Calendar is a date field: an input that accepts a typed date and a panel with the month grid
beside it. It collects a day, a time or both, mode decides which, and in the default date
mode one press on a day is the whole interaction, because the panel closes with the choice. It
is a field first: label, description, message and status behave as they do everywhere in the
field family.
Usage
import { Calendar } from "@asheeui/web";
<Calendar label="Delivery date" selected={date} onChange={setDate} />
The value is a Date, and null means nothing is chosen. selected reads it, onChange
reports it, and the field writes it into the input as dd/mm/yyyy, one format whatever the
reader's locale, so a value that is typed, re-read and compared is always written the same way.
Modes
mode states what the field collects. date shows the month grid and closes the panel when a
day is chosen; datetime shows the grid and the time spinners together and keeps the panel open,
because a reader choosing both has not finished after the day; time shows only the spinners and
applies the time to the day the field already holds.
The time is reported as it changes, spinner by spinner, and Done closes the panel in the two
modes that keep it open. Typing is a real second path in every mode: the digits are read in the
order the field writes them, day, month, year, then hours, minutes, seconds, and the field
reformats as you go. A typed time keeps the day the field already holds, so adding an hour does
not move the day.
Constraints
disableFuture refuses any day after today, and stops the forward control from moving past the
month that holds today, a month whose every day would be refused is not worth opening.
isClearable adds a clear control to the field and a Clear to the panel once something is
chosen.
Validation is the family's: status and message on the field, announced the same way every
other field announces them. Typed input is forgiving rather than strict, a part out of range is
clamped to the month's own answer, so 31 in a thirty-day month gives you the 30th, which is a
value you can correct instead of a field that appears to ignore you.
Props
mode is registered as date, size as md and variant as bordered, because the
component registers the field family's web defaults; radius follows the application's
defaultRadius and the accent follows its defaultColor. isClearable and disableFuture are
both off, and picker carries the panel's own settings: portal (true) and portalTarget
(rendered into document.body by default) decide where it lives, and lockScroll (true)
whether the page behind it moves. Pass placeholder to replace the wording the field supplies
for the mode.
Accessibility
- The input announces a dialog: it carries
aria-haspopup="dialog"andaria-expanded, so the panel is not a surprise and its closing is not either. - The month is a
tablewithrole="grid", named by its month and year. Each day is agridcellthat states whether it is selected, and today is marked witharia-current="date". - The grid is one tab stop, not thirty-one: when it opens, only one day is in the tab order, the chosen day, or today when the field is empty, and the arrow keys move it by a day and by a week, Home and End go to the first and last day of the focused week, and PageUp and PageDown move thirty days either way. Focus follows the navigated day across a month boundary.
- The month controls are labelled (
Previous month,Next month) and the next one is disabled rather than hidden whendisableFutureforbids it, the field's clear control is labelledClear selection, and opening the panel does not move focus, it stays in the input, so typing keeps working while the grid is open and an outside press or Escape closes it.