InputsReact
A DateField with a calendar popup: the field is the primary input, a trigger button opens a dialog that holds a Calendar, and both edit one value, an ISO 8601 string such as '2026-11-12'.
Rendered by React 19.3.1
Loading React…Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<DatePicker.Root>
<DatePicker.Control>
<DatePicker.Input>
<DatePicker.Segment />
</DatePicker.Input>
<DatePicker.Clear />
<DatePicker.Trigger />
</DatePicker.Control>
<DatePicker.Portal>
<DatePicker.Positioner>
<DatePicker.Popup>
<DatePicker.Calendar />
<DatePicker.Close />
</DatePicker.Popup>
</DatePicker.Positioner>
</DatePicker.Portal>
</DatePicker.Root>
// Not in this example: DatePicker.PresetExamples
Limits
min and max with isDateUnavailable for weekends, in a Field: the calendar disables them and a typed one is invalid.
Form
Inside Field and Form with required and a name: the date submits as due=2026-11-12.
API reference
61 props across 12 parts, in React syntax. className, style, render are listed once, under Shared props.
CalendarDatePicker.Calendar
The calendar of the popup: Calendar.Root (or RangeCalendar.Root) wired to the picker's value, limits, locale and visible month. Compose it with the Calendar parts (Calendar.PrevButton, Calendar.Heading, Calendar.Grid and the rest). It takes no part in the Field: the control already submits and validates the value. Renders a <div>.
ClearDatePicker.Clear
Clears the whole value, including a partly typed one. It is out of the tab order: Backspace clears a segment from the keyboard. Renders a <button>.
CloseDatePicker.Close
A button that closes the popover. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
ControlDatePicker.Control
The group that holds the field and the trigger, and the element the popup is anchored to. It is the field's root: it is named by the Field label, shows the Field's validity, and counts the popup as inside it, so moving focus into the calendar neither touches nor validates the field. Renders a <div>.
InputDatePicker.Input
The visual control: it wraps the segments. Its children are a function of the segments, since their order depends on the locale; without children it renders every segment. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
childrenThe segments, or a function of them: ({ segments }) => .... | React.ReactNode | ((context: { segments: FieldSegment[]; }) => React.ReactNode) | — |
PopupDatePicker.Popup
The dialog that holds the calendar and the presets. It is named "Choose date" unless you name it. Focus moves to the highlighted day when it opens, and returns to the trigger (or to the segment Alt+Down was pressed on) when it closes. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
initialFocusDetermines the element to focus when the popover is opened. | boolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | void | HTMLElement | null) | — |
finalFocusDetermines the element to focus when the popover is closed. | boolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null) | — |
PortalDatePicker.Portal
A portal element that moves the popup to a different part of the DOM. By default, the portal element is appended to <body>. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
keepMountedWhether to keep the portal mounted in the DOM while the popup is hidden. | boolean | false |
containerA parent element to render the portal element into. | HTMLElement | ShadowRoot | React.RefObject<HTMLElement | ShadowRoot | null> | null | — |
PositionerDatePicker.Positioner
Positions the popup against the control (the field and the trigger together). Renders a <div>.
| Prop | Type | Default |
|---|---|---|
alignHow to align the popup relative to the specified side. | Align | 'start' |
anchorAn element to position the popup against. | Element | VirtualElement | React.RefObject<Element | null> | (() => Element | VirtualElement | null) | null | — |
positionMethodDetermines which CSS position property to use. | "absolute" | "fixed" | 'absolute' |
sideWhich side of the anchor element to align the popup against. | Side | 'bottom' |
sideOffsetDistance between the anchor and the popup in pixels. | number | OffsetFunction | 0 |
alignOffsetAdditional offset along the alignment axis in pixels. | number | OffsetFunction | 0 |
collisionBoundaryAn element or a rectangle that delimits the area that the popup is confined to. | Boundary | 'clipping-ancestors' |
collisionPaddingAdditional space to maintain from the edge of the collision boundary. | Padding | 5 |
stickyWhether to maintain the popup in the viewport after | boolean | false |
arrowPaddingMinimum distance to maintain between the arrow and the edges of the popup. | number | 5 |
disableAnchorTrackingWhether to disable the popup from tracking any layout shift of its positioning anchor. | boolean | false |
collisionAvoidanceDetermines how to handle collisions when positioning the popup. | CollisionAvoidance | — |
PresetDatePicker.Preset
A button that sets the value to a date or a range, such as "Last 7 days". The value can be a function of today, which the picker reads from the clock after mount (or from today). It closes the popup like a day does. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
valuerequiredThe value the preset sets: a date ('2026-11-07'), a range ({ start, end }), or a function | `${number}-${number}-${number}` | DateRange | ((today: `${number}-${number}-${number}`) => `${number}-${number}-${number}` | DateRange) | — |
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
RootDatePicker.Root
Groups all parts of a field with a calendar popup that picks one date. It renders no element. Values are ISO 8601 strings such as '2026-11-07'; onValueChange is called only with a complete, real date, or null.
| Prop | Type | Default |
|---|---|---|
valueThe date, null for none. | `${number}-${number}-${number}` | null | — |
defaultValueThe date when initially rendered. | `${number}-${number}-${number}` | null | — |
onValueChangeEvent handler called when the date changes: a complete, real date, or null. | ((value: `${number}-${number}-${number}` | null, eventDetails: DatePickerRootChangeEventDetails) => void) | — |
autoComplete'bday' gives the segments the bday-day, bday-month and bday-year autocomplete tokens. | "off" | "bday" | 'off' |
openWhether the popup is open. | boolean | — |
defaultOpenWhether the popup is initially open. | boolean | false |
onOpenChangeEvent handler called when the popup opens or closes. | ((open: boolean, eventDetails: DatePickerRootOpenChangeEventDetails) => void) | — |
onOpenChangeCompleteEvent handler called after any animations complete when the popup opens or closes. | ((open: boolean) => void) | — |
actionsRefA ref to imperative actions: unmount and close. | React.RefObject<PopoverRootActions | null> | — |
modalWhether the rest of the page is inert while the popup is open. | boolean | "trap-focus" | false |
closeOnSelectWhether choosing a day (the second end of a range) or a preset closes the popup. | boolean | true |
minThe earliest date that can be chosen. | `${number}-${number}-${number}` | — |
maxThe latest date that can be chosen. | `${number}-${number}-${number}` | — |
isDateUnavailableWhether a date cannot be chosen but can hold focus. | ((date: `${number}-${number}-${number}`, anchor: `${number}-${number}-${number}` | null) => boolean) | — |
isDateDisabledWhether a date is skipped by navigation and cannot be chosen. | ((date: `${number}-${number}-${number}`) => boolean) | — |
localeThe BCP 47 locale of the field and the calendar. | string | 'en-US' |
firstDayOfWeekThe first day of the week, 0 (Sunday) to 6. | number | — |
visibleMonthThe first visible month. | `${number}-${number}-${number}` | `${number}-${number}` | null | — |
onVisibleMonthChangeEvent handler called when the visible month changes. | ((month: `${number}-${number}`, eventDetails: DatePickerVisibleMonthChangeEventDetails) => void) | — |
visibleMonthsHow many months are visible. | number | 1 |
pageBehaviorWhether Previous and Next move by the visible months or by one. | "visible" | "single" | 'visible' |
fixedWeeksWhether every month shows six weeks. | boolean | false |
todayThe date of today, for the calendar and the presets. | `${number}-${number}-${number}` | — |
timeZoneThe time zone that decides what today is, when today is not given. | string | — |
labelsThe texts the picker, the field and the calendar add (the trigger and popup names, the Close | Partial<DatePickerLabels & DateFieldLabels & CalendarLabels> | — |
forceLeadingZerosWhether the day, month and hour show a leading zero. | boolean | — |
placeholderValueThe value an empty segment takes on its first Up or Down press. | string | — |
autoAdvanceWhether focus moves to the next segment when the typed number cannot get another digit. | boolean | true |
segmentRoleThe role of the segments. | DateFieldSegmentRole | 'spinbutton' |
onIncompleteChangeEvent handler called when the segments change while no complete value exists. | ((parts: FieldParts, eventDetails: any) => void) | — |
disabledWhether the component should ignore user interaction. | boolean | false |
readOnlyWhether the user should be unable to change the value. | boolean | false |
requiredWhether the user must fill in the field before submitting a form. | boolean | false |
invalidWhether the field is invalid. | boolean | false |
nameIdentifies the field when a form is submitted. | string | — |
formIdentifies the form that owns the hidden inputs. | string | — |
inputRefA ref to access the first segment. | React.Ref<HTMLInputElement> | — |
children | React.ReactNode | — |
SegmentDatePicker.Segment
One segment of the value. An editable segment (year, month, day, hour, minute, second, millisecond, day period) is a real <input> with the spinbutton role; a literal (/, :) is a <span> hidden from assistive technology., or a <span> for a literal. Renders an <input>.
| Prop | Type | Default |
|---|---|---|
segmentrequiredThe segment to render, one of the segments the Input gives its children. | FieldSegment | — |
TriggerDatePicker.Trigger
A button that opens the popup. It is named "Choose date", or "Change date, Saturday, November 7, 2026" once a date is chosen. It sits inside the control. Renders a <button>.
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native <button> element when replacing it | boolean | true |
idID of the trigger. | string | — |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
| Keys | Does | Part |
|---|---|---|
| EnterSpace | On the trigger: opens the popup and moves focus to the highlighted day | Trigger |
| AltArrowDown | On a segment: opens the popup and moves focus to the highlighted day | Segment |
| ArrowDown | On a segment: steps the segment as in DateField; it does not open the popup | Segment |
| EnterSpace | On a day: chooses it, closes the popup (with closeOnSelect) and returns focus | Popup |
| Escape | Closes the popup and returns focus to the trigger, or to the segment Alt+ArrowDown was used on | Popup |
| AltArrowUp | Inside the popup: closes it | Popup |
| Tab | Non-modal: from the last element of the popup closes it and continues after the trigger | Popup |
Accessibility
| Part | Sets | So that |
|---|---|---|
| Control | role="group", named by the Field label (or aria-label); the Field's validity, data-popup-open | the group is announced once, "Birthday, group", and the error is on the segments |
| Trigger | aria-haspopup="dialog", aria-expanded, aria-controls; aria-label "Choose date" or "Change date, Saturday, November 7, 2026" | the button says what it does and what the date is now |
| Trigger | aria-disabled while readOnly | a read only picker does not open, and says so |
| Popup | role="dialog" named "Choose date" (or your aria-label); aria-modal only with modal | a screen reader announces the dialog on open; the page is not hidden unless it is inert |
| Close | a button, "Close" | a touch screen reader can leave a popup it cannot Escape |
Focus order
- Each segment is a tab stop, then Clear is out of the order, then the Trigger. Nothing takes focus on mount.
- Opening moves focus into the popup, to the calendar day; presets and the Close button come in DOM order around it.
- Closing returns focus to the trigger, or to the segment the popup was opened from.
- Tab from the last tabbable element of a non-modal popup closes it and moves to the next element after the trigger.