DatePicker

A single-date picker that combines a trigger field with a calendar popup for selecting dates.

Import

import { DatePicker } from 'heroui-native-pro';

Anatomy

<DatePicker>
  <Label>...</Label>
  <DatePicker.Select>
    <DatePicker.Trigger>
      <DatePicker.Value />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content>
        <DatePicker.Calendar>
          <Calendar.Header>...</Calendar.Header>
          <Calendar.Grid>...</Calendar.Grid>
        </DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
  <Description>...</Description>
</DatePicker>
  • DatePicker: Root container that manages date selection state, open state, display formatting, and form field context (for Label, Description, FieldError). Supports controlled and uncontrolled modes.
  • DatePicker.Select: Pre-wired Select root connected to the DatePicker context. State props (value, isOpen, onValueChange, onOpenChange) are managed by the root.
  • DatePicker.Trigger: Pressable trigger button that opens the calendar overlay. Supports variant and inherits invalid border styling from the root.
  • DatePicker.Value: Text display for the selected date label. Shows a placeholder when no date is selected.
  • DatePicker.TriggerIndicator: Indicator icon inside the trigger. Defaults to a calendar icon instead of a chevron.
  • DatePicker.Portal: Portal wrapper that re-provides DatePicker context across the portal boundary.
  • DatePicker.Overlay: Backdrop overlay behind the calendar content.
  • DatePicker.Content: Content container for the calendar popup. Supports "popover", "dialog", and "bottom-sheet" presentations.
  • DatePicker.Calendar: Pre-wired Calendar root that commits the selected date, updates the trigger label, and closes the overlay on selection. Uses Calendar compound parts as children.

Usage

Basic Usage

The DatePicker uses a popover presentation by default. Pass Calendar compound parts as children of DatePicker.Calendar.

<DatePicker>
  <Label>Event date</Label>
  <DatePicker.Select>
    <DatePicker.Trigger>
      <DatePicker.Value />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content presentation="popover" width="trigger">
        <DatePicker.Calendar>
          <Calendar.Header>
            <Calendar.Heading />
            <Calendar.NavButton slot="previous" />
            <Calendar.NavButton slot="next" />
          </Calendar.Header>
          <Calendar.Grid>
            <Calendar.GridHeader>
              {(day) => <Calendar.HeaderCell day={day} />}
            </Calendar.GridHeader>
            <Calendar.GridBody>
              {(date) => <Calendar.Cell date={date} />}
            </Calendar.GridBody>
          </Calendar.Grid>
        </DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
</DatePicker>

Dialog Presentation

Display the calendar in a centered modal dialog.

<DatePicker>
  <Label>Event date</Label>
  <DatePicker.Select presentation="dialog">
    <DatePicker.Trigger>
      <DatePicker.Value />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content presentation="dialog">
        <DatePicker.Calendar>...</DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
</DatePicker>

Bottom Sheet Presentation

Display the calendar in a bottom sheet.

<DatePicker>
  <Label>Event date</Label>
  <DatePicker.Select presentation="bottom-sheet">
    <DatePicker.Trigger>
      <DatePicker.Value />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content presentation="bottom-sheet">
        <DatePicker.Calendar>...</DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
</DatePicker>

Display Format

Configure how the selected date is displayed in the trigger using dateDisplayFormat.

<DatePicker dateDisplayFormat="short">
  <Label>Short format</Label>
  <DatePicker.Select>
    <DatePicker.Trigger>
      <DatePicker.Value />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content presentation="popover" width="trigger">
        <DatePicker.Calendar>...</DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
</DatePicker>

Custom Format Function

Override the display label entirely with formatDate.

function formatSpanishDate(date: CalendarDate): string {
  return new Intl.DateTimeFormat('es-ES', {
    weekday: 'long',
    day: 'numeric',
    month: 'long',
    year: 'numeric',
  }).format(date.toDate(getLocalTimeZone()));
}

<DatePicker formatDate={formatSpanishDate} locale="es-ES">
  <Label>Custom format</Label>
  <DatePicker.Select>
    <DatePicker.Trigger>
      <DatePicker.Value />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content presentation="popover" width="trigger">
        <DatePicker.Calendar>...</DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
</DatePicker>;

Field States

Use root props for required, invalid, and disabled states.

<DatePicker isRequired>
  <Label>Deadline</Label>
  <DatePicker.Select>
    <DatePicker.Trigger>
      <DatePicker.Value placeholder="Select a deadline" />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content presentation="popover" width="trigger">
        <DatePicker.Calendar>...</DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
  <Description>Required for the project timeline.</Description>
</DatePicker>

Invalid State with FieldError

Combine isInvalid with FieldError to display validation messages. The trigger shows a danger border.

<DatePicker isInvalid>
  <Label>Ship date</Label>
  <DatePicker.Select>
    <DatePicker.Trigger>
      <DatePicker.Value />
      <DatePicker.TriggerIndicator />
    </DatePicker.Trigger>
    <DatePicker.Portal>
      <DatePicker.Overlay />
      <DatePicker.Content presentation="popover" width="trigger">
        <DatePicker.Calendar>...</DatePicker.Calendar>
      </DatePicker.Content>
    </DatePicker.Portal>
  </DatePicker.Select>
  <Description hideOnInvalid>Must be a business day.</Description>
  <FieldError>Please select a valid ship date.</FieldError>
</DatePicker>

With Year Picker

Use Calendar.YearPickerTrigger inside DatePicker.Calendar to add a year picker overlay.

<DatePicker.Calendar>
  <Calendar.Header>
    <Calendar.YearPickerTrigger>
      <Calendar.YearPickerTriggerHeading />
      <Calendar.YearPickerTriggerIndicator />
    </Calendar.YearPickerTrigger>
    <Calendar.NavButton slot="previous" />
    <Calendar.NavButton slot="next" />
  </Calendar.Header>
  <Calendar.Grid>
    <Calendar.GridHeader>
      {(day) => <Calendar.HeaderCell day={day} />}
    </Calendar.GridHeader>
    <Calendar.GridBody>
      {(date) => <Calendar.Cell date={date} />}
    </Calendar.GridBody>
  </Calendar.Grid>
  <Calendar.YearPickerGrid>
    <Calendar.YearPickerGridBody>
      {({ year, isSelected }) => (
        <Calendar.YearPickerCell year={year} isSelected={isSelected} />
      )}
    </Calendar.YearPickerGridBody>
  </Calendar.YearPickerGrid>
</DatePicker.Calendar>

Example

import type { CalendarDate } from '@internationalized/date';
import { getLocalTimeZone } from '@internationalized/date';
import { Description, FieldError, Label } from 'heroui-native';
import { Calendar, DatePicker } from 'heroui-native-pro';
import { View } from 'react-native';

function formatSpanishDate(date: CalendarDate): string {
  return new Intl.DateTimeFormat('es-ES', {
    weekday: 'long',
    day: 'numeric',
    month: 'long',
    year: 'numeric',
  }).format(date.toDate(getLocalTimeZone()));
}

export default function DatePickerExample() {
  return (
    <View className="flex-1 justify-center px-5 gap-12">
      <DatePicker formatDate={formatSpanishDate} locale="es-ES">
        <Label>Fecha del evento</Label>
        <DatePicker.Select>
          <DatePicker.Trigger>
            <DatePicker.Value />
            <DatePicker.TriggerIndicator />
          </DatePicker.Trigger>
          <DatePicker.Portal>
            <DatePicker.Overlay />
            <DatePicker.Content presentation="popover" width="trigger">
              <DatePicker.Calendar>
                <Calendar.Header>
                  <Calendar.YearPickerTrigger>
                    <Calendar.YearPickerTriggerHeading />
                    <Calendar.YearPickerTriggerIndicator />
                  </Calendar.YearPickerTrigger>
                  <Calendar.NavButton slot="previous" />
                  <Calendar.NavButton slot="next" />
                </Calendar.Header>
                <Calendar.Grid>
                  <Calendar.GridHeader>
                    {(day) => <Calendar.HeaderCell day={day} />}
                  </Calendar.GridHeader>
                  <Calendar.GridBody>
                    {(date) => <Calendar.Cell date={date} />}
                  </Calendar.GridBody>
                </Calendar.Grid>
                <Calendar.YearPickerGrid>
                  <Calendar.YearPickerGridBody>
                    {({ year, isSelected }) => (
                      <Calendar.YearPickerCell
                        year={year}
                        isSelected={isSelected}
                      />
                    )}
                  </Calendar.YearPickerGridBody>
                </Calendar.YearPickerGrid>
              </DatePicker.Calendar>
            </DatePicker.Content>
          </DatePicker.Portal>
        </DatePicker.Select>
      </DatePicker>

      <DatePicker isInvalid>
        <Label>Ship date</Label>
        <DatePicker.Select>
          <DatePicker.Trigger>
            <DatePicker.Value />
            <DatePicker.TriggerIndicator />
          </DatePicker.Trigger>
          <DatePicker.Portal>
            <DatePicker.Overlay />
            <DatePicker.Content presentation="popover" width="trigger">
              <DatePicker.Calendar>
                <Calendar.Header>
                  <Calendar.Heading />
                  <Calendar.NavButton slot="previous" />
                  <Calendar.NavButton slot="next" />
                </Calendar.Header>
                <Calendar.Grid>
                  <Calendar.GridHeader>
                    {(day) => <Calendar.HeaderCell day={day} />}
                  </Calendar.GridHeader>
                  <Calendar.GridBody>
                    {(date) => <Calendar.Cell date={date} />}
                  </Calendar.GridBody>
                </Calendar.Grid>
              </DatePicker.Calendar>
            </DatePicker.Content>
          </DatePicker.Portal>
        </DatePicker.Select>
        <Description hideOnInvalid>Must be a business day.</Description>
        <FieldError>Please select a valid ship date.</FieldError>
      </DatePicker>
    </View>
  );
}

API Reference

DatePicker

proptypedefaultdescription
childrenReact.ReactNode-Children elements (Label, DatePicker.Select, Description, FieldError)
valueDatePickerOption-Controlled selected option
defaultValueDatePickerOption-Default selected option for uncontrolled usage
isDisabledbooleanfalseWhether the entire field is disabled
isInvalidbooleanfalseWhether the field is in an invalid state
isRequiredbooleanfalseWhether the field is required
isOpenboolean-Controlled open state of the calendar overlay
isDefaultOpenboolean-Initial open state for uncontrolled usage
dateDisplayFormatDatePickerDateDisplayFormat'medium'Preset date label format; ignored when formatDate is set
localestring-BCP 47 locale for label formatting and calendar grid
formatDate(date: CalendarDate) => string-Custom formatter that overrides dateDisplayFormat and locale for labels
classNamestring-Additional CSS classes for the root container
animationAnimationRootDisableAll-Animation configuration for the date picker subtree
onValueChange(value: DatePickerOption | undefined) => void-Handler called when the selected option changes
onOpenChange(open: boolean) => void-Handler called when the open state changes
...ViewPropsViewProps-All standard React Native View props are supported

DatePickerOption

propertytypedescription
valuestringISO date string (e.g. "2026-06-15")
labelstringDisplay string shown in the trigger (e.g. "Jun 15, 2026")

DatePickerDateDisplayFormat

Built-in date label presets (maps to Intl.DateTimeFormat dateStyle):

  • 'short' — e.g. "6/15/26"
  • 'medium' — e.g. "Jun 15, 2026" (default)
  • 'long' — e.g. "June 15, 2026"
  • 'full' — e.g. "Monday, June 15, 2026"

AnimationRootDisableAll

Animation configuration for the DatePicker root. Can be:

  • "disable-all": Disable all animations including children (cascades down)
  • undefined: Use default animations

DatePicker.Select

proptypedefaultdescription
childrenReact.ReactNode-Select content (Trigger, Portal)
isDisabledboolean-Overrides the root isDisabled when set
presentation'popover' | 'dialog' | 'bottom-sheet''popover'Presentation mode for the select content
classNamestring-Additional CSS classes
...ViewPropsViewProps-All standard React Native View props are supported

DatePicker.Trigger

proptypedefaultdescription
childrenReact.ReactNode-Trigger content (Value, TriggerIndicator)
variant'default' | 'unstyled''default'Trigger styling variant
isDisabledboolean-Whether the trigger is disabled
isInvalidboolean-When true, applies a danger border; inherits from root when omitted
classNamestring-Additional CSS classes for the trigger
...PressablePropsPressableProps-All standard React Native Pressable props are supported

DatePicker.Value

proptypedefaultdescription
placeholderstring'Choose a date'Text shown when no date is selected
classNamestring-Additional CSS classes for the value text
...TextPropsTextProps-All standard React Native Text props are supported

DatePicker.TriggerIndicator

proptypedefaultdescription
childrenReact.ReactNode-Custom indicator content; defaults to a calendar icon when omitted
iconPropsSelectTriggerIndicatorIconProps-Overrides for the default icon
isAnimatedStyleActivebooleanfalseWhether animated rotation styles are applied
classNamestring-Additional CSS classes for the indicator container
animationSelectTriggerIndicatorAnimationfalseRotation animation configuration; disabled by default for calendar icon
...ViewPropsViewProps-All standard React Native View props are supported

SelectTriggerIndicatorIconProps

proptypedefaultdescription
sizenumber16Icon size in logical pixels
colorstringmutedIcon fill color

DatePicker.Portal

proptypedefaultdescription
childrenReact.ReactNode-Portal content (Overlay, Content)
hostNamestring-Optional name of the host element for the portal
disableFullWindowOverlaybooleanfalseUse a regular View instead of FullWindowOverlay on iOS
unstable_accessibilityContainerViewIsModalbooleanfalseControls whether VoiceOver treats the overlay as a modal container (iOS)
classNamestring-Additional CSS classes for the portal container

DatePicker.Overlay

proptypedefaultdescription
closeOnPressbooleantrueWhether to close the picker when the overlay is pressed
isAnimatedStyleActivebooleantrueWhether animated opacity styles are applied
classNamestring-Additional CSS classes for the overlay backdrop
animationSelectOverlayAnimation-Opacity animation configuration
...PressablePropsPressableProps-All standard React Native Pressable props are supported

DatePicker.Content

The content component is a union type based on the presentation prop.

Popover presentation

proptypedefaultdescription
childrenReact.ReactNode-Content (DatePicker.Calendar)
presentation'popover'-Popover presentation mode
width'content-fit' | 'trigger' | 'full' | number'content-fit'Content width sizing strategy
classNamestring-Additional CSS classes for the content container
animationSelectContentPopoverAnimation-Keyframe animation configuration for entering/exiting
...ViewPropsViewProps-All standard React Native View props are supported

Dialog presentation

proptypedefaultdescription
childrenReact.ReactNode-Content (DatePicker.Calendar)
presentation'dialog'-Dialog presentation mode
isSwipeablebooleantrueWhether the dialog can be swiped to dismiss
classNamestring-Additional CSS classes for the content container
animationSelectContentAnimation-Keyframe animation configuration for scale/opacity
...ViewPropsViewProps-All standard React Native View props are supported

Bottom sheet presentation

proptypedefaultdescription
childrenReact.ReactNode-Content (DatePicker.Calendar)
presentation'bottom-sheet'-Bottom sheet presentation mode
...BottomSheetPropsBottomSheetProps-All @gorhom/bottom-sheet props are supported

DatePicker.Calendar

proptypedefaultdescription
childrenReact.ReactNode-Calendar compound parts (Calendar.Header, Calendar.Grid, etc.)
valueDateValue | null-Overrides the calendar value derived from the root selection
localestring-Overrides the root locale for the calendar grid
accessibilityLabelstring'Pick a date'Screen reader label for the calendar container
onChange(date: DateValue) => void-Side-effect handler called before the default commit behavior
...CalendarPropsCalendarProps-All Calendar root props are supported (minValue, maxValue, etc.)

Hooks

useDatePicker

Hook to access the DatePicker context. Must be used within a DatePicker component.

import { useDatePicker } from 'heroui-native-pro';

const { value, commitDate, isOpen, formatLabel } = useDatePicker();

Returns: DatePickerContextValue

propertytypedescription
valueDatePickerOption | undefinedCurrent select option (ISO string + display label)
onValueChange(next: DatePickerOption | undefined) => voidUpdate the selected option
isOpenbooleanWhether the calendar overlay is open
onOpenChange(open: boolean) => voidUpdate the open state
commitDate(date: CalendarDate) => voidCommit a date: updates the option, formats the label, closes the overlay
formatLabel(date: CalendarDate) => stringFormat a date using root dateDisplayFormat / locale / formatDate
isDisabledRootbooleanWhether the root is disabled
localestring | undefinedRoot locale forwarded to DatePicker.Calendar

On this page