React Time Input Component

Time Input

CoreUI PRO
This component is part of CoreUI PRO – a powerful UI library with over 250 components and 25+ templates, designed to help you build modern, responsive apps faster. Fully compatible with Angular, Bootstrap, React.js, and Vue.js.

Create React time fields with a section-based input mask. Users type the hour, minutes, and seconds in separate sections with automatic navigation and validation — like the native time input, but with full control over the format.

Available in Other JavaScript Frameworks

CoreUI React Time Input Component is also available for Bootstrap and Vue. Explore framework-specific implementations below:

Example

Added in v5.27.0

The React Time Input component renders a masked time field. The mask is split into hour, minute, and — depending on the locale — AM/PM sections. Click or focus a section and type, use arrow keys to adjust values, and the caret moves to the next section automatically.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-sm-0" sm={6} lg={5}>
        <CTimeInput label="Meeting time" locale="en-US" />
      </CCol>
      <CCol sm={6} lg={5}>
        <CTimeInput label="Meeting time" locale="en-US" defaultTime="14:30" />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-sm-0" sm={6} lg={5}>
        <CTimeInput label="Meeting time" locale="en-US" />
      </CCol>
      <CCol sm={6} lg={5}>
        <CTimeInput label="Meeting time" locale="en-US" defaultTime="14:30" />
      </CCol>
    </CRow>
  )
}

With form field

Wrap the control in <CFormField> to lay it out with its label and description, and to get validation feedback in the right place.

import React from 'react'
import { CFormField, CFormText } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputFormFieldExample = () => {
  return (
    <CFormField>
      <span className="form-label">Meeting time</span>
      <CTimeInput locale="en-US" name="meetingTime" />
      <CFormText>Local time, in your own time zone.</CFormText>
    </CFormField>
  )
}
import React from 'react'
import { CFormField, CFormText } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputFormFieldExample = () => {
  return (
    <CFormField>
      <span className="form-label">Meeting time</span>
      <CTimeInput locale="en-US" name="meetingTime" />
      <CFormText>Local time, in your own time zone.</CFormText>
    </CFormField>
  )
}

Formats

Set an explicit format with the format property: HH/H for the 23-hour cycle, hh/h for the 12-hour cycle, mm for minutes, ss for seconds, and A/a for the day period. Type a or p in the AM/PM section to switch it, or use the arrow keys.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputFormatsExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm" label="HH:mm" />
      </CCol>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm:ss" label="HH:mm:ss" />
      </CCol>
      <CCol lg={4}>
        <CTimeInput format="hh:mm A" label="hh:mm A" locale="en-US" />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputFormatsExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm" label="HH:mm" />
      </CCol>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm:ss" label="HH:mm:ss" />
      </CCol>
      <CCol lg={4}>
        <CTimeInput format="hh:mm A" label="hh:mm A" locale="en-US" />
      </CCol>
    </CRow>
  )
}

Locale

Without an explicit format, the hour cycle and layout follow the locale set via the locale property — en-US gets a 12-hour clock with an AM/PM section, pl-PL or de-DE a 24-hour one.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputLocalesExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput label="en-US" locale="en-US" />
      </CCol>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput label="pl-PL" locale="pl-PL" />
      </CCol>
      <CCol lg={4}>
        <CTimeInput label="de-DE" locale="de-DE" />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputLocalesExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput label="en-US" locale="en-US" />
      </CCol>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput label="pl-PL" locale="pl-PL" />
      </CCol>
      <CCol lg={4}>
        <CTimeInput label="de-DE" locale="de-DE" />
      </CCol>
    </CRow>
  )
}

Seconds

Without an explicit format, enable the seconds section with the seconds property.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputSecondsExample = () => {
  return (
    <CRow>
      <CCol lg={5}>
        <CTimeInput label="Time with seconds" seconds />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputSecondsExample = () => {
  return (
    <CRow>
      <CCol lg={5}>
        <CTimeInput label="Time with seconds" seconds />
      </CCol>
    </CRow>
  )
}

Min and max times

Constrain the selectable range with minDate and maxDate — time strings work here too. A completed time outside the range gets the .is-invalid class and the component reports null, and submits no time, until the value is corrected.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputMinMaxExample = () => {
  return (
    <CRow>
      <CCol lg={5}>
        <CTimeInput
          format="HH:mm"
          label="Business hours (09:00–17:00)"
          maxDate="17:00"
          minDate="09:00"
          defaultTime="09:30"
        />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputMinMaxExample = () => {
  return (
    <CRow>
      <CCol lg={5}>
        <CTimeInput
          format="HH:mm"
          label="Business hours (09:00–17:00)"
          maxDate="17:00"
          minDate="09:00"
          defaultTime="09:30"
        />
      </CCol>
    </CRow>
  )
}

Validation

The field takes its validation state the same way as the date input: a completed time outside minDate/maxDate makes it invalid whatever else is set, then validationState, then a validation that reported the field, and in a form with the validate property of <CForm> the :user-invalid state of its value field, with validate="valid" also its :user-valid state. A given state is a verdict on the time it was given for: when the user changes the time, or the form is reset, the component calls onValidationStateChange(undefined), while a change your code makes through time asks nothing. A given 'invalid' blocks the submit with the text of the linked message, or Invalid value. when there is none. The feedbackValid/feedbackInvalid texts render like for any other form control, and while the field is invalid the error, its own or one you render after the field, describes every section.

import React, { useState } from 'react'
import { CButton, CCol, CForm, CTimeInput } from '@coreui/react-pro'

export const TimeInputValidationExample = () => {
  const [roomState, setRoomState] = useState<string | undefined>('invalid')

  return (
    <CForm className="row g-4" noValidate validate>
      <CCol sm={6} lg={5}>
        <CTimeInput
          feedbackInvalid="Please provide a meeting time."
          format="HH:mm"
          label="Meeting time (required)"
          name="meeting"
          required
        />
      </CCol>
      <CCol sm={6} lg={5}>
        <CTimeInput
          defaultTime="12:30"
          feedback="The room is taken at this time."
          format="HH:mm"
          label="Room booking"
          name="room"
          onValidationStateChange={setRoomState}
          validationState={roomState}
        />
      </CCol>
      <CCol xs={12}>
        <CButton color="primary" type="submit">
          Submit
        </CButton>
      </CCol>
    </CForm>
  )
}
import React, { useState } from 'react'
import { CButton, CCol, CForm, CTimeInput } from '@coreui/react-pro'

export const TimeInputValidationExample = () => {
  const [roomState, setRoomState] = useState<string | undefined>('invalid')

  return (
    <CForm className="row g-4" noValidate validate>
      <CCol sm={6} lg={5}>
        <CTimeInput
          feedbackInvalid="Please provide a meeting time."
          format="HH:mm"
          label="Meeting time (required)"
          name="meeting"
          required
        />
      </CCol>
      <CCol sm={6} lg={5}>
        <CTimeInput
          defaultTime="12:30"
          feedback="The room is taken at this time."
          format="HH:mm"
          label="Room booking"
          name="room"
          onValidationStateChange={setRoomState}
          validationState={roomState}
        />
      </CCol>
      <CCol xs={12}>
        <CButton color="primary" type="submit">
          Submit
        </CButton>
      </CCol>
    </CForm>
  )
}

Floating labels

Use the floatingLabel property. When the field is empty and not focused, the mask placeholders are hidden so the label can rest inside the field; focusing the field floats the label and reveals the mask.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputFloatingLabelsExample = () => {
  return (
    <CRow>
      <CCol lg={5}>
        <CTimeInput floatingLabel="Meeting time" format="HH:mm" id="floatingTimeInput" />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputFloatingLabelsExample = () => {
  return (
    <CRow>
      <CCol lg={5}>
        <CTimeInput floatingLabel="Meeting time" format="HH:mm" id="floatingTimeInput" />
      </CCol>
    </CRow>
  )
}

Set floatingLabelAlways to keep the label always floating with the mask showing.

Sizing

The field renders as a .form-control, so the standard sizing works — set the size property to lg or sm.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputSizingExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm" label="Large" size="lg" />
      </CCol>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm" label="Default" />
      </CCol>
      <CCol lg={4}>
        <CTimeInput format="HH:mm" label="Small" size="sm" />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputSizingExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm" label="Large" size="lg" />
      </CCol>
      <CCol className="mb-4 mb-lg-0" lg={4}>
        <CTimeInput format="HH:mm" label="Default" />
      </CCol>
      <CCol lg={4}>
        <CTimeInput format="HH:mm" label="Small" size="sm" />
      </CCol>
    </CRow>
  )
}

Disabled and readonly

Set the disabled property to disable the field, or readOnly to make it focusable but non-editable.

import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputDisabledReadonlyExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-sm-0" sm={6} lg={5}>
        <CTimeInput disabled format="HH:mm" label="Disabled" defaultTime="14:30" />
      </CCol>
      <CCol sm={6} lg={5}>
        <CTimeInput format="HH:mm" label="Readonly" readOnly defaultTime="14:30" />
      </CCol>
    </CRow>
  )
}
import React from 'react'
import { CCol, CRow } from '@coreui/react'
import { CTimeInput } from '@coreui/react-pro'

export const TimeInputDisabledReadonlyExample = () => {
  return (
    <CRow>
      <CCol className="mb-4 mb-sm-0" sm={6} lg={5}>
        <CTimeInput disabled format="HH:mm" label="Disabled" defaultTime="14:30" />
      </CCol>
      <CCol sm={6} lg={5}>
        <CTimeInput format="HH:mm" label="Readonly" readOnly defaultTime="14:30" />
      </CCol>
    </CRow>
  )
}

Value semantics

The component reports a Date object anchored to 1970-01-01 — the same convention as the CoreUI time picker — so only the time part is meaningful. minDate/maxDate therefore constrain the time of day. A native reset of the form puts back the time the field started with and calls onTimeChange when that changes it; with time set it only asks for the first time through onTimeChange.

Accessibility

The time input shares the accessibility model of the date input: role="group" on the container, named by label, a role="spinbutton" with full ARIA value attributes per section, a single tab stop with roving focus, and inputmode hints for mobile keyboards. Clicking the label that names the field moves focus to the first empty section. The AM/PM section announces its localized name via aria-valuetext and can be toggled with the A/P letters or arrow keys.

The keyboard support table applies unchanged, including Ctrl + A (select all), Ctrl + C (copy), and paste.