Inputs
Date Field
A date input: a field that shows the date in the page's language and opens a Calendar to change it — anchored under the field on a desktop, in a bottom sheet on a phone, where a popover would be a thumb's width from the edge.
import { DateField } from 'omaris' Examples
Basic
A field that opens a calendar — under the field on a desktop, in a bottom sheet on a phone. The value is a Date at local midnight, or null.
<script lang="ts"> import { DateField } from 'omaris'; let due = $state<Date | null>(null);</script><DateField class="w-64 max-w-full" label="Due date" bind:value={due} /> States
The same frame, sizes and states as a text field, so a form that mixes the two validates as one thing. min, max and isDateDisabled grey days out in the calendar rather than rejecting them after the fact.
Weekdays, next 30 days
Pick a start date.
<script lang="ts"> import { DateField, addDays, startOfDay } from 'omaris'; const today = startOfDay(new Date()); const weekend = (date: Date) => date.getDay() === 0 || date.getDay() === 6;</script><DateField class="w-56 max-w-full" variant="filled" label="Delivery" min={today} max={addDays(today, 30)} isDateDisabled={weekend} supportingText="Weekdays, next 30 days"/><DateField class="w-56 max-w-full" label="Start date" required invalid supportingText="Pick a start date."/><DateField class="w-56 max-w-full" label="Signed" disabled value={today} /> Format and locale
format is Intl.DateTimeFormat options for the text in the field, and locale decides the names and the first weekday. Western digits either way.
<script lang="ts"> import { DateField } from 'omaris'; let meeting = $state<Date | null>(new Date(2026, 2, 12)); let arabic = $state<Date | null>(new Date(2026, 2, 12));</script><DateField class="w-64 max-w-full" label="Meeting" format={{ weekday: 'long', day: 'numeric', month: 'long' }} bind:value={meeting}/><div class="w-64 max-w-full" dir="rtl" lang="ar-IQ"> <DateField label="الموعد" locale="ar-IQ" placeholder="اختر تاريخًا" format={{ dateStyle: 'long' }} bind:value={arabic} /></div> Overridden
classes reaches the frame's parts and calendarClasses the calendar's. A name posts the date as YYYY-MM-DD, so the field works in a plain form.
<script lang="ts"> import { DateField } from 'omaris';</script><form class="w-48 max-w-full"> <DateField label="Invoice date" name="invoice-date" size="sm" format={{ year: 'numeric', month: '2-digit', day: '2-digit' }} value={new Date(2026, 2, 12)} classes={{ field: 'rounded-full', value: 'font-mono', icon: 'text-primary' }} calendarClasses={{ face: 'rounded-shape-sm' }} /></form> When to use it
Use it for
- A date in a form: a due date, a start date, a delivery day. It reads as text until pressed, then opens a calendar under the field — or, on a phone, in a bottom sheet where a thumb can reach it.
- A date that should read in the page's language, with Western digits, without anyone writing a formatter:
formattakesIntloptions. - A form posted the plain way: with
name, the date goes asYYYY-MM-DD.
Not for
- A span of dates → Date Range Field.
- A calendar that stays open on the page → Calendar.
- A birthday or any date years away →
DatePickerin Picker; three wheels beat forty pages of months. - A time, or a date with a time →
TimePickerorDateTimePickerin Picker. - A date people know by heart and type faster than they pick — an ID's expiry on a data-entry screen → an Input with
type="date".
Do
- Give it a
label, and aplaceholderthat says what is missing when it is empty — "Pick a delivery day" rather than a format mask. - Put the valid window in
min,maxandisDateDisabled, so the calendar greys out what cannot be picked instead of the form rejecting it. - Use the same
variantandsizeas the text fields around it; they are the same frame. - Turn
clearableoff when the date is required — an × that empties a field that cannot be empty is a trap.
Don't
- Pass it a string. The value is a
Dateat local midnight, ornull. - Use it as a filter chip in a toolbar. A range filter is Date Range Field; a single-day filter still wants a label someone can read.
- Set
mobileQuerywider than a phone. The sheet is for a thumb; a tablet is better served by the popover.
Quick reference
variant outline(default)filledghost
size smdefault(default)lg
API
DateField
A date input: a field that shows the date in the page's language and opens a Calendar to change it — anchored under the field on a desktop, in a bottom sheet on a phone, where a popover would be a thumb's width from the edge.
It looks and behaves like Input — the same variants, sizes, label, supporting text and invalid state — so a form reads as one thing. The value is a Date at local midnight, or null; with a name it is also posted as YYYY-MM-DD.
Keyboard: Enter, Space or ↓ opens the calendar with focus on the date, the arrows walk it, Enter picks and closes, Escape closes without picking. Backspace on the field clears it.
import { DateField } from 'omaris' <DateField label="Due" bind:value={due} min={new Date()} /> Parts
Every element this renders is reachable from outside. Pass Tailwind for one part as classes={{ part: '…' }}; class covers the root and is merged last, so it always wins.
root- Wrapper: label, field, supporting text.
field- The frame: border, background, height.
control- The button that opens the calendar: the whole frame, minus the clear button.
value- The formatted date, or the placeholder.
placeholder- Added to
valuewhile there is no date. icon- The calendar glyph at the end.
action- The clear button.
label- The label above the frame.
support- The helper or error line under the frame.
panel- The popover the calendar opens in, on a desktop.
sheet- The bottom sheet it opens in, on a phone.
Props
value bindableDefaults to null
Date | null The date, at local midnight, or null. Bindable.
variant Defaults to 'outline'
DateFieldVariant outline, filled or ghost — the same frames as Input.
outline- The default: a hairline frame on the page background.
filled- Softer — a tinted well with no border until you touch it.
ghost- No frame at all, for fields nested in another surface.
size Defaults to 'default'
DateFieldSize sm, default or lg — the same heights as Input.
smdefaultlg
label string Label above the field.
required Defaults to false
boolean Marks the label required.
supportingText string Helper line under the field. Turns into the error text when invalid.
invalid Defaults to false
boolean Marks the field invalid and wires up aria-invalid.
placeholder Defaults to 'Select a date'
string Shown, greyed, while there is no date.
format Defaults to { dateStyle: 'medium' }
Intl.DateTimeFormatOptions How the date reads in the field. Intl.DateTimeFormat options, with Western digits added — { dateStyle: 'long' }, or { weekday: 'short', day: 'numeric', month: 'short' }.
min Date Earliest selectable day.
max Date Latest selectable day.
isDateDisabled (date: Date) => boolean Days that cannot be picked.
locale string BCP-47 tag for the field and the calendar. Defaults to <html lang>.
weekStartsOn Weekday 0 is Sunday. Defaults to the locale's first day.
clearable Defaults to true
boolean Show an × that empties the field once it has a date.
open bindableDefaults to false
boolean Whether the calendar is open. Bindable.
mobileQuery Defaults to '(max-width: 639px)'
string What counts as a phone, where the calendar opens in a bottom sheet.
onchange (value: Date | null) => void Fires after a pick or a clear.
class string Merged onto the root wrapper.
classes DateFieldClasses Per-part Tailwind overrides. class still covers the root.
calendarClasses CalendarClasses Per-part overrides for the calendar inside the popup.
ref bindableDefaults to null
HTMLButtonElement | null The trigger button.