Skip to content

DateTimePicker

Chooses a day and a time in one popup. Use it where the two together make a single moment: a scheduled send, a publish time.

tsx
import { DateTimePicker } from 'neba';

<DateTimePicker label="Publish at" placeholder="Pick a moment" minuteStep={15} clearable />;

Props

PropTypeDefaultDescription
variantshared'solid' | 'outline' | 'text''outline'Weight of the surface: filled, hairline, or none
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Height and type scale
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'Semantic colour role. Arbitrary colour values are not accepted
densityshared'default' | 'compact''default'Padding only: never the height, never the type scale
elevationshared0 | 1 | 2 | 30Drop shadow depth. 0 means no shadow at all
valueDate | nullThe chosen moment. Use with onValueChange for a controlled picker
defaultValueDate | nullThe initial value, for an uncontrolled picker
onValueChange(value: Date | null) => voidCalled when the chosen moment changes
defaultMonthDateWhich month the calendar opens on when there is no value. Defaults to this one
minDateDate | nullThe earliest moment that may be chosen. Unlike DatePicker's this is read at full precision: the day stays selectable in the calendar and the clock blocks the hours before it
maxDateDate | nullThe other end of the same span
shouldDisableDate(date: Date) => booleanBlocks individual cells inside the range: weekends, holidays, a room already booked. The cell stays in the grid, unavailable, and the callback is handed the value that cell would produce
weekStartsOnshared0 | 1 | 2 | 3 | 4 | 5 | 6Which day the week starts on, Sunday being 0. Defaults to whatever the locale says
hour12booleanA 12-hour dial with an AM/PM column. Defaults to whatever the locale does
showSecondsbooleanfalseAdds the seconds column
hourStepnumber1How far apart the rows of the hour column are
minuteStepnumber1The same, for minutes
secondStepnumber1The same, for seconds
shouldDisableTime(value: Date, unit: 'hour' | 'minute' | 'second' | 'meridiem') => booleanBlocks individual rows. Called once per row per column with the instant that row would produce and the column it is in
showNowButtonbooleantrueOffers the shortcut to this moment in the footer
openbooleanWhether the popup is open. Use with onOpenChange for a controlled one
defaultOpenbooleanfalseWhether it starts open
onOpenChange(open: boolean) => voidCalled when the popup opens or closes
localestringBCP 47 tag deciding the month and weekday names, the order of the header's two buttons, and how the trigger writes the value. Defaults to the browser's
formatIntl.DateTimeFormatOptionsHow the trigger writes the value. Passed straight to Intl
placeholderReactNodeShown in the trigger while nothing is chosen
clearablebooleanfalseOffers the × that empties the control
closeOnSelectbooleanfalseCloses the popup as soon as a day is chosen. A moment is a day *and* a time, so closing on the first of the two would leave the second unanswered
labelsPartial<PickerLabels>The strings a screen reader hears. One object rather than twenty props, because they are a set: they default to the locale’s wording, and the date names are not among them, those come from Intl
namestringIdentifies the field when a form is submitted, as YYYY-MM-DDTHH:MM. Local, not UTC
fullWidthbooleanfalseStretches to the width of the container
labelReactNodeThe label, wired to the control by Base UI's Field
descriptionReactNodeHelper text
errorReactNodeError message. Its presence turns the control invalid and re-points the colour family at danger
invalidboolean!!errorForces the invalid state without a message, for when a form library owns validity
readOnlybooleanfalseShown but not changeable. Keeps its colour and edge, drains the saturation
disabledbooleanfalseUnavailable. Drops the colour family for neutral grey

Native <div> attributes pass through to the root. Only color, defaultValue and children are excluded, since the table above spells them differently.

The calendar props behave as they do on DatePicker and the clock props as they do on TimePicker. The calendar and the clock sit side by side at the same height.

closeOnSelect defaults to false and the footer carries a Done button, since two answers have to be given before the popup can close.

Choosing a day leaves the time alone, and choosing a time leaves the day alone, so the two can be picked in either order.

Examples

minDate · maxDate

The bounds are read at full precision, not just to the day. A minDate of 09:30 on the 27th leaves the 27th selectable in the calendar and greys out only the times before 09:30 in the clock; on any later day nothing is blocked.

That is what a rule like "no earlier than now" needs.

What the trigger shows

The trigger wears the calendar glyph and not the clock. The value is written as one string with Intl, combining the date and the time.

Accessibility

  • The calendar is a role="grid" and the clock a set of role="listbox" columns. See DatePicker and TimePicker for the details.
  • The trigger's accessible name reads as one sentence covering both halves.

Released under the MIT License