Date Field
The default date type exports only YYYY-MM-DD. Explicit time, local date-time, instant and zoned types keep their own value semantics; display formatting never changes the binding type. Editable dates and times with canonical string values, localized numeric typing, Temporal validation, inclusive bounds and declarative date availability. Native inputs remain usable before upgrade; precision and space-separated local values use text fallbacks to retain their serialization. Enhanced input preserves incomplete drafts and submits canonical values. A set-value CustomEvent with canonical detail.value commits an explicit choice and replaces the draft, including when its accepted value is unchanged.
Type a date
ISO paste and the declared locale's date order are accepted. Focus uses numeric entry; the unfocused field can use a longer Intl display format.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-date-field/ui-date-field.html"
>
<ui-date-field
label="Due date"
name="due"
value="2026-10-30"
locale="en-US"
display-options="{"dateStyle":"long"}"
></ui-date-field><script setup>
import { UiDateField } from "@threadlabs/looma";
</script>
<template>
<UiDateField
label="Due date"
name="due"
value="2026-10-30"
locale="en-US"
:display-options="{ dateStyle: 'long' }"
/>
</template>import { UiDateField } from "@threadlabs/looma";
export default function Example() {
return <UiDateField
label="Due date"
name="due"
value="2026-10-30"
locale="en-US"
displayOptions={{"dateStyle":"long"}}
/>;
}/** @jsxImportSource preact */
import { UiDateField } from "@threadlabs/looma";
export default function Example() {
return <UiDateField
label="Due date"
name="due"
value="2026-10-30"
locale="en-US"
displayOptions={{"dateStyle":"long"}}
/>;
}<script>
import { UiDateField } from "@threadlabs/looma";
</script>
<UiDateField
label="Due date"
name="due"
value="2026-10-30"
locale="en-US"
displayOptions={{"dateStyle":"long"}}
/>import { Component } from "@angular/core";
import { UiDateField } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiDateField],
template: `
<span
ui-date-field
[label]="'Due date'"
[name]="'due'"
[value]="'2026-10-30'"
[locale]="'en-US'"
[displayOptions]="{ dateStyle: 'long' }"
></span>
`,
})
export default class Example {}Available dates
Bounds and allowed intervals intersect; disabled dates and weekdays take precedence. Unavailable typed values remain visible with native validation.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-date-field/ui-date-field.html"
>
<ui-date-field
label="Appointment date"
min="2026-10-01"
max="2026-12-31"
disabled-dates="["2026-11-11"]"
disabled-weekdays="[6,7]"
></ui-date-field><script setup>
import { UiDateField } from "@threadlabs/looma";
</script>
<template>
<UiDateField
label="Appointment date"
min="2026-10-01"
max="2026-12-31"
:disabled-dates="['2026-11-11']"
:disabled-weekdays="[6, 7]"
/>
</template>import { UiDateField } from "@threadlabs/looma";
export default function Example() {
return <UiDateField
label="Appointment date"
min="2026-10-01"
max="2026-12-31"
disabledDates={["2026-11-11"]}
disabledWeekdays={[6,7]}
/>;
}/** @jsxImportSource preact */
import { UiDateField } from "@threadlabs/looma";
export default function Example() {
return <UiDateField
label="Appointment date"
min="2026-10-01"
max="2026-12-31"
disabledDates={["2026-11-11"]}
disabledWeekdays={[6,7]}
/>;
}<script>
import { UiDateField } from "@threadlabs/looma";
</script>
<UiDateField
label="Appointment date"
min="2026-10-01"
max="2026-12-31"
disabledDates={["2026-11-11"]}
disabledWeekdays={[6,7]}
/>import { Component } from "@angular/core";
import { UiDateField } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiDateField],
template: `
<span
ui-date-field
[label]="'Appointment date'"
[min]="'2026-10-01'"
[max]="'2026-12-31'"
[disabledDates]="['2026-11-11']"
[disabledWeekdays]="[6, 7]"
></span>
`,
})
export default class Example {}Wall-clock and exact time
A time of day has no date or zone. An exact instant uses an explicit editing zone; localized formatting never changes its identity.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-date-field/ui-date-field.html"
>
<ui-stack
gap="s"
>
<ui-date-field
type="time"
label="Opening time"
value="09:30"
min="08:00"
max="18:00"
locale="en-US"
></ui-date-field>
<ui-date-field
type="instant"
label="Meeting time"
value="2026-10-30T18:30:00Z"
time-zone="America/New_York"
locale="en-US"
></ui-date-field>
</ui-stack><script setup>
import { UiDateField, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
gap="s"
>
<UiDateField
type="time"
label="Opening time"
value="09:30"
min="08:00"
max="18:00"
locale="en-US"
/>
<UiDateField
type="instant"
label="Meeting time"
value="2026-10-30T18:30:00Z"
time-zone="America/New_York"
locale="en-US"
/>
</UiStack>
</template>import { UiDateField, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
>
<UiDateField
type="time"
label="Opening time"
value="09:30"
min="08:00"
max="18:00"
locale="en-US"
/>
<UiDateField
type="instant"
label="Meeting time"
value="2026-10-30T18:30:00Z"
timeZone="America/New_York"
locale="en-US"
/>
</UiStack>;
}/** @jsxImportSource preact */
import { UiDateField, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
>
<UiDateField
type="time"
label="Opening time"
value="09:30"
min="08:00"
max="18:00"
locale="en-US"
/>
<UiDateField
type="instant"
label="Meeting time"
value="2026-10-30T18:30:00Z"
timeZone="America/New_York"
locale="en-US"
/>
</UiStack>;
}<script>
import { UiDateField, UiStack } from "@threadlabs/looma";
</script>
<UiStack
gap="s"
>
<UiDateField
type="time"
label="Opening time"
value="09:30"
min="08:00"
max="18:00"
locale="en-US"
/>
<UiDateField
type="instant"
label="Meeting time"
value="2026-10-30T18:30:00Z"
timeZone="America/New_York"
locale="en-US"
/>
</UiStack>import { Component } from "@angular/core";
import { UiDateField, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiDateField],
template: `
<div
ui-stack
[gap]="'s'"
>
<span
ui-date-field
[type]="'time'"
[label]="'Opening time'"
[value]="'09:30'"
[min]="'08:00'"
[max]="'18:00'"
[locale]="'en-US'"
></span>
<span
ui-date-field
[type]="'instant'"
[label]="'Meeting time'"
[value]="'2026-10-30T18:30:00Z'"
[timeZone]="'America/New_York'"
[locale]="'en-US'"
></span>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: span
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
allowed-dates | Allowed ISO dates, unioned with allowedRanges. Omission imposes no allow restriction; an explicitly empty allow set permits nothing. | allowedDates | list(string) | — | — |
allowed-ranges | Allowed inclusive ISO-date intervals, unioned with allowedDates. | allowedRanges | list(object)
| — | — |
disabled | Prevents editing and omits the value from submission. | disabled | boolean | false | — |
disabled-dates | Unavailable ISO dates, applied in the editing zone for exact values. | disabledDates | list(string) | [] | — |
disabled-ranges | Unavailable inclusive ISO-date intervals. | disabledRanges | list(object)
| [] | — |
disabled-weekdays | Unavailable ISO weekdays, from 1 (Monday) to 7 (Sunday). | disabledWeekdays | list(integer) | [] | — |
disambiguation | How zoned edits resolve a skipped or repeated wall-clock time. Reject leaves the draft visible with a validation error. | disambiguation | keyword | reject | reject, earlier, later, compatible |
display-options | Intl display options while unfocused. Focusing uses the numeric editing grammar; formatting does not change the binding. Calendar identity and editing timezone stay with the field. | displayOptions | object
| — | — |
form | Optional ID of a form outside this component’s ancestor tree. | form | string | | — |
granularity | Smallest displayed time unit. Existing nonzero seconds and fractions remain editable without precision loss. | granularity | keyword | minute | minute, second |
hour-cycle | Intl hour cycle. Omit to follow locale conventions. | hourCycle | keyword | — | h11, h12, h23, h24 |
input-id | ID of the active native input for an authored label's for attribute, preserved across upgrade. | inputId | string | | — |
invalid | External invalid state, independent of parsing and availability. | invalid | boolean | false | — |
label | Optional accessible name. Prefer an authored visible label associated with input-id; a supplied label overrides that name. | label | string | | — |
locale | Explicit Intl locale for numeric editing order, digits and display. ISO input is always accepted. | locale | string | en-US | — |
max | Inclusive maximum in the bound value's format. | max | string | | — |
min | Inclusive minimum in the bound value's format. | min | string | | — |
name | Native form field name. The enhanced field submits its canonical value. | name | string | | — |
placeholder | Optional editing hint. A placeholder never replaces the label. | placeholder | string | | — |
readonly | Retains selection and submission while preventing edits. | readonly | boolean | false | — |
required | Requires a complete value. | required | boolean | false | — |
size | Input's shared size scale. | size | keyword | md | sm, md, lg |
time-zone | Display/editing zone for instant values, required for localized instant editing. Zoned values otherwise use their saved zone; local typing through an override preserves that saved zone. Required for a new zoned value. Date, time and local date-time bindings remain without a zone. | timeZone | string | | — |
type | The value's meaning and export format. Date is the default and exports only YYYY-MM-DD, without a time or timezone. Time and local date-time remain wall-clock values; instant uses a UTC timestamp; zoned retains a named zone. Display options alone never change this type. | type | keyword | date | date, time, datetime-local, instant, zoned |
value | Initial canonical value, and a replacement when changed externally. Valid edits update live state and emit input/change; a form reset returns to the last external value. | value | string | | — |
value-format | Local date-time bindings use T by default; space emits YYYY-MM-DD HH:ss. Other types retain their ISO form. | valueFormat | keyword | iso | iso, space |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
allowedDates | readonly (string)[] | — | — |
allowedRanges | readonly ({ readonly start: string; readonly end: string })[]
| — | — |
disabled | boolean | false | — |
disabledDates | readonly (string)[] | [] | — |
disabledRanges | readonly ({ readonly start: string; readonly end: string })[]
| [] | — |
disabledWeekdays | readonly (number)[] | [] | — |
disambiguation | "reject" | "earlier" | "later" | "compatible" | reject | reject, earlier, later, compatible |
displayOptions | { readonly dateStyle?: "full" | "long" | "medium" | "short" | null; readonly timeStyle?: "full" | "long" | "medium" | "short" | null; readonly weekday?: "long" | "short" | "narrow" | null; readonly era?: "long" | "short" | "narrow" | null; readonly year?: "numeric" | "2-digit" | null; readonly month?: "numeric" | "2-digit" | "long" | "short" | "narrow" | null; readonly day?: "numeric" | "2-digit" | null; readonly hour?: "numeric" | "2-digit" | null; readonly minute?: "numeric" | "2-digit" | null; readonly second?: "numeric" | "2-digit" | null; readonly timeZoneName?: "long" | "short" | "shortOffset" | "longOffset" | "shortGeneric" | "longGeneric" | null; readonly dayPeriod?: "long" | "short" | "narrow" | null; readonly hourCycle?: "h11" | "h12" | "h23" | "h24" | null; readonly localeMatcher?: "lookup" | "best fit" | null; readonly formatMatcher?: "basic" | "best fit" | null; readonly fractionalSecondDigits?: number | null; readonly hour12?: boolean | null; readonly numberingSystem?: string | null }
| — | — |
form | string | | — |
granularity | "minute" | "second" | minute | minute, second |
hourCycle | "h11" | "h12" | "h23" | "h24" | — | h11, h12, h23, h24 |
inputId | string | | — |
invalid | boolean | false | — |
label | string | | — |
locale | string | en-US | — |
max | string | | — |
min | string | | — |
name | string | | — |
placeholder | string | | — |
readonly | boolean | false | — |
required | boolean | false | — |
size | "sm" | "md" | "lg" | md | sm, md, lg |
timeZone | string | | — |
type | "date" | "time" | "datetime-local" | "instant" | "zoned" | date | date, time, datetime-local, instant, zoned |
value | string | | — |
valueFormat | "iso" | "space" | iso | iso, space |
Events
| Name | Detail | Description |
|---|---|---|
change | object
| Emitted when a toggleable control changes checked state. |
input | object
| Emitted with the declared detail payload. |
query-change | object
| Emitted with the declared detail payload. |
validation-change | object
| Emitted with the declared detail payload. |
Slots
No slots.
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
No component tokens.
Shared tokens
No shared tokens.