TimePicker

Captures time value from the user

Usage

TimePicker component is an alternative to TimeInput that offers more features, it supports 24-hour and 12-hour formats, dropdown with hours, minutes and seconds, and more.

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return <TimePicker label="Enter time" />;
}

Controlled

TimePicker component value is a string in hh:mm:ss 24-hour format (for example 18:34:55). Empty string is used to represent no value. onChange function is called only when the entered value is valid. The input value is considered valid in the following cases:

  • All inputs are empty. In this case onChange is called with an empty string.
  • All inputs are filled. For example if withSeconds prop is set and the user entered 12:34:56, onChange will be called with 12:34:56. But if the user entered 12:34, onChange will not be called because seconds value is missing.
import { useState } from 'react';
import { TimePicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState('');
  return <TimePicker value={value} onChange={setValue} />;
}

With seconds

Set withSeconds prop to enable seconds input. Note that if this prop is used, onChange is not called until all inputs are filled – it is not possible to enter only hours and minutes.

::
import { TimePicker } from '@mantine/dates';

function Demo() {
  return <TimePicker label="Enter time" withSeconds />;
}

12-hour format

Set format="12h" to use 12-hour format. Note that onChange is called only when all inputs are filled including am/pm input.

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return <TimePicker label="Enter time" format="12h" />;
}

Change am/pm labels

To change am/pm labels use amPmLabels prop. Example of changing labels to Hindi:

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker label="Enter time" format="12h" amPmLabels={{ am: 'पूर्वाह्न', pm: 'अपराह्न' }} />
  );
}

Min and max values

Set min and max props to limit available time range:

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return <TimePicker label="Enter time" min="10:00" max="18:30" />;
}

With dropdown

Set withDropdown prop to display the dropdown with hours, minutes, seconds and am/pm selects. By default, the dropdown is visible when one of the inputs is focused.

::
::
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <>
      <TimePicker label="Enter time (24h format)" withSeconds withDropdown />
      <TimePicker label="Enter time (12h format)" withSeconds withDropdown format="12h" mt="md" />
    </>
  );
}

Hours/minutes/seconds step

Use hoursStep, minutesStep and secondsStep props to control step for each input. These props are used to control value by which the input is incremented or decremented when up/down arrow keys are pressed and to generate corresponding values range in the dropdown.

::
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      label="Enter time"
      withSeconds
      withDropdown
      hoursStep={1}
      minutesStep={5}
      secondsStep={10}
    />
  );
}

Control dropdown opened state

Use popoverProps to pass props down to the underlying Popover component:

:
import { useState } from 'react';
import { IconClock } from '@tabler/icons-react';
import { ActionIcon } from '@mantine/core';
import { TimePicker } from '@mantine/dates';

function Demo() {
  const [dropdownOpened, setDropdownOpened] = useState(false);
  const [value, setValue] = useState('');

  return (
    <TimePicker
      rightSection={
        <ActionIcon onClick={() => setDropdownOpened(true)} variant="default">
          <IconClock size={18} stroke={1.5} />
        </ActionIcon>
      }
      value={value}
      onChange={(val) => {
        setValue(val);
        if (value === '') {
          setDropdownOpened(false);
        }
      }}
      popoverProps={{
        opened: dropdownOpened,
        onChange: (_opened) => !_opened && setDropdownOpened(false),
      }}
    />
  );
}

Time presets

You can define time presets with presets prop. Presets are displayed in the dropdown and can be selected by clicking on them. Time values for presets should be in hh:mm:ss or hh:mm 24-hour time format. Presets display value is generated based on format, amPmLabels and withSeconds props.

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      label="Enter time"
      withDropdown
      presets={['12:30', '15:45', '18:00', '20:15', '22:30']}
    />
  );
}

Time presets groups

To group presets use an array of objects with label and values keys:

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      label="Enter time"
      withDropdown
      maxDropdownContentHeight={300}
      presets={[
        { label: 'Morning', values: ['06:00:00', '08:00:00', '10:00:00'] },
        { label: 'Afternoon', values: ['12:00:00', '14:00:00', '16:00:00'] },
        { label: 'Evening', values: ['18:00:00', '20:00:00', '22:00:00'] },
      ]}
    />
  );
}

Time presets range

If you need to generate a range of time values, use getTimeRange function exported from @mantine/dates package. The function accepts start, end time and interval in hh:mm:ss format.

:
import { getTimeRange, TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      label="Enter time"
      withDropdown
      presets={getTimeRange({ startTime: '06:00:00', endTime: '18:00:00', interval: '01:30:00' })}
    />
  );
}

Dropdown position

By default, the dropdown is displayed below the input if there is enough space; otherwise it is displayed above the input. You can change this behavior by setting position and middlewares props, which are passed down to the underlying Popover component.

Example of dropdown that is always displayed above the input:

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      label="Enter time"
      withDropdown
      popoverProps={{
        position: 'top-start',
        middlewares: { flip: false, shift: false },
      }}
    />
  );
}

Dropdown width

To change dropdown width, set width prop in comboboxProps. By default, dropdown width is adjusted to fit all content. Example of dropdown width set to the input width:

::
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      label="Enter time"
      withDropdown
      withSeconds
      format="12h"
      popoverProps={{
        width: 'target',
      }}
    />
  );
}

Paste events

By default, TimePicker handles only time in 24-hour format (for example 17:33:43 or 19:22) for paste events. With pasteSplit prop you can create a custom paste time parser:

::

Try pasting time in 12h format in any input. For example, try pasting 12:34 PM or 8:56:45 AM

import { Code, Text } from '@mantine/core';
import { TimePicker, TimePickerPasteSplit } from '@mantine/dates';

const re = /^(1[0-2]|0?[1-9]):[0-5][0-9](?::[0-5][0-9])?\s?(AM|PM)$/;

const customPasteSplit: TimePickerPasteSplit = ({ time }) => {
  if (!re.test(time)) {
    return { hours: null, minutes: null, seconds: null, amPm: null };
  }

  const [hours, minutes, second] = time.split(':').map((part) => part.replace(/AM|PM/g, ''));
  const isPm = time.toLowerCase().includes('pm');

  return {
    hours: typeof hours === 'string' ? Number(hours) : null,
    minutes: typeof minutes === 'string' ? Number(minutes) : null,
    seconds: typeof second === 'string' ? Number(second) : 0,
    amPm: isPm ? 'PM' : 'AM',
  };
};

function Demo() {
  return (
    <div>
      <TimePicker label="Paste time here" format="12h" withSeconds pasteSplit={customPasteSplit} />
      <Text mt="md">
        Try pasting time in 12h format in any input. For example, try pasting <Code>12:34 PM</Code>{' '}
        or <Code>8:56:45 AM</Code>
      </Text>
    </div>
  );
}

Clearable

Set clearable prop to display a clear button in the right section of the input. The clear button is visible when at least one of the fields has value.

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return <TimePicker label="Enter time" clearable defaultValue="12:34:44" />;
}

Disabled

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return <TimePicker label="Enter time" disabled />;
}

Read only

:
import { TimePicker } from '@mantine/dates';

function Demo() {
  return <TimePicker label="Enter time" defaultValue="12:45:33" readOnly />;
}

Input props

TimePicker component supports Input and Input.Wrapper components features and all div element props. TimePicker documentation does not include all features supported by the component – see Input documentation to learn about all available features.

Input description

:
Variant
Size
Radius
import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      withDropdown
      label="Input label"
      description="Input description"
    />
  );
}

Get refs of inner inputs

Use hoursRef, minutesRef, secondsRef and amPmRef props to get refs of inner inputs:

import { useRef } from 'react';
import { TimePicker } from '@mantine/dates';

function Demo() {
  const hoursRef = useRef<HTMLInputElement>(null);
  const minutesRef = useRef<HTMLInputElement>(null);
  const secondsRef = useRef<HTMLInputElement>(null);
  const amPmRef = useRef<HTMLSelectElement>(null);

  return (
    <TimePicker
      hoursRef={hoursRef}
      minutesRef={minutesRef}
      secondsRef={secondsRef}
      amPmRef={amPmRef}
    />
  );
}

onFocus and onBlur events

onFocus and onBlur events are called when the first input is focused and the last input is blurred:

import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      onFocus={() => console.log('Focused')}
      onBlur={() => console.log('Blurred')}
    />
  );
}

Accessibility

Set aria labels for hours, minutes, seconds and am/pm inputs and clear button with corresponding props:

import { TimePicker } from '@mantine/dates';

function Demo() {
  return (
    <TimePicker
      hoursInputLabel="Hours"
      minutesInputLabel="Minutes"
      secondsInputLabel="Seconds"
      amPmInputLabel="AM/PM"
      clearButtonProps={{ 'aria-label': 'Clear time' }}
    />
  );
}

Keyboard interactions:

KeyDescription
ArrowDownDecrements current value by step
ArrowUpIncrements current value by step
HomeSets current value to min possible value
EndSets current value to max possible value
BackspaceClears current value
ArrowRightMoves focus to the next input
ArrowLeftMoves focus to the previous input