EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
DateInput·component·@astryxdesign/core

Date Time Input

DateTimeInput combines date and time selection in one field. With presentation="adaptive-native" (the default), mouse/trackpad devices use Astryx typed fields and popovers, while coarse-pointer devices use browser/OS date and time controls in the same two-segment field. presentation="native" uses both native controls on every pointer; presentation="adaptive-bottom-sheet" keeps Astryx's own surfaces — pointer fields on fine pointers and the coordinated Date/Time bottom sheet on coarse pointers; "popover" and "bottom-sheet" force one Astryx surface on every pointer. The closed segments stay side by side when at least 400px is available and wrap into full-width rows below 400px, independent of viewport width. Use it for scheduling, event creation, deadline setting, or any form field that needs a specific datetime.

Open in Playground @astryxdesign/core/DateTimeInput

Showcases and examples

2 documented examples

Date Time Input

A combined date and time picker. Desktop opens a calendar popover with a time input; touch devices open a Date/Time bottom sheet.

Preview loads on approachPreview loads on approach
Exact source · date-time-input-showcase
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {useState} from 'react';
import {DateTimeInput} from '@astryxdesign/core/DateTimeInput';
import type {ISODateTimeString} from '@astryxdesign/core/DateTimeInput';
import {Stack} from '@astryxdesign/core/Layout';

export default function DateTimeInputShowcase() {
  const [dateTime, setDateTime] = useState<ISODateTimeString | undefined>(
    undefined,
  );

  return (
    <Stack
      direction="vertical"
      width="100%"
      style={{minWidth: 240, maxWidth: 400}}>
      <DateTimeInput
        label="Meeting time"
        placeholder="Select a date"
        value={dateTime}
        onChange={setDateTime}
        hasClear
      />
    </Stack>
  );
}

Usage

DateTimeInput combines date and time selection in one field. With presentation="adaptive-native" (the default), mouse/trackpad devices use Astryx typed fields and popovers, while coarse-pointer devices use browser/OS date and time controls in the same two-segment field. presentation="native" uses both native controls on every pointer; presentation="adaptive-bottom-sheet" keeps Astryx's own surfaces — pointer fields on fine pointers and the coordinated Date/Time bottom sheet on coarse pointers; "popover" and "bottom-sheet" force one Astryx surface on every pointer. The closed segments stay side by side when at least 400px is available and wrap into full-width rows below 400px, independent of viewport width. Use it for scheduling, event creation, deadline setting, or any form field that needs a specific datetime.

  • Provide clear labels and descriptions so users understand what datetime is expected.
  • Use min and max to restrict selectable datetimes to valid ranges.
  • Use hasClear when the datetime is optional so the user can reset it.
  • Choose the hour format (12h or 24h) that matches your audience's locale.
  • Use DateTimeInput when only a date is needed; use DateInput instead.
  • Use DateTimeInput when only a time is needed; use TimeInput instead.
  • Hide the label without surrounding context that makes the field purpose obvious.
  • Wrap a disabled DateTimeInput in Tooltip to explain why it is disabled; disabled triggers swallow the hover events the wrapper needs. Use the disabledMessage prop instead.

Typed props

PropType and behavior
labelstring · required
Label text.
isLabelHiddenboolean · default false
Visually hide the label.
descriptionstring
Helper text displayed below the label.
isOptionalboolean · default false
Show an "(optional)" indicator next to the label.
isRequiredboolean · default false
Mark the field as required.
isDisabledboolean · default false
Disable the input and picker.
disabledMessagestring
Explains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the field focusable via aria-disabled (activation stays blocked). Use this instead of wrapping a disabled DateTimeInput in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.
valueISODateTimeString
Selected datetime in ISO 8601 format (YYYY-MM-DDTHH:MM or YYYY-MM-DDTHH:MM:SS).
onChange(value: ISODateTimeString | undefined) => void · required
Callback invoked when the selected datetime changes.
changeAction(value: ISODateTimeString | undefined) => void | Promise<void>
Async action fired after onChange. Drives optimistic UI updates via useTransition.
isLoadingboolean · default false
Whether the input is in a loading state. Disables interaction and shows a spinner.
minISODateTimeString
Minimum selectable datetime. Constrains both date and time selection.
maxISODateTimeString
Maximum selectable datetime. Constrains both date and time selection.
dateConstraintsArray<(date: Date) => boolean>
Array of custom constraint functions that disable specific dates.
hasSecondsboolean · default false
Include seconds in the time portion. Keeps Astryx's time field even when nativePicker selects native surfaces, because iOS has no seconds wheel.
hourFormat'12h' | '24h' · default '12h'
Hour display format. '12h' shows AM/PM; '24h' uses 24-hour notation.
timeIncrement1 | 5 | 10 | 15 | 30 · default 1
Minute step for arrow keys in Astryx's typed time field. A non-default value keeps the Astryx time field in nativePicker modes because iOS treats native step as validation, not picker cadence. Ignored by the Astryx touch sheet, which uses wheels.
timeOptionInterval5 | 10 | 15 | 30 | 60
Minute cadence for the preset-time combobox on Astryx's fine-pointer time field. Setting it keeps that Astryx time field even in nativePicker modes because the OS picker has no equivalent preset list. The Astryx touch sheet uses wheels.
hasClearboolean · default false
Shows a clear button when a datetime value is set.
placeholderstring · default 'Select a date'
Placeholder text shown in the date portion when no date is selected.
timePlaceholderstring · default 'Select a time'
Placeholder text shown in the time portion when no time is selected. On touch, this appears in the closed time segment before a time is chosen.
timeLabelstring
Accessible label for the time portion. Defaults to "{label} time" so it is tied to the field label and localizable.
size'sm' | 'md' | 'lg' · default 'md'
Size of the input control.
status{type: 'warning' | 'error' | 'success', message?: string}
Status indicator object for error, warning, or success states with a message.
labelTooltipstring
Tooltip text displayed via an info icon at the end of the label.
numberOfMonths1 | 2 · default 1
Number of months displayed simultaneously in Astryx's pointer calendar popover. Ignored by native date controls and the mobile touch sheet, whose Date panel always shows one swipe-paged month at a time.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 6 | 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' · default 0
First day of week in Astryx calendars. A number (0 = Sunday to 6 = Saturday) or a three-letter day name. Ignored by native date controls.
presentation'popover' | 'bottom-sheet' | 'native' | 'adaptive-bottom-sheet' | 'adaptive-native' · default 'adaptive-native'
Which surfaces draw the date and time pickers. 'adaptive-native' (the default) uses Astryx's typed fields and popovers on a fine pointer and browser/OS controls on a coarse pointer — with per-segment Astryx fallbacks: hasSeconds, non-default timeIncrement, or timeOptionInterval retain Astryx's time field because iOS cannot express them faithfully; 'native' always uses both browser/OS controls with no fallback; 'adaptive-bottom-sheet' uses popovers on a fine pointer and Astryx's coordinated bottom sheet on a coarse pointer; 'popover' and 'bottom-sheet' force that Astryx surface on every pointer. Every value opens pickers; typed-only fields are TimeInput's alone. Use a non-native presentation when numberOfMonths, weekStartsOn, or visible dateConstraints behavior matters. Constraints are enforced on commit; min/max are forwarded as hints. hourFormat formats the closed time, while the OS picker follows the user's locale.
nativePicker'touch' | 'always' | 'never' · default 'touch'
Deprecated: use presentation ('touch' = 'adaptive-native', 'always' = 'native', 'never' = 'adaptive-bottom-sheet'). Still works exactly as released; presentation wins when both are set.
widthSizeValue
Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.
xstyleStyleXStyles
StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value, not an inline style object like style={{}}.

Anatomy

Label · required

Text above the input describing what datetime is expected.

Date input · required

A typed date field with calendar popover on the fine-pointer Astryx surface, a real input type=date in native modes, or a read-only segment opening the Astryx touch sheet under presentation="adaptive-bottom-sheet" on a coarse pointer.

Calendar icon · required

A button that opens the active date surface: the platform picker, Astryx calendar popover, or Astryx touch sheet.

Date picker · optional

The browser/OS picker in native modes, an Astryx month-grid popover on a fine pointer, or the Date panel of the Astryx bottom sheet on a coarse pointer with presentation="adaptive-bottom-sheet".

Time input · required

A real input type=time for the default minute-precision native mode, a text/combobox time field when seconds, custom increments, or preset options are requested, or a read-only segment opening accessible time wheels under presentation="adaptive-bottom-sheet" on a coarse pointer.

Time options popover · optional

A list of preset times at the timeOptionInterval cadence. Setting the prop retains Astryx's text/combobox time field even when nativePicker otherwise selects native controls; the Astryx touch sheet uses wheels instead.

Clear button · optional

A × button that resets the datetime value.

Status message · optional

An error, warning, or success message below the inputs.

Theming

Targets

astryx-date-time-input

Visual props: size, status

States: disabled

astryx-date-time-input-date-segment

Visual props: size, status

astryx-date-time-input-time-segment

Visual props: size, status

astryx-date-time-input-toggle-icon

States: state

astryx-date-time-input-clock-icon
astryx-date-time-input-time-listbox
astryx-date-time-input-time-option