Skip to content
Aihio v2.5.0
Search
GitHub
Search Describe what you are building, or name a component, intent, or token. Components and patterns are ranked the way the MCP server's find tool ranks them for an agent.

<aihio-date-picker> v1.0.0 Markdown for agents

Date Picker

A form field for one date (a due date, a birth date, a travel date), typed in the page's language or picked from a month calendar that a button opens under the field. The date submits as YYYY-MM-DD, as a native date input's does. For a date chosen on the page itself, such as a booking day, use aihio-calendar.

Intents form-field date-entry text-entry

Variants

Every value of the attributes that change how it looks. The values come from the schema.

size

Field size, matching aihio-input.

size="sm"
size="md"
size="lg"

Examples

Each one rendered live, over the markup that produces it.

In a field

The placeholder shows the date format in the page's language, and the date submits as YYYY-MM-DD.

Invoices are sent on this day.
<aihio-field>
  <label slot="label">Due date</label>
  <aihio-date-picker name="due-date" value="2026-10-30"></aihio-date-picker>
  <span slot="description">Invoices are sent on this day.</span>
</aihio-field>

A range of dates

Days outside min and max are struck through in the calendar, and the months and years it offers stop at them.

<aihio-field>
  <label slot="label">Appointment</label>
  <aihio-date-picker name="appointment" min="2026-10-12" max="2026-12-18" required></aihio-date-picker>
</aihio-field>

A birth date

Most people type it. autocomplete="bday" lets the browser fill it in, and the year select reaches back a century.

<aihio-field>
  <label slot="label">Date of birth</label>
  <aihio-date-picker name="birth-date" autocomplete="bday" max="2026-10-09"></aihio-date-picker>
</aihio-field>

In another language

lang sets how dates are written and read, the names of months and weekdays, and the first day of the week. The text attributes put the rest in the same language.

<aihio-field lang="fi">
  <label slot="label">Eräpäivä</label>
  <aihio-date-picker name="due-date" choose-text="Valitse päivä" previous-month-text="Edellinen kuukausi" next-month-text="Seuraava kuukausi" invalid-text="Kirjoita päivä muodossa {format}." min-text="Valitse {min} tai myöhemmin." max-text="Valitse {max} tai aiemmin." unavailable-text="{date} ei ole valittavissa."></aihio-date-picker>
</aihio-field>

Mistakes

Each one beside its fix, with what aihio lint says about it. The prompt fragment gives agents the same pairs, and the build fails if the linter stops catching one or a fix stops passing.

Placeholder is not a label, and this one hides the date format the field would show there.

Put the picker in aihio-field with a label.

Don't

<aihio-date-picker placeholder="Due date"></aihio-date-picker>

aihio lint reports

  • date-picker-label error Label it with aria-labelledby pointing at visible text, or aria-label. Placeholder is not a label, and a wrapping <label> would fold the open calendar's text into the field's name.

Do

<aihio-field>
  <label slot="label">Due date</label>
  <aihio-date-picker name="due-date"></aihio-date-picker>
</aihio-field>

A wrapping <label> takes its name from all of its text, so the open calendar's month, weekdays, and days become part of the field's name.

Use aihio-field instead.

Don't

<label>
  Due date
  <aihio-date-picker name="due-date"></aihio-date-picker>
</label>

aihio lint reports

  • date-picker-label error Label it with aria-labelledby pointing at visible text, or aria-label. Placeholder is not a label, and a wrapping <label> would fold the open calendar's text into the field's name.

Do

<aihio-field>
  <label slot="label">Due date</label>
  <aihio-date-picker name="due-date"></aihio-date-picker>
</aihio-field>

Dates in attributes are YYYY-MM-DD whatever the page's language: 10/09/2026 is 9 October in Finland and 10 September in the US.

The field shows the date the page's way.

Don't

<aihio-date-picker aria-label="Due date" value="10/09/2026"></aihio-date-picker>

aihio lint reports

  • date-value error value="10/09/2026" is not a date the component reads. Write it YYYY-MM-DD (2026-10-09), whatever the page's language; the component shows it the page's way.

Do

<aihio-date-picker aria-label="Due date" value="2026-10-09"></aihio-date-picker>

min is after max, so there is no date to choose.

Don't

<aihio-date-picker aria-label="Check-in" min="2026-12-31" max="2026-01-01"></aihio-date-picker>

aihio lint reports

  • date-range error min="2026-12-31" is after max="2026-01-01", so no date can be chosen.

Do

<aihio-date-picker aria-label="Check-in" min="2026-01-01" max="2026-12-31"></aihio-date-picker>

Nothing reads format or locale.

The field writes and reads dates the way the page's language does: set lang, on the page or the picker.

Don't

<aihio-date-picker aria-label="Start date" format="dd.MM.yyyy" locale="fi"></aihio-date-picker>

aihio lint reports

  • unknown-attribute error <aihio-date-picker> has no attribute "format". Use form instead. It accepts: value, name, form, min, max, placeholder, disabled, readonly, required, error, size, open, autocomplete, first-day-of-week, choose-text, previous-month-text, next-month-text, invalid-text, min-text, max-text, unavailable-text. Suggests form
  • unknown-attribute error <aihio-date-picker> has no attribute "locale". It accepts: value, name, form, min, max, placeholder, disabled, readonly, required, error, size, open, autocomplete, first-day-of-week, choose-text, previous-month-text, next-month-text, invalid-text, min-text, max-text, unavailable-text.

Do

<aihio-date-picker aria-label="Alkupäivä" lang="fi"></aihio-date-picker>

API

Every attribute, property, method, and event the schema declares for aihio-date-picker.

Attributes

value
string
The initial date as YYYY-MM-DD, whatever the page's language, and the date a form reset returns to. The value property carries the live date.
name
string
Form field name. The date submits under it as YYYY-MM-DD, not as the text on show. Without it the field submits nothing.
form
string
Id of an external form that owns the field.
min
string
The earliest date that can be chosen, as YYYY-MM-DD. Earlier days are struck through in the calendar, and a typed earlier date makes the field invalid.
max
string
The latest date that can be chosen, as YYYY-MM-DD.
placeholder
string
Placeholder text. Defaults to the date format in the page's language, such as mm/dd/yyyy or pp.kk.vvvv. It is not a label.
disabled
boolean default false
Disables the field and its calendar. A disabled field submits nothing.
readonly
boolean default false
Shows the date without letting it change. The date still submits.
required
boolean default false
Requires a date for native constraint validation.
error
boolean default false
Shows error styling and sets aria-invalid. aihio-field sets this from its error slot.
size
one of smmdlg default md
Field size, matching aihio-input.
open
boolean default false
Reflects whether the calendar is showing. Set or remove it to open or close the calendar.
autocomplete
string default off
Forwarded to the text field. Off by default, so the browser's list of past entries does not cover the calendar; bday lets the browser fill in a birth date.
first-day-of-week
one of montuewedthufrisatsun
The day the calendar's 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.
choose-text
string default Choose date
The calendar button's name and the calendar's, each followed by the field's label. For localisation.
previous-month-text
string default Previous month
The previous month button's name. For localisation.
next-month-text
string default Next month
The next month button's name. For localisation.
invalid-text
string default Enter a date as {format}.
Validation message for text that is not a date, with {format} for the date format (dd.mm.yyyy). For localisation.
min-text
string default Choose {min} or later.
Validation message for a date before min, with {min} for it. For localisation.
max-text
string default Choose {max} or earlier.
Validation message for a date after max, with {max} for it. For localisation.
unavailable-text
string default {date} is not available.
Validation message for a date isDateDisabled rules out, with {date} for it. For localisation.

Properties

value
string
Get or set the date as YYYY-MM-DD, or "" for none. Anything that is not a date clears it, as with a native date input. Setting it 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 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 the calendar shows, as YYYY-MM-DD. A date it returns true for is struck through and cannot be chosen, and typing it makes the field invalid. Set it again when the dates it rules out change. Read a weekday as new Date(date).getUTCDay().
control
HTMLInputElement | null read-only
The native text field the date is typed into
form
HTMLFormElement | null read-only
The owning form, or null outside one
validity
ValidityState | null read-only
Native constraint validation state, including the field's own checks: text that is not a date, a date outside min and max, and one isDateDisabled rules out
validationMessage
string read-only
Native validation message
willValidate
boolean read-only
Whether the field participates in constraint validation

Methods

open(): void
Opens the calendar and moves focus into it, on the chosen date or today. Focus goes back to whatever had it when the calendar closes.
close(): void
Closes the calendar.
toggle(): void
Opens or closes the calendar.
focus(options?: FocusOptions): void
Moves focus to the text field.
checkValidity(): boolean
Runs native constraint validation and returns whether the field is valid.
reportValidity(): boolean
Runs native constraint validation and shows the browser message if invalid.
setCustomValidity(message: string): void
Sets a custom validation message, which wins over the field's own. An empty message hands validation back to the field.

Events

aihio-change
detail { value: string }
Fired when the person commits a different date: picks one, or leaves the field (or presses Enter) after typing. Text that is not a date commits as "". Also fired when a form reset changes the date, and not for programmatic changes. The native input and change events come from the text field and carry its text.
aihio-month
detail { month: string, start: string, end: string }
Fired when the calendar opens, and whenever it 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.
aihio-open
Fired after the calendar opens.
aihio-close
detail { reason: string }
Fired after the calendar closes, with why: select, escape, outside, blur, toggle, reset, or api.

Composition

Allowed children
none

Accessibility

What you have to provide, and what the component already does. The obligations with a rule are checked by aihio lint and by the dev build's console warnings.

Your obligations

  • error When the date picker is not inside an aihio-field

    Label it with aria-labelledby pointing at visible text, or aria-label. Placeholder is not a label, and a wrapping <label> would fold the open calendar's text into the field's name.

    Checked as date-picker-label

  • warn When the date picker is inside a <form> and its date should be submitted

    Set name. A date picker without a name is omitted from FormData.

    Checked as date-picker-form-name

Handled for you

  • A real text <input> to type into, and a real <button> with aria-haspopup="dialog", aria-expanded, and aria-controls that opens the calendar. The button is named "Choose date" followed by the field's label, and described by the chosen date in words
  • Typed dates are read in the page's language (the closest lang): 9.10.2026 in Finland, 10/9/2026 in the US, and 2026-10-09 anywhere, with any separator, a month name ("9 Oct 2026", "9. lokakuuta"), two-digit years, no year (this year), the language's own digits, or no separators at all (09102026). Where lang names no region (en), the browser's region for that language fills it in, so a browser set to en-GB reads 9/10/2026 as 9 October; a region lang names is kept. The placeholder is the format, written the language's way (mm/dd/yyyy, pp.kk.vvvv, tt.mm.jjjj)
  • Text that is not a date is kept to be corrected, not thrown away, and the field reports it through native validation; so does a date outside min and max or one isDateDisabled rules out, with a localisable message
  • The calendar is a dialog named "Choose date" and the field's label. Focus moves into its grid on the chosen date, or today, and goes back to the button (or the field, when Alt+ArrowDown opened it) when a date is picked or Escape closes it. Focus leaving the field closes it
  • The grid is a <table role="grid"> with one tab stop. Arrow keys move a day or a week (mirrored right to left), Home and End go to the ends of the week, Page Up and Page Down move a month and, with Shift, a year; Enter or Space picks the day
  • Each day is named by its full date ("Friday, October 9, 2026") and carries aria-selected for the chosen date, aria-current="date" for today, and aria-disabled for a day outside min and max or ruled out by isDateDisabled, which is struck through, not only greyed
  • Previous and next month buttons and native month and year selects head the grid; a step is announced in a polite status region. Weeks start on the first day of the language's region, the Gregorian calendar is used whatever the language's own, and month and weekday names come from Intl
  • Escape on a closed field is left alone, so a surrounding dialog still closes. Keys pressed while an IME is composing are left to the IME
  • The date submits as YYYY-MM-DD through a hidden input under name; required, form reset, <fieldset disabled>, and the form attribute behave natively
  • The calendar renders in the top layer, flips above the field when there is more room there, and stays inside the visual viewport; on touch screens its days are larger
  • Forced colours restate the chosen, today, and unavailable days with system colours; reduced motion removes the open animation