TimePickerNew

A time picker that combines a trigger field with a scrollable wheel popup for selecting an hour, minute, and optional AM/PM period.

TimePicker uses @internationalized/date for time manipulation (Time, locale-aware formatting). The wheel exchanges a Time value internally, while the selected option stores an ISO time string. For full context on the time type exposed through formatTime, read the @internationalized/date docs alongside this page.

Import

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

Anatomy

<TimePicker>
  <Label>...</Label>
  <TimePicker.Select>
    <TimePicker.Trigger>
      <TimePicker.Value />
      <TimePicker.TriggerIndicator />
    </TimePicker.Trigger>
    <TimePicker.Portal>
      <TimePicker.Overlay />
      <TimePicker.Content>
        <TimePicker.Wheel>
          <TimePicker.WheelHour />
          <TimePicker.WheelMinute />
          <TimePicker.WheelPeriod />
          <TimePicker.WheelIndicator />
          <TimePicker.WheelMask />
        </TimePicker.Wheel>
      </TimePicker.Content>
    </TimePicker.Portal>
  </TimePicker.Select>
  <Description>...</Description>
</TimePicker>
  • TimePicker: Root container that manages time selection state, open state, label formatting, and form field context (for Label, Description, FieldError). Supports controlled and uncontrolled modes.
  • TimePicker.Select: Pre-wired Select root connected to the TimePicker context. State props (value, isOpen, onValueChange, onOpenChange) are managed by the root. Always single selection mode.
  • TimePicker.Trigger: Pressable trigger button that opens the wheel overlay. Inherits invalid border styling from the root.
  • TimePicker.Value: Text display for the selected time label. Shows a placeholder when no time is selected.
  • TimePicker.TriggerIndicator: Indicator icon inside the trigger. Defaults to a clock icon instead of a chevron.
  • TimePicker.Portal: Portal wrapper that re-provides TimePicker context across the portal boundary.
  • TimePicker.Overlay: Backdrop overlay behind the wheel content.
  • TimePicker.Content: Content container for the wheel popup. Supports "popover", "dialog", and "bottom-sheet" presentations. Dialog swipe-to-dismiss is always disabled, and the bottom sheet defaults to no pan-down-to-close.
  • TimePicker.Wheel: Pre-wired wheel time selector that commits the selected time live on scroll and updates the trigger label while the surface stays open. Renders the default wheel parts when no children are passed.
  • TimePicker.WheelHour: Hour column.
  • TimePicker.WheelMinute: Minute column.
  • TimePicker.WheelPeriod: AM/PM column. Rendered by default only in 12-hour mode.
  • TimePicker.WheelIndicator: Shared selection band spanning every column.
  • TimePicker.WheelMask: Top / bottom fade overlays. Defaults its gradient color to the overlay surface so it blends with the popup background.

Usage

Basic Usage

The TimePicker uses a popover presentation by default. Pass TimePicker.Wheel with no children to render the default hour, minute, period, indicator, and mask parts.

<TimePicker>
  <Label>Reminder</Label>
  <TimePicker.Select>
    <TimePicker.Trigger>
      <TimePicker.Value />
      <TimePicker.TriggerIndicator />
    </TimePicker.Trigger>
    <TimePicker.Portal>
      <TimePicker.Overlay />
      <TimePicker.Content presentation="popover" width="trigger">
        <TimePicker.Wheel />
      </TimePicker.Content>
    </TimePicker.Portal>
  </TimePicker.Select>
</TimePicker>

Dialog Presentation

Display the wheel in a centered modal dialog.

<TimePicker>
  <Label>Reminder</Label>
  <TimePicker.Select presentation="dialog">
    <TimePicker.Trigger>
      <TimePicker.Value />
      <TimePicker.TriggerIndicator />
    </TimePicker.Trigger>
    <TimePicker.Portal>
      <TimePicker.Overlay />
      <TimePicker.Content presentation="dialog">
        <TimePicker.Wheel />
      </TimePicker.Content>
    </TimePicker.Portal>
  </TimePicker.Select>
</TimePicker>

Bottom Sheet Presentation

Display the wheel in a bottom sheet.

<TimePicker>
  <Label>Reminder</Label>
  <TimePicker.Select presentation="bottom-sheet">
    <TimePicker.Trigger>
      <TimePicker.Value />
      <TimePicker.TriggerIndicator />
    </TimePicker.Trigger>
    <TimePicker.Portal>
      <TimePicker.Overlay />
      <TimePicker.Content presentation="bottom-sheet">
        <TimePicker.Wheel />
      </TimePicker.Content>
    </TimePicker.Portal>
  </TimePicker.Select>
</TimePicker>

Hour Format and Minute Interval

Use hourFormat to switch between 12-hour and 24-hour mode, and minuteInterval to control the step between minute options. In 24-hour mode the AM/PM column is omitted.

<TimePicker hourFormat={24} minuteInterval={5} locale="en-GB">
  <Label>Departure</Label>
  <TimePicker.Select>
    <TimePicker.Trigger>
      <TimePicker.Value placeholder="Select a time" />
      <TimePicker.TriggerIndicator />
    </TimePicker.Trigger>
    <TimePicker.Portal>
      <TimePicker.Overlay />
      <TimePicker.Content presentation="popover" width="trigger">
        <TimePicker.Wheel />
      </TimePicker.Content>
    </TimePicker.Portal>
  </TimePicker.Select>
</TimePicker>

Custom Format Function

Override the trigger label entirely with formatTime.

function formatCompactTime(time: Time): string {
  const hour12 = time.hour % 12 === 0 ? 12 : time.hour % 12;
  const minute = String(time.minute).padStart(2, '0');
  const marker = time.hour < 12 ? 'a.m.' : 'p.m.';
  return `${hour12}:${minute} ${marker}`;
}

<TimePicker formatTime={formatCompactTime}>
  <Label>Custom format</Label>
  <TimePicker.Select>
    <TimePicker.Trigger>
      <TimePicker.Value />
      <TimePicker.TriggerIndicator />
    </TimePicker.Trigger>
    <TimePicker.Portal>
      <TimePicker.Overlay />
      <TimePicker.Content presentation="popover" width="trigger">
        <TimePicker.Wheel />
      </TimePicker.Content>
    </TimePicker.Portal>
  </TimePicker.Select>
</TimePicker>;

Field States

Use root props for required, invalid, and disabled states. Combine isInvalid with FieldError to display validation messages; the trigger shows a danger border.

<TimePicker isInvalid>
  <Label>Cutoff</Label>
  <TimePicker.Select>
    <TimePicker.Trigger>
      <TimePicker.Value />
      <TimePicker.TriggerIndicator />
    </TimePicker.Trigger>
    <TimePicker.Portal>
      <TimePicker.Overlay />
      <TimePicker.Content presentation="popover" width="trigger">
        <TimePicker.Wheel />
      </TimePicker.Content>
    </TimePicker.Portal>
  </TimePicker.Select>
  <Description hideOnInvalid>Must be during business hours.</Description>
  <FieldError>Please select a valid cutoff time.</FieldError>
</TimePicker>

Example

import type { Time } from '@internationalized/date';
import { Description, FieldError, Label } from 'heroui-native';
import { TimePicker } from 'heroui-native-pro';
import { View } from 'react-native';

function formatCompactTime(time: Time): string {
  const hour12 = time.hour % 12 === 0 ? 12 : time.hour % 12;
  const minute = String(time.minute).padStart(2, '0');
  const marker = time.hour < 12 ? 'a.m.' : 'p.m.';
  return `${hour12}:${minute} ${marker}`;
}

export default function TimePickerExample() {
  return (
    <View className="flex-1 justify-center px-5 gap-12">
      <TimePicker formatTime={formatCompactTime}>
        <Label>Reminder</Label>
        <TimePicker.Select>
          <TimePicker.Trigger>
            <TimePicker.Value placeholder="Pick a reminder time" />
            <TimePicker.TriggerIndicator />
          </TimePicker.Trigger>
          <TimePicker.Portal>
            <TimePicker.Overlay />
            <TimePicker.Content
              presentation="popover"
              width="trigger"
              className="items-center justify-center"
            >
              <TimePicker.Wheel />
            </TimePicker.Content>
          </TimePicker.Portal>
        </TimePicker.Select>
        <Description>Required to schedule the notification.</Description>
      </TimePicker>

      <TimePicker isInvalid hourFormat={24} minuteInterval={5}>
        <Label>Cutoff</Label>
        <TimePicker.Select>
          <TimePicker.Trigger>
            <TimePicker.Value />
            <TimePicker.TriggerIndicator />
          </TimePicker.Trigger>
          <TimePicker.Portal>
            <TimePicker.Overlay />
            <TimePicker.Content
              presentation="popover"
              width="trigger"
              className="items-center justify-center"
            >
              <TimePicker.Wheel />
            </TimePicker.Content>
          </TimePicker.Portal>
        </TimePicker.Select>
        <Description hideOnInvalid>Must be during business hours.</Description>
        <FieldError>Please select a valid cutoff time.</FieldError>
      </TimePicker>
    </View>
  );
}

You can find more examples in the GitHub repository.

API Reference

TimePicker

proptypedefaultdescription
childrenReact.ReactNode-Children elements (Label, TimePicker.Select, Description, FieldError)
valueTimePickerOption-Controlled selected option
defaultValueTimePickerOption-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 wheel overlay
isDefaultOpenboolean-Initial open state for uncontrolled usage
hourFormatWheelTimePickerHourFormat12Hour display mode; 12 adds an AM/PM marker, 24 omits it
minuteIntervalnumber1Step between consecutive minute options
timeDisplayFormatTimePickerTimeDisplayFormat'short'Preset time label format; ignored when formatTime is set
localestring-BCP 47 locale for label formatting and the wheel's AM/PM labels
formatTime(time: Time) => string-Custom formatter that overrides timeDisplayFormat, hourFormat, locale
classNamestring-Additional CSS classes for the root container
animationAnimationRootDisableAll-Animation configuration for the time picker subtree
onValueChange(value: TimePickerOption | 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

TimePickerOption

propertytypedescription
valuestringISO time string (e.g. "14:30:00")
labelstringDisplay string shown in the trigger (e.g. "2:30 PM")

TimePickerTimeDisplayFormat

Built-in time label presets:

  • 'short' — hour and minute only (e.g. "2:30 PM" / "14:30") (default)
  • 'medium' — includes seconds (e.g. "2:30:00 PM")

WheelTimePickerHourFormat

Hour display mode for the wheel and label formatting:

  • 12 — twelve-hour clock with an AM/PM period column (default)
  • 24 — twenty-four-hour clock without a period column

AnimationRootDisableAll

Animation configuration for the TimePicker root. Can be:

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

TimePicker.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

TimePicker.Trigger

proptypedefaultdescription
childrenReact.ReactNode-Trigger content (Value, TriggerIndicator)
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

TimePicker.Value

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

TimePicker.TriggerIndicator

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

SelectTriggerIndicatorIconProps

proptypedefaultdescription
sizenumber16Icon size in logical pixels
colorstringmutedIcon fill color

TimePicker.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

TimePicker.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

TimePicker.Content

The content component is a union type based on the presentation prop. The dialog isSwipeable prop is removed — TimePicker always disables dialog swipe-to-dismiss, and the bottom sheet defaults to no pan-down-to-close.

Popover presentation

proptypedefaultdescription
childrenReact.ReactNode-Content (TimePicker.Wheel)
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 (TimePicker.Wheel)
presentation'dialog'-Dialog presentation mode
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 (TimePicker.Wheel)
presentation'bottom-sheet'-Bottom sheet presentation mode
...BottomSheetPropsBottomSheetProps-All @gorhom/bottom-sheet props are supported

TimePicker.Wheel

Wired from TimePicker context; value, defaultValue, and onValueChange are managed by the root. Each scroll commits the selected option (formatted label + select value) live while the surface stays open. When children are omitted, the default wheel parts are rendered (period column only in 12-hour mode).

proptypedefaultdescription
childrenReact.ReactNode-Wheel parts; defaults to Hour, Minute, Period (12h), Indicator, and Mask
hourFormatWheelTimePickerHourFormatroot valueOverrides the root hour display mode for the wheel
minuteIntervalnumberroot valueOverrides the root step between minute options
itemHeightnumber44Pixel height of a single row, shared by all columns
visibleCountnumber5Number of visible rows, shared by all columns. Must be odd
isDisabledbooleanfalseDisables interaction for the whole wheel
localestringroot valueOverrides the root locale for the wheel's AM/PM labels
classNamestring-Additional CSS classes for the wheel container
animationWheelTimePickerRootAnimation-Animation configuration; cascades disable-all to the columns
...ViewPropsOmit<ViewProps, 'children'>-All standard React Native View props are supported

TimePicker.WheelHour

Hour column. The underlying name and items are owned by the wheel so the stored value stays correct.

proptypedefaultdescription
isDisabledbooleanfalseDisables interaction for this column
classNamestring-Additional CSS classes for the column container
classNamesElementSlots<WheelPickerRootSlots>-Additional CSS classes for individual column slots
stylesWheelPickerRootStyles-Inline styles for individual column slots
renderItemWheelPickerRenderItem<number>-Custom row renderer; defaults to a WheelPicker.ItemLabel
animationWheelPickerRootAnimation-Per-item opacity / scale interpolation configuration
...ViewPropsOmit<ViewProps, 'children'>-All standard React Native View props are supported

TimePicker.WheelMinute

Minute column. Same props as TimePicker.WheelHour; the underlying name and items are owned by the wheel.

TimePicker.WheelPeriod

AM/PM column. Same props as TimePicker.WheelHour; the underlying name and items are owned by the wheel. Rendered by default only in 12-hour mode.

TimePicker.WheelIndicator

Shared selection band spanning every column.

proptypedefaultdescription
childrenReact.ReactNode-Optional content rendered inside the highlight slot
classNamestring-Additional CSS classes for the indicator container
classNamesElementSlots<WheelPickerGroupIndicatorSlots>-Additional CSS classes for individual indicator slots
stylesPartial<Record<WheelPickerGroupIndicatorSlots, ViewStyle>>-Inline styles for individual indicator slots
...ViewPropsViewProps-All standard React Native View props are supported

ElementSlots<WheelPickerGroupIndicatorSlots>

slotdescription
wrapperAbsolutely-positioned band centered on the wheel viewport
highlightFilled rectangle rendered inside the wrapper

TimePicker.WheelMask

Top / bottom fade overlays. When color is omitted it defaults to the Select overlay surface color so the gradient blends with the popup background.

proptypedefaultdescription
colorstringoverlay surfaceSolid color the gradient fades from. Accepts any RN color string
heightnumber | string"100%"Height of each mask half. number = raw pixels; percentage scales the default fade height (((visibleCount - 1) / 4) * itemHeight)
classNamestring-Additional CSS classes applied to both mask halves
classNamesElementSlots<WheelPickerGroupMaskSlots>-Additional CSS classes for individual mask slots
stylesPartial<Record<WheelPickerGroupMaskSlots, ViewStyle>>-Inline styles for individual mask slots
...ViewPropsOmit<ViewProps, 'children'>-All standard React Native View props are supported

ElementSlots<WheelPickerGroupMaskSlots>

slotdescription
topTop fade overlay
bottomBottom fade overlay

Hooks

useTimePicker

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

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

const { value, commitTime, isOpen, formatLabel } = useTimePicker();

Returns: TimePickerContextValue

propertytypedescription
valueTimePickerOption | undefinedCurrent select option (ISO time string + display label)
onValueChange(next: TimePickerOption | undefined) => voidUpdate the selected option
isOpenbooleanWhether the wheel overlay is open
onOpenChange(open: boolean) => voidUpdate the open state
commitTime(time: Time, options?: TimePickerCommitOptions) => voidCommit a time: updates the option, formats the label, and closes unless options.close is false
formatLabel(time: Time) => stringFormat a time using root timeDisplayFormat / hourFormat / locale / formatTime
hourFormatWheelTimePickerHourFormatRoot hour format forwarded to TimePicker.Wheel
minuteIntervalnumberRoot minute interval forwarded to TimePicker.Wheel
localestring | undefinedRoot locale forwarded to TimePicker.Wheel
isDisabledRootbooleanWhether the root is disabled

TimePickerCommitOptions

propertytypedefaultdescription
closebooleantrueWhether to close the select surface after committing

On this page