# How to Use Astryx DateTimeInput and Calendar Components for Date Picking

> Learn to use Astryx DateTimeInput and Calendar components for easy date picking. This guide covers their integration for accessible date and time selection.

- Repository: [Meta/astryx](https://github.com/facebook/astryx)
- Tags: how-to-guide
- Published: 2026-08-06

---

**Astryx provides a composable DateTimeInput component that bundles a text field, pop-over calendar, and time picker into a single accessible interaction, internally leveraging the Calendar component from [`packages/core/src/Calendar/Calendar.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Calendar/Calendar.tsx) to handle month grids, navigation, and ARIA live announcements.**

The facebook/astryx repository delivers robust date-picking primitives through its DateTimeInput and Calendar components. These components manage ISO-8601 datetime strings, support complex constraints like disabled date ranges, and provide full keyboard navigation while maintaining strict accessibility standards.

## Component Architecture and Source Files

The **DateTimeInput** component, implemented in [`packages/core/src/DateTimeInput/DateTimeInput.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/DateTimeInput/DateTimeInput.tsx), composes the core **Calendar** component from [`packages/core/src/Calendar/Calendar.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Calendar/Calendar.tsx) to render the month grid. When a user focuses the date field or clicks the calendar icon, the Calendar pop-over activates, managing navigation via the `useGridFocus` hook and screen-reader announcements via `useAnnounce`.

## Basic Implementation with DateTimeInput

To implement a standard date and time picker, import **DateTimeInput** from `@astryxdesign/core/DateTimeInput` and bind an ISO-8601 string value.

```tsx
import {DateTimeInput} from '@astryxdesign/core/DateTimeInput';
import {useState} from 'react';

function MeetingScheduler() {
  const [meeting, setMeeting] = useState<ISODateTimeString | undefined>();

  return (
    <DateTimeInput
      label="Meeting date & time"
      description="Select a future date and time for the meeting."
      placeholder="Select a date"
      timePlaceholder="Select a time"
      value={meeting}
      onChange={setMeeting}
      hasClear                // shows a clear (×) button when a value is set
      hourFormat="24h"       // use 24‑hour clock
      timeIncrement={5}      // arrow keys step minutes by 5
      min="2024-01-01T00:00" // earliest selectable datetime
      max="2025-12-31T23:59" // latest selectable datetime
    />
  );
}

```

## Configuring Calendar Display and Constraints

The underlying **Calendar** component supports multiple display modes and validation constraints through props forwarded from **DateTimeInput**.

### Multi-Month Display

Set `numberOfMonths` to `2` to display two months side-by-side, useful for range selection or travel booking interfaces.

### Date Constraints

Use `min` and `max` props to define selectable boundaries, or provide a `dateConstraints` array with predicate functions to disable specific dates.

```tsx
// Example with a two‑month calendar and custom date constraints
import {DateTimeInput} from '@astryxdesign/core/DateTimeInput';
import {useState} from 'react';

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

  // Disable all weekdays – only weekends can be selected
  const weekendOnly = (date: Date) => {
    const day = date.getDay(); // 0 = Sun, 6 = Sat
    return day === 0 || day === 6;
  };

  return (
    <DateTimeInput
      label="Weekend event"
      value={dateTime}
      onChange={setDateTime}
      numberOfMonths={2}       // show two months side‑by‑side
      dateConstraints={[weekendOnly]}
      placeholder="Pick a weekend date"
    />
  );
}

```

## Time Input Configuration

**DateTimeInput** exposes granular control over time selection through several props. Set `hourFormat` to `'12h'` or `'24h'`, enable `hasSeconds` for second-level precision, and configure `timeIncrement` to define minute-step intervals for keyboard navigation. The `hasClear` prop adds a clear button to reset the value.

## Handling Async Updates with changeAction

For server-side persistence, use `changeAction` instead of `onChange` to handle asynchronous operations. This prop accepts a callback function and works with the `isLoading` state to indicate pending operations.

```tsx
// Using async changeAction for optimistic UI updates
import {DateTimeInput} from '@astryxdesign/core/DateTimeInput';
import {useState, useTransition} from 'react';

function OptimisticSave() {
  const [value, setValue] = useState<ISODateTimeString | undefined>();
  const [isPending, startTransition] = useTransition();

  const save = async (newValue: ISODateTimeString | undefined) => {
    await fetch('/api/save', {
      method: 'POST',
      body: JSON.stringify({datetime: newValue}),
    });
  };

  return (
    <DateTimeInput
      label="Save on change"
      value={value}
      onChange={setValue}
      changeAction={newVal => startTransition(() => save(newVal))}
      isLoading={isPending}
    />
  );
}

```

## Accessibility and Keyboard Navigation

The **Calendar** component implements robust accessibility features through internal hooks. The `useGridFocus` hook manages keyboard navigation across the month grid using arrow keys, Page Up/Down for month navigation, and Home/End keys. Screen-reader users receive context updates via the `useAnnounce` hook, which provides live region announcements for month changes and selected dates. These implementations ensure compliance with ARIA guidelines as documented in `packages/core/src/Calendar/Calendar.doc.mjs` and `packages/core/src/DateTimeInput/DateTimeInput.doc.mjs`.

## Summary

- **DateTimeInput** composes **Calendar** from [`packages/core/src/Calendar/Calendar.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Calendar/Calendar.tsx) to provide a unified date-time picking interface.
- Configure display options via `numberOfMonths`, and restrict selection using `min`, `max`, and custom `dateConstraints` predicates.
- Control time formatting with `hourFormat`, `hasSeconds`, and `timeIncrement` props.
- Implement asynchronous saves using `changeAction` coupled with `isLoading` state.
- Accessibility is handled internally via `useGridFocus` for keyboard navigation and `useAnnounce` for screen-reader updates.

## Frequently Asked Questions

### How do I disable specific dates in the Astryx Calendar component?

Pass an array of predicate functions to the `dateConstraints` prop. Each function receives a JavaScript Date object and returns a boolean indicating whether the date is selectable. For example, to allow only weekends, return `true` when `date.getDay()` equals `0` or `6`.

### What is the difference between onChange and changeAction in DateTimeInput?

The `onChange` callback executes synchronously when the value updates, suitable for local state management. The `changeAction` prop accepts an async function for server-side operations, automatically handling loading states and optimistic updates when paired with the `isLoading` prop.

### How do I display two months side by side in the date picker?

Set the `numberOfMonths` prop to `2`. This configuration renders a dual-month view within the Calendar pop-over, allowing users to navigate and select dates across two adjacent months simultaneously.

### Can I use the Calendar component independently without the time picker?

Yes. While **DateTimeInput** provides the combined interface, you can import and use the **Calendar** component directly from `@astryxdesign/core/Calendar` for date-only selection scenarios. The component maintains the same constraint and navigation APIs.