Date Field

A date field provides a fully labeled date input with built-in support for descriptions and error messages. It wraps a native <input type="date"> with a visible <label>, optional helper text, and validation error display, all properly linked via generated IDs for accessibility.

This component is ideal for forms that require date input with validation feedback. The value prop is bindable, allowing two-way data flow with the parent component. Error messages are announced to screen readers via role="alert", and the input's invalid state is communicated through aria-invalid and aria-errormessage.

Example

/ /
Show demo markup
<div class="date-field" role="group" aria-label="Date"><input type="text" aria-label="Day" size="2" value="15" /> / <input type="text" aria-label="Month" size="2" value="03" /> / <input type="text" aria-label="Year" size="4" value="2026" /></div>
Usage example
<script lang="ts">
    import DateField from "./DateField.svelte";

    let start = $state("");
</script>

<DateField label="Start date" bind:value={start} />
Show Svelte source
// In your Svelte component:
import DateField from "lily-design-system-svelte-headless/components/DateField/DateField.svelte";

<DateField>
  <!-- content -->
</DateField>

Usage

Basic date field for a registration form:

<DateField label="Date of birth" value={dateOfBirth} description="Enter as day, month, year" required />

Date field with validation error:

<DateField label="Appointment date" value={appointmentDate} error="Date must be in the future" required />

Optional date field with helper text:

<DateField label="Preferred start date" value={startDate} description="Leave blank if flexible" />

Props

  • label: string (required) -- visible label text for the date field
  • value: string (default: "") -- current date value in YYYY-MM-DD format, two-way bindable via value
  • description: string (default: undefined) -- helper text displayed below the input
  • error: string (default: undefined) -- error message displayed when validation fails
  • required: boolean (default: false) -- whether the field is required
  • disabled: boolean (default: false) -- whether the field is disabled
  • id: string (default: undefined) -- custom ID for the input element; auto-generated if omitted

Keyboard Interactions

None beyond native <input type="date"> keyboard behavior, which varies by browser.

ARIA

  • <label for={inputId}> -- links the visible label to the input
  • aria-describedby={descriptionId} -- links the input to its description text when present
  • aria-invalid="true" -- indicates the input contains an invalid value when an error is present
  • aria-errormessage={errorId} -- links the input to its error message when present
  • role="alert" -- on the error paragraph, announces the error message to screen readers

When to Use

  • Use for structured date entry with separate fields for day, month, and year.
  • Use when more control over individual date parts is needed than a plain DateInput provides.
  • Use when you want built-in ARIA linking between the label, input, description, and error message without manual ID management.
  • Use for forms that require date input with validation feedback, description text, and error display in a single integrated component.
  • Use when accessibility-compliant date entry is essential, such as in healthcare or government forms.

When Not to Use

  • Do not use for known exact dates where a simple DateInput is sufficient.
  • Do not use for calendar-based date selection -- use CalendarTable or CalendarRangePicker instead.
  • Do not use when you need a bare date input with custom label placement; use DateInput instead.

Headless

This headless DateField component provides a <div> wrapper with a <label>, <input type="date">, optional description <p>, and optional error <p> with role="alert", all linked by auto-generated IDs for aria-describedby and aria-errormessage. The consumer provides all visual styling including label typography, input appearance, description and error text colors, and layout.

Styles

The consumer provides all CSS styling. The component renders with a .date-field class for targeting. No default styles are included — this is a fully headless component.

Testing

  • Verify the component renders a <div> element with class date-field
  • Verify role="alert"` -- on the error paragraph, announces the error message to screen readers
  • Verify pass-through attributes are applied

Advice

  • Designers: Place the description text below the label and above the input to set expectations before users interact. Display error messages in a contrasting color near the input.
  • Developers: Use the bindable value prop for two-way date state. The auto-generated IDs handle all ARIA linking; provide a custom id prop only when you need a specific ID for testing or integration.

Implementation Notes

  • Renders a <div> wrapper containing a <label>, <input type="date">, optional description <p>, and optional error <p>
  • Auto-generates a unique ID for the input if none is provided, using derived value for reactivity
  • Derives descriptionId and errorId from the input ID for ARIA linking
  • Supports two-way binding on the value prop
  • Error paragraph uses role="alert" for live announcement to screen readers

Related components

  • date-input — an input for entering a date value <input type="date">
  • date-range — paired start and end date inputs
  • calendar-range-picker — a picker for selecting a date range on a calendar

References

  • ARIA Error Handling: https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA21
  • WAI Forms Tutorial: https://www.w3.org/WAI/tutorials/forms/

Canonical contract

Generated from this component's canonical metadata — the machine-checked source the implementations are held to.

Metadata

  • Component: date-field
  • PascalCase: DateField
  • Description: a structured field for entering date components
  • Status: beta — implemented and unit-tested in all seven frameworks with an axe-clean demo page; not yet exercised in composed flows
  • HTML tag: <div>
  • CSS class: .date-field
  • Interactive: no

ARIA

  • <label for={inputId}> -- links the visible label to the input
  • aria-describedby={descriptionId} -- links the input to its description text when present
  • aria-invalid="true" -- indicates the input contains an invalid value when an error is present
  • aria-errormessage={errorId} -- links the input to its error message when present
  • role="alert" -- on the error paragraph, announces the error message to screen readers

Keyboard

  • No keyboard interactions — this is a passive element

Props

  • label: string (required) -- visible label text for the date field
  • value: string (default: "") -- current date value in YYYY-MM-DD format, two-way bindable via value
  • description: string (default: undefined) -- helper text displayed below the input
  • error: string (default: undefined) -- error message displayed when validation fails
  • required: boolean (default: false) -- whether the field is required
  • disabled: boolean (default: false) -- whether the field is disabled
  • id: string (default: undefined) -- custom ID for the input element; auto-generated if omitted