DatePicker
A date field you can type into, with a Calendar in a popover. Typed text is read in the locale's numeric order (09/30/2026 for en-US, 30.09.2026 for tr-TR) or as ISO 2026-09-30.
Type MM/DD/YYYY or pick from the calendar.
const [date, setDate] = useState<Date | null>(null);
<Field label="Due date" description="Type MM/DD/YYYY or pick from the calendar.">
<DatePicker value={date} onValueChange={setDate} name="due" />
</Field>Import
import { DatePicker } from "@meridui/react";Examples
Range
mode="range" renders a start and an end field. The calendar closes once both days are picked.
const [range, setRange] = useState<DateRange>({ start: null, end: null });
<DatePicker mode="range" value={range} onValueChange={setRange} startLabel="Check-in" endLabel="Check-out" />Min, max and disabled days
Typed dates outside the limits are rejected and the field reverts to the last valid value.
Weekdays only, from today.
<DatePicker min={today} isDateDisabled={(d) => d.getDay() === 0 || d.getDay() === 6} />Sizes and states
<DatePicker aria-label="Small" size="sm" />
<DatePicker aria-label="Invalid" invalid />
<DatePicker aria-label="Disabled" disabled defaultValue={today} />In a form
With name, a hidden input submits yyyy-mm-dd. A range submits two values under name[]. toISODate(date) gives the same string.
API reference
Renders a div; other div attributes and the ref go on it. aria-label / aria-labelledby name the text field. Inside a Field the (first) field gets the id, description, error, required and disabled.
| Prop | Type | Default | Description |
|---|---|---|---|
mode | "single" | "range" | "single" | Pick one day or a start and end day. |
value / defaultValue | Date | null | DateRange | – | Controlled or initial selection. |
onValueChange | (value) => void | – | Called with the new day (or range); null when the field is cleared. |
locale | string | "en-US" | Calendar names, week start and the typed numeric format. |
min / max | Date | – | Earliest and latest selectable day. |
isDateDisabled | (date: Date) => boolean | – | Marks individual days unavailable. |
weekStartsOn | 0 – 6 | – | First calendar column. Defaults to the locale's week start. |
open / onOpenChange | boolean / (open) => void | – | Controlled open state of the calendar. |
placeholder | string | locale pattern, e.g. MM/DD/YYYY | Placeholder of the text field(s). |
calendarLabel | string | "Choose date" | Accessible name of the calendar button. |
dialogLabel | string | calendarLabel | Accessible name of the calendar dialog. |
previousMonthLabel / nextMonthLabel | string | "Previous month" / "Next month" | Calendar navigation button names. |
startLabel / endLabel | string | "Start date" / "End date" | Range only: names of the two fields. |
size | "sm" | "md" | "lg" | "md" | Height of the field. |
invalid / disabled / required | boolean | – | States; inside a Field they come from it. |
name | string | – | Hidden input with yyyy-mm-dd; a range submits name[] twice. |
icon | ReactNode | – | Icon inside the calendar button. |
inputId | string | – | id of the (first) text field. |
Styling
| Class | Element |
|---|---|
.mrd-date-picker | Root (data-size, data-mode, data-invalid, data-disabled) |
.mrd-date-picker__field | Bordered field |
.mrd-date-picker__input, .mrd-date-picker__separator | Text field(s) and the range dash |
.mrd-date-picker__trigger | Calendar button (data-state) |
.mrd-date-picker__content | Popover holding the calendar |
Accessibility
The text field is the primary input; the calendar button (aria-haspopup="dialog") opens a non-modal dialog with focus on the selected day. Picking a day or pressing Escape closes it and returns focus to the button. See Calendar for keys inside the grid.
| Key | Action |
|---|---|
| AltArrowDown | In the text field: open the calendar. |
| Enter | In the text field: read the typed date. In the calendar: pick the focused day. |
| Escape | Close the calendar and return focus to the button. |