DateField
Type a date or pick one from a calendar in a popover.
SourcePackage @weft-js/warpPlayground
Preview
tsx
import { state } from '@weft-js/core'import { DateField, Stack, Text } from '@weft-js/warp'import type { IsoDate } from '@weft-js/warp'export function Release() { const date = state<IsoDate | null>('2026-11-14') return ( <Stack gap="related"> <DateField label="Release date" today={TODAY} value={date} /> <Text subtle role="caption">{date.value ? `Saved as ${date.value}` : 'No date set'}</Text> </Stack> )}const TODAY: IsoDate = '2026-11-02'Installation
npm install @weft-js/warpUsage
tsx
import { DateField } from '@weft-js/warp'Limits
min, max and isDateUnavailable turn days off in the calendar.
tsx
import { DateField } from '@weft-js/warp'import type { IsoDate } from '@weft-js/warp'export function Limits() { return ( <DateField label="Maintenance day" hint="Weekdays, within the next 60 days" defaultValue="2026-11-10" today={TODAY} min="2026-11-02" max="2026-12-31" isDateUnavailable={isWeekend} /> )}const min = 60_000const TODAY: IsoDate = '2026-11-02'const isWeekend = (d: IsoDate) => [0, 6].includes(new Date(`${d}T12:00Z`).getUTCDay())Week numbers
Set the week's first day and show its number.
tsx
import { DateField } from '@weft-js/warp'import type { IsoDate } from '@weft-js/warp'export function Weeks() { return ( <DateField label="Sprint starts" defaultValue="2026-11-16" today={TODAY} firstDayOfWeek={1} weekNumbers /> )}const TODAY: IsoDate = '2026-11-02'Hint, error, read-only, disabled
A date field can show a hint or an error, and can be readonly or disabled.
tsx
import { DateField, Stack } from '@weft-js/warp'import type { IsoDate } from '@weft-js/warp'export function States() { return ( <Stack gap="group"> <DateField label="Release date" today={TODAY} hint="Optional" /> <DateField label="Release date" today={TODAY} error="Pick a date after the freeze ends" defaultValue="2026-12-24" /> <DateField label="Release date" today={TODAY} defaultValue="2026-11-14" readonly /> <DateField label="Release date" today={TODAY} defaultValue="2026-11-14" disabled /> </Stack> )}const TODAY: IsoDate = '2026-11-02'Schedule a deploy
A date and a time in one small form.
tsx
import { state } from '@weft-js/core'import { Button, DateField, Row, Stack, Text, TimeField } from '@weft-js/warp'import type { IsoDate, IsoTime } from '@weft-js/warp'export function Schedule() { const date = state<IsoDate | null>('2026-11-05') const time = state<IsoTime | null>('14:00') const planned = state('') const plan = () => (planned.value = `checkout goes out on ${date.value} at ${time.value}`) return ( <Stack gap="group"> <Text role="heading">Schedule a deploy</Text> <Row gap="related" wrap={false}> <DateField label="Date" today={TODAY} value={date} min={TODAY} /> <TimeField label="Time" today={TODAY} value={time} step={30} /> </Row> <Row gap="related" justify="between"> <Text subtle role="caption">{planned.value || 'Nothing planned yet'}</Text> <Button aria-disabled={date.value && time.value ? undefined : 'true'} onClick={plan}>Schedule</Button> </Row> </Stack> )}const min = 60_000const TODAY: IsoDate = '2026-11-02'When to use
Use it for
- One date in a form
- People may know the date and want to type it
Reach for something else
- DateTimeField, when the time matters too
- DateRangeField, when it is a start and an end
- InlineCalendar, when the calendar should always show
Playground
import { DateField } from '@weft-js/warp'<DateField label="Release date" />Accessibility
- Up/Down
- Changes the focused part of the date
- Left/Right
- Moves between month, day and year
- Arrowsinthecalendar
- Move by day or week
- PageUp/PageDown
- Change the month
- Enter
- Picks the day
- Escape
- Closes the calendar
- Each part of the date is its own spin button, and every calendar day is named in full.
- On phones the calendar opens as a sheet.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | The accessible name, drawn as the floating border label (or above, classic). Required. |
hint | unknown | — | One line of help under the control. |
error | unknown | — | Shown instead of the hint; marks the field invalid. |
icon | IconRef | — | Leading icon: it sweeps with the border. |
prefix | unknown | — | Text or an element inside the field before the value, such as $. |
suffix | unknown | — | Text or an element inside the field after the value, such as kg. |
variant | "floating" | "classic" | — | floating (default, or the app's warp({ fields })) · classic: the label above. |
appearance | "line" | — | line: only a bottom line under the value, no box or fill. The boxed field otherwise. |
size | "sm" | "md" | "lg" | 'md' | Control size. md by default. |
clearable | boolean | false | A clear button (shown once there is a value). |
counter | number | — | Maximum length, shown as a counter. |
id | string | — | The element id. One is made for you if you leave it out. |
disabled | boolean | false | Turns it off, and takes it out of the tab order. |
readonly | boolean | false | Shows the value and lets it be selected and copied, but not changed. |
required | boolean | false | The form will not submit without it. |
name | string | — | The name it posts under in a form. |
locale | string | — | The language and region used to format values. |
today | string | — | Fixes what today is, for tests and server rendering. |
presentation | Presentation | — | auto opens a popover, or a sheet when the viewport is under 600px wide; popover and sheet force one. |
value | `${number}-${number}-${number}` | State<`${number}-${number}-${number}` … | — | The current value, when you own the state. |
defaultValue | `${number}-${number}-${number}` | null | — | The starting value, when the component owns the state. |
open | boolean | State<boolean> | — | A state box that holds whether it is open. |
defaultOpen | boolean | false | Starts open, when the component keeps its own open state. |
min | `${number}-${number}-${number}` | — | The lowest allowed value. |
max | `${number}-${number}-${number}` | — | The highest allowed value. |
isDateUnavailable | ((d: `${number}-${number}-${number}`) => boolean) | — | Return true to turn a day off. |
firstDayOfWeek | 0 | 2 | 3 | 4 | 6 | 1 | 5 | — | The day each calendar row starts on, 0 for Sunday to 6. The locale's otherwise. |
weekNumbers | boolean | false | Shows the week number at the start of each calendar row. |
parse | ((text: string, today: `${number}-${number}-${number}`) => `${number}-${… | — | Your own reader for pasted or typed text. |
| Event | Type | Default | Description |
|---|---|---|---|
onInput | ((e: InputEvent & { currentTarget: HTMLInputElement & HTMLTextAreaElemen… | — | Called on each keystroke. |
onValueChange | ((v: `${number}-${number}-${number}` | null, reason: ChangeReason) => vo… | — | Called with each new value, and whether a pointer, a key or code made the change. |
onOpenChange | ((o: boolean) => void) | — | Called with true when it opens and false when it closes. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="date-field"] [data-part="segment"]
segmentfoot