A date range picker that combines a trigger field with a range calendar popup for selecting start and end dates.
import { DateRangePicker } from 'heroui-native-pro' ;
< DateRangePicker >
< Label >...</ Label >
< DateRangePicker.Select >
< DateRangePicker.Trigger >
< DateRangePicker.Value />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content >
< DateRangePicker.Calendar >
< RangeCalendar.Header >...</ RangeCalendar.Header >
< RangeCalendar.Grid >...</ RangeCalendar.Grid >
</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
< Description >...</ Description >
</ DateRangePicker >
DateRangePicker : Root container that manages date range selection state, open state, display formatting, and form field context (for Label, Description, FieldError). Supports controlled and uncontrolled modes.
DateRangePicker.Select : Pre-wired Select root connected to the DateRangePicker context. State props (value, isOpen, onValueChange, onOpenChange) are managed by the root.
DateRangePicker.Trigger : Pressable trigger button that opens the calendar overlay. Supports variant and inherits invalid border styling from the root.
DateRangePicker.Value : Text display for the selected range label. Shows a placeholder when no range is selected.
DateRangePicker.TriggerIndicator : Indicator icon inside the trigger. Defaults to a calendar icon instead of a chevron.
DateRangePicker.Portal : Portal wrapper that re-provides DateRangePicker context across the portal boundary.
DateRangePicker.Overlay : Backdrop overlay behind the calendar content.
DateRangePicker.Content : Content container for the calendar popup. Supports "popover", "dialog", and "bottom-sheet" presentations.
DateRangePicker.Calendar : Pre-wired RangeCalendar root that commits a completed range, updates the trigger label, and closes the overlay after selection. Two taps are required to complete a range (start, then end). Uses RangeCalendar compound parts as children.
The DateRangePicker uses a popover presentation by default. Pass RangeCalendar compound parts as children of DateRangePicker.Calendar.
< DateRangePicker >
< Label >Trip dates</ Label >
< DateRangePicker.Select >
< DateRangePicker.Trigger >
< DateRangePicker.Value />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "popover" width = "trigger" >
< DateRangePicker.Calendar >
< RangeCalendar.Header >
< RangeCalendar.Heading />
< RangeCalendar.NavButton slot = "previous" />
< RangeCalendar.NavButton slot = "next" />
</ RangeCalendar.Header >
< RangeCalendar.Grid >
< RangeCalendar.GridHeader >
{( day ) => < RangeCalendar.HeaderCell day = {day} />}
</ RangeCalendar.GridHeader >
< RangeCalendar.GridBody >
{( date ) => < RangeCalendar.Cell date = {date} />}
</ RangeCalendar.GridBody >
</ RangeCalendar.Grid >
</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
</ DateRangePicker >
Display the range calendar in a centered modal dialog.
< DateRangePicker >
< Label >Trip dates</ Label >
< DateRangePicker.Select presentation = "dialog" >
< DateRangePicker.Trigger >
< DateRangePicker.Value />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "dialog" >
< DateRangePicker.Calendar >...</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
</ DateRangePicker >
Display the range calendar in a bottom sheet.
< DateRangePicker >
< Label >Trip dates</ Label >
< DateRangePicker.Select presentation = "bottom-sheet" >
< DateRangePicker.Trigger >
< DateRangePicker.Value />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "bottom-sheet" >
< DateRangePicker.Calendar >...</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
</ DateRangePicker >
Configure how the selected range is displayed in the trigger using dateDisplayFormat.
< DateRangePicker dateDisplayFormat = "long" >
< Label >Trip dates</ Label >
< DateRangePicker.Select >
< DateRangePicker.Trigger >
< DateRangePicker.Value />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "popover" width = "trigger" >
< DateRangePicker.Calendar >...</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
</ DateRangePicker >
Override the display label entirely with formatDateRange.
function formatSpanishRange ( start : CalendarDate , end : CalendarDate ) : string {
const fmt = new Intl. DateTimeFormat ( 'es-ES' , {
day: 'numeric' ,
month: 'long' ,
year: 'numeric' ,
});
const a = fmt. format (start. toDate ( getLocalTimeZone ()));
const b = fmt. format (end. toDate ( getLocalTimeZone ()));
if (start. compare (end) === 0 ) return a;
return `${ a } – ${ b }` ;
}
< DateRangePicker formatDateRange = {formatSpanishRange} locale = "es-ES" >
< Label >Custom range label</ Label >
< DateRangePicker.Select >
< DateRangePicker.Trigger >
< DateRangePicker.Value />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "popover" width = "trigger" >
< DateRangePicker.Calendar >...</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
< Description >Pick a start date, then an end date.</ Description >
</ DateRangePicker >;
Change the separator between formatted start and end dates in the trigger label.
< DateRangePicker rangeSeparator = "to" >
< Label >Stay</ Label >
< DateRangePicker.Select >
< DateRangePicker.Trigger >
< DateRangePicker.Value />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "popover" width = "trigger" >
< DateRangePicker.Calendar >...</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
</ DateRangePicker >
Use root props for required, invalid, and disabled states.
< DateRangePicker isRequired >
< Label >Travel dates</ Label >
< DateRangePicker.Select >
< DateRangePicker.Trigger >
< DateRangePicker.Value placeholder = "Select travel dates" />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "popover" width = "trigger" >
< DateRangePicker.Calendar >...</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
< Description >Required for booking confirmation.</ Description >
</ DateRangePicker >
import type { CalendarDate } from '@internationalized/date' ;
import { getLocalTimeZone } from '@internationalized/date' ;
import { Description, Label } from 'heroui-native' ;
import { DateRangePicker, RangeCalendar } from 'heroui-native-pro' ;
import { View } from 'react-native' ;
function formatSpanishDateRange (
start : CalendarDate ,
end : CalendarDate
) : string {
const fmt = new Intl. DateTimeFormat ( 'es-ES' , {
day: 'numeric' ,
month: 'long' ,
year: 'numeric' ,
});
const a = fmt. format (start. toDate ( getLocalTimeZone ()));
const b = fmt. format (end. toDate ( getLocalTimeZone ()));
if (start. compare (end) === 0 ) return a;
return `${ a } – ${ b }` ;
}
export default function DateRangePickerExample () {
return (
< View className = "flex-1 justify-center px-5 gap-12" >
< DateRangePicker formatDateRange = {formatSpanishDateRange} locale = "es-ES" >
< Label >Custom range label (es-ES)</ Label >
< DateRangePicker.Select >
< DateRangePicker.Trigger >
< DateRangePicker.Value className = "text-sm" numberOfLines = { 1 } />
< DateRangePicker.TriggerIndicator />
</ DateRangePicker.Trigger >
< DateRangePicker.Portal >
< DateRangePicker.Overlay />
< DateRangePicker.Content presentation = "popover" width = "trigger" >
< DateRangePicker.Calendar >
< RangeCalendar.Header >
< RangeCalendar.Heading />
< RangeCalendar.NavButton slot = "previous" />
< RangeCalendar.NavButton slot = "next" />
</ RangeCalendar.Header >
< RangeCalendar.Grid >
< RangeCalendar.GridHeader >
{( day ) => < RangeCalendar.HeaderCell day = {day} />}
</ RangeCalendar.GridHeader >
< RangeCalendar.GridBody >
{( date ) => < RangeCalendar.Cell date = {date} />}
</ RangeCalendar.GridBody >
</ RangeCalendar.Grid >
</ DateRangePicker.Calendar >
</ DateRangePicker.Content >
</ DateRangePicker.Portal >
</ DateRangePicker.Select >
< Description >Pick a start date, then an end date.</ Description >
</ DateRangePicker >
</ View >
);
}
prop type default description childrenReact.ReactNode- Children elements (Label, DateRangePicker.Select, Description, FieldError) valueDateRangePickerOption- Controlled selected option defaultValueDateRangePickerOption- 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 dateDisplayFormatDateRangePickerDateDisplayFormat'medium'Preset date label format; ignored when formatDateRange is set localestring- BCP 47 locale for label formatting and calendar grid formatDateRange(start: CalendarDate, end: CalendarDate) => string- Custom formatter that overrides dateDisplayFormat and locale for labels rangeSeparatorstring'–'Separator between start and end dates when using presets; same-day ranges collapse to a single date classNamestring- Additional CSS classes for the root container animationAnimationRootDisableAll- Animation configuration for the date range picker subtree onValueChange(value: DateRangePickerOption | 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 valuestringJSON string encoding start/end ISO dates (e.g. {"start":"2026-04-01","end":"2026-04-07"}) labelstringDisplay string shown in the trigger (e.g. "Apr 1, 2026 – Apr 7, 2026")
Built-in date label presets (maps to Intl.DateTimeFormat dateStyle):
'short' — e.g. "4/1/26 – 4/7/26"
'medium' — e.g. "Apr 1, 2026 – Apr 7, 2026" (default)
'long' — e.g. "April 1, 2026 – April 7, 2026"
'full' — e.g. "Wednesday, April 1, 2026 – Tuesday, April 7, 2026"
Animation configuration for the DateRangePicker 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 range'Text shown when no range 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 (DateRangePicker.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 (DateRangePicker.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 (DateRangePicker.Calendar) presentation'bottom-sheet'- Bottom sheet presentation mode ...BottomSheetPropsBottomSheetProps- All @gorhom/bottom-sheet props are supported
prop type default description childrenReact.ReactNode- RangeCalendar compound parts (RangeCalendar.Header, RangeCalendar.Grid, etc.) valueRangeValue<DateValue> | null- Overrides the calendar value derived from the root selection localestring- Overrides the root locale for the calendar grid accessibilityLabelstring'Pick a date range'Screen reader label for the calendar container onChange(value: RangeValue<DateValue> | null) => void- Side-effect handler called for range updates including null while restarting selection ...RangeCalendarPropsRangeCalendarProps- All RangeCalendar root props are supported (minValue, maxValue, allowsNonContiguousRanges, etc.)
Hook to access the DateRangePicker context. Must be used within a DateRangePicker component.
import { useDateRangePicker } from 'heroui-native-pro' ;
const { value , commitRange , isOpen , formatRangeLabel } = useDateRangePicker ();
property type description valueDateRangePickerOption | undefinedCurrent select option (JSON range string + display label) onValueChange(next: DateRangePickerOption | undefined) => voidUpdate the selected option isOpenbooleanWhether the calendar overlay is open onOpenChange(open: boolean) => voidUpdate the open state commitRange(range: RangeValue<CalendarDate>) => voidCommit a range: updates the option, formats the label, closes the overlay formatRangeLabel(start: CalendarDate, end: CalendarDate) => stringFormat a range using root dateDisplayFormat / locale / formatDateRange isDisabledRootbooleanWhether the root is disabled localestring | undefinedRoot locale forwarded to DateRangePicker.Calendar