Built on Vercel’s UI SDK 0.1.0-beta.2. Its API may change.
Date input
A date field on Vercel's UI SDK typed one part at a time in the locale's order, with an optional time, min and max, unavailable days and an ISO value.
- Form components
- 3 parts
- 10 examples
@ui-sdk/core@ui-sdk/react
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-date-input.jsonAdds the component, the HextaUI theme tokens and any HextaUI components it depends on.
Add the theme tokens to your global CSS, if you haven’t yet.
Install the dependencies.
pnpm add @ui-sdk/react@0.1.0-beta.2 @ui-sdk/core@0.1.0-beta.2 cnCopy and paste the following code into your project.
components/ui/ui-sdk-date-input.tsx Update the import paths to match your project setup.
UI SDK adds a little CSS of its own in a cascade layer named ui-sdk. Declare that layer at the top of your global stylesheet, above the Tailwind import, so your classes win over it.
Use a date input for dates people know by heart, like a birthday. The value is an ISO date like "2026-11-02", and it stays null until every part holds something. Each part fills as you type and moves on, the day is kept within its month, and a whole date can be pasted into any part. For picking from a calendar, use the Date Picker.
The field is a group, so name it with aria-labelledby or aria-label. Clicking anywhere in the box focuses the nearest part.
DateInput renders its parts on its own. Add DateInputSegments yourself to put an icon or other content beside them.
granularity set to "hour", "minute" or "second" adds the time, and the value becomes a local date and time like "2026-11-02T14:30".
A date before min or after max marks the field invalid, and its form won’t submit.
unavailable takes ISO dates, { from, to } ranges, weekdays or a function, and a date on one is invalid.
locale sets the order and the separators. The digits are always 0 to 9 and the calendar is always Gregorian, so the value means the same date everywhere.
A hidden input submits the ISO date under name, here beside a Time Input. required stops an empty or half-typed date, and a reset brings back the default.
createDateInputController() sets, clears or focuses the field from anywhere. Focus a part by its unit, like "year".
A disabled field is skipped by focus and doesn’t submit.
A read-only field takes focus and submits, but keys and typing don’t change it.
The parts keep the locale’s order, and the arrow keys follow them on screen.
| Key | Action |
|---|---|
| 0–9 | Fills the part, then moves to the next one. |
| /. | Moves to the next part. |
| ↑↓ | Steps the part by one, wrapping around. An empty part starts at today. |
| PageUpPageDown | Steps by more: a year by 5, a month by 3, a day by 7. |
| HomeEnd | Goes to the part’s first or last value. |
| ←→ | Moves to the part before or after. |
| Backspace | Removes the last digit, then empties the part, then moves back. |
| Enter | Submits the form with what’s typed. |
The root is a group. Each part is a spinbutton named by its unit, like “month”, with its value and range, and an empty part reads as “Empty”. The text between parts is hidden from screen readers.
Parts are real inputs, so phones show a number pad and typing works before the page’s script runs. They grow to 16px on touch screens so phones don’t zoom in, and the focused part is highlighted rather than showing a caret.
Each part wraps the UI SDK part of the same name and accepts all of its props, including render and a className that can be a function of the part’s state.
| Prop | Type | Default |
|---|---|---|
value | string | null | – |
defaultValue | string | null | – |
onValueChangeRuns once every part holds something, and with null when one is emptied. | (value: string | null, details) => void | – |
granularity | "day" | "hour" | "minute" | "second" | "day" |
hourCycleDefaults to the locale’s clock. | 12 | 24 | – |
min | string | – |
max | string | – |
unavailableISO dates, { from, to } ranges, { weekday } or a function. | DateMatchers | – |
localeDefaults to the page’s language. | string | – |
invalid | boolean | false |
disabled | boolean | false |
readOnly | boolean | false |
required | boolean | false |
name | string | – |
form | string | – |
controllerFrom createDateInputController(). | DateInputController | – |
childrenDefaults to DateInputSegments. | ReactNode | (state) => ReactNode | – |
render | ReactElement | (props, state) => ReactElement | – |
| Attribute | Description |
|---|---|
data-slot="date-input" | Target the date input in CSS. |
data-invalid | Present when the date is outside min and max, unavailable, or invalid is set. |
data-empty | Present while every part is empty. |
data-disabled | Present when disabled. |
data-readonly | Present when read-only. |
data-required | Present when required. |
Renders a DateInputSegment for each part, in the locale’s order, with the text between them.
| Prop | Type | Default |
|---|---|---|
segmentOne of the root state’s segments. | DateInputSegmentData | – |
render | ReactElement | (props, state) => ReactElement | – |
| Attribute | Description |
|---|---|
data-slot="date-input-segment" | Target a part in CSS. |
data-type | year, month, day, hour, minute, second, dayPeriod, or literal for the text between parts. |
data-empty | Present while the part is empty. |
- CalendarA date grid for single, range and multiple selection, with sliding months, range previews and touch-sized days.
- CheckboxA checkbox whose check draws in, with indeterminate parents, groups and labels that share its hover.
- ComboboxA filterable select with chips, groups and async results, in a popup that resizes as you type.
- Date pickerA button that opens a calendar in a popover, or a bottom sheet on phones, for single dates and ranges.
- FieldLabels, descriptions and errors wired to their control, with validation states and layouts for forms.
- InputA text input with three sizes, invalid and read-only states, native validation styling and a 16px touch font so phones never zoom in.