# <aihio-calendar>

A month calendar on the page for choosing one date where the choice is the point of the page: a booking day, a delivery day, an appointment. The chosen date submits as YYYY-MM-DD under name. For a date entered in a form field, typed as often as picked, use aihio-date-picker, which opens the same calendar under a field.

Intents: `form-field`, `date-entry`, `selection`.

## Attributes

- `value` (string): The initially chosen date as YYYY-MM-DD, whatever the page's language, and the date a form reset returns to. The calendar opens on its month. The value property carries the live choice.
- `name` (string): Form field name. The chosen date submits under it as YYYY-MM-DD. Without it the calendar submits nothing.
- `form` (string): Id of an external form that owns the calendar.
- `min` (string): The earliest date that can be chosen, as YYYY-MM-DD. Earlier days are struck through, and the months and years offered stop at it.
- `max` (string): The latest date that can be chosen, as YYYY-MM-DD.
- `disabled` (boolean): Shows the calendar dimmed, out of the tab order, and submits nothing. Default: `false`.
- `readonly` (boolean): Shows the chosen date and lets the months be browsed, without letting the date change. The date still submits. Default: `false`.
- `first-day-of-week` (`mon` | `tue` | `wed` | `thu` | `fri` | `sat` | `sun`): The day the weeks start on. Defaults to the page's language and region: Monday in Finland, Sunday in the US, Saturday in Egypt. Where lang names no region (en), the browser's region for that language fills it in.
- `previous-month-text` (string): The previous month button's name. For localisation. Default: `Previous month`.
- `next-month-text` (string): The next month button's name. For localisation. Default: `Next month`.

## Properties

- `value` (`string`): Get or set the chosen date as YYYY-MM-DD, or "" for none. Anything that is not a date clears it. Setting it shows its month and does not fire aihio-change.
- `defaultValue` (`string`): Get or set the reset value reflected by the value attribute.
- `valueAsDate` (`Date | null`): Get or set the chosen date as the UTC midnight it starts at, as a native date input's valueAsDate is.
- `isDateDisabled` (`((date: string) => boolean) | null`): Called with each date shown, as YYYY-MM-DD. A date it returns true for is struck through and cannot be chosen. Set it again when the dates it rules out change. Read a weekday as new Date(date).getUTCDay().
- `month` (`string`): Get or set the month shown, as YYYY-MM. Setting it shows that month without choosing a date, and fires aihio-month.
- `form` (`HTMLFormElement | null`, read-only): The owning form, or null outside one.

## Methods

- `focus()`: Moves focus to the grid's tab stop: the chosen date, or else today.

## Events

- `aihio-change` (detail: value: string): Fired when the person chooses a different date, or when a form reset changes it. Not fired for programmatic changes.
- `aihio-month` (detail: month: string, start: string, end: string): Fired when the calendar shows another month: the month as YYYY-MM, and its first and last day. Fetch the dates to rule out for that month here, then set isDateDisabled again. The month property has the one shown first.

## Accessibility obligations

- (error, calendar-label) When the calendar is not inside an aihio-field: Name it after what the date is for, with aria-labelledby pointing at visible text or aria-label. Without a name, its group says nothing about the date it holds.
- (warn, calendar-form-name) When the calendar is inside a <form> and its date should be submitted: Set name. A calendar without a name is omitted from FormData.

## Examples

### A booking day

In a field, named by its label. Days outside min and max are struck through.

```html
<form>
  <aihio-field>
    <span slot="label">Delivery day</span>
    <aihio-calendar name="delivery-day" min="2026-10-12" max="2026-11-27"></aihio-calendar>
    <span slot="description">Deliveries run until 27 November.</span>
  </aihio-field>
</form>
```

### A chosen date, read only

readonly keeps the months browsable and the date fixed.

```html
<aihio-calendar aria-label="Contract start" value="2026-11-02" readonly></aihio-calendar>
```

### Weeks from Monday

first-day-of-week overrides the language's own first day.

```html
<aihio-calendar aria-label="Week starting" first-day-of-week="mon" lang="en-US"></aihio-calendar>
```

## Mistakes

### The heading is not associated with the calendar, so its group is unnamed. Point aria-labelledby at the heading, or put the calendar in aihio-field.

Don't (aihio lint: calendar-label):

```html
<h2>Choose a day</h2>
<aihio-calendar name="delivery-day"></aihio-calendar>
```

Do:

```html
<h2 id="delivery-day-heading">Choose a day</h2>
<aihio-calendar name="delivery-day" aria-labelledby="delivery-day-heading"></aihio-calendar>
```

### Dates in attributes are YYYY-MM-DD whatever the page's language. The calendar shows the date the page's way.

Don't (aihio lint: date-value):

```html
<aihio-calendar aria-label="Delivery day" value="9.10.2026"></aihio-calendar>
```

Do:

```html
<aihio-calendar aria-label="Delivery day" value="2026-10-09"></aihio-calendar>
```

### The earliest date is min. Nothing reads min-date, so every day stays open.

Don't (aihio lint: unknown-attribute):

```html
<aihio-calendar aria-label="Delivery day" min-date="2026-10-12"></aihio-calendar>
```

Do:

```html
<aihio-calendar aria-label="Delivery day" min="2026-10-12"></aihio-calendar>
```
