A single-date picker that combines a trigger field with a calendar popup for selecting dates.
import { DatePicker } from 'heroui-native-pro' ;
< 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.
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 >
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 >
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 >
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 >
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 >;
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 >
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 >
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 >
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 >
);
}
prop type default description 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
property type description valuestringISO date string (e.g. "2026-06-15") labelstringDisplay string shown in the trigger (e.g. "Jun 15, 2026")
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"
Animation configuration for the DatePicker root. Can be:
"disable-all": Disable all animations including children (cascades down)
undefined: Use default animations
prop type default description 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
prop type default description 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
prop type default description 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
prop type default description 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
prop type default description sizenumber16Icon size in logical pixels colorstringmutedIcon fill color
prop type default description 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
prop type default description 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
The content component is a union type based on the presentation prop.
prop type default description 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
prop type default description 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
prop type default description childrenReact.ReactNode- Content (DatePicker.Calendar) presentation'bottom-sheet'- Bottom sheet presentation mode ...BottomSheetPropsBottomSheetProps- All @gorhom/bottom-sheet props are supported
prop type default description 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.)
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 ();
property type description 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