Skip to content

Time Field

A field for a time of day, with separate hour, minute and (optional) second segments that follow the visitor's locale and 12 or 24 hour clock.

Inputv0.1.0experimentalWCAG 2.2 AAView spec
Start time
930AM
import { Time } from "@internationalized/date";
import { TimeField } from "@rdloom/react";

export default function TimeFieldBasicExample() {
  return (
    <div className="w-48">
      <TimeField label="Start time" defaultValue={new Time(9, 30)} />
    </div>
  );
}

Installation

npx rdloom add time-field

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/time-field.json

Works, but without upgrade tracking.

Usage

import { TimeField } from "@rdloom/react";

<div className="w-48">
  <TimeField label="Start time" defaultValue={new Time(9, 30)} />
</div>

Seconds

Timestamp
20530PM
24 hour clock
1800
import { Time } from "@internationalized/date";
import { TimeField } from "@rdloom/react";

export default function TimeFieldSecondsExample() {
  return (
    <div className="flex flex-col gap-4">
      <div className="w-56">
        <TimeField label="Timestamp" granularity="second" defaultValue={new Time(14, 5, 30)} />
      </div>
      <div className="w-48">
        <TimeField label="24 hour clock" hourCycle={24} defaultValue={new Time(18, 0)} />
      </div>
    </div>
  );
}

Range

Pickup time
815PM
We are open 9:00 to 17:00.Pick a time between 9:00 and 17:00.
import { Time } from "@internationalized/date";
import { TimeField } from "@rdloom/react";

// minValue and maxValue make times outside opening hours invalid.
export default function TimeFieldRangeExample() {
  return (
    <div className="w-64">
      <TimeField
        label="Pickup time"
        description="We are open 9:00 to 17:00."
        validationBehavior="aria"
        minValue={new Time(9)}
        maxValue={new Time(17)}
        defaultValue={new Time(20, 15)}
        errorMessage="Pick a time between 9:00 and 17:00."
      />
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
labelrequired

Visible label, also the accessible name.

stringnone
description

Help text under the field.

stringnone
errorMessage

Shown when the value is invalid. Leave out to use the built-in message.

stringnone
value

Controlled value.

TimeValue | nullnone
defaultValue

Initial value when uncontrolled.

TimeValue | nullnone
onChange

Called with the time, or null when it is cleared.

(value: TimeValue | null) => voidnone
granularity

Smallest unit shown and edited.

"hour" | "minute" | "second""minute"
hourCycle

Force a 12 or 24 hour clock. Leave out to follow the locale.

12 | 24none
minValue

Earliest allowed time.

TimeValuenone
maxValue

Latest allowed time.

TimeValuenone
size

Field height and text size.

"sm" | "md" | "lg""md"
isDisabled

Prevents interaction and dims the field.

booleanfalse
isInvalid

Marks the field invalid. Leave it unset to let validation decide.

booleannone
isRequired

Marks the field required and adds an asterisk.

booleanfalse

Accessibility

Role group, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

  • Left and Right arrows (or Tab) move between hour, minute and AM/PM
  • Up and Down arrows change the focused segment; typing digits sets it
  • Backspace clears the focused segment

Screen readers announce

  • Entering announces the label, then the first segment as "hours, spin button" with its value
  • Changing a segment announces the new value
  • The group is announced with the full time, e.g. "9:30 AM"

What your code must do

  • A labelled group of spin buttons: each segment is named (hours, minutes, AM/PM) and exposes its range
  • Digits typed move to the next segment on their own
  • Invalid state and the error message are linked to the field
  • The focused segment is highlighted with 3:1 contrast, not only by color

Guidelines

Use it when

  • Opening hours, reminders, meeting times and schedules
  • Any time of day that is not tied to a date

Avoid it when

  • A date and a time together: use DatePicker and TimeField side by side
  • A duration, such as 90 minutes: use NumberField

Don't

  • Forcing a 24 hour clock on people who use 12 hour (leave hourCycle to the locale unless you must)
  • A free text field for times

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-surface-default
  • --rd-color-surface-subtle
  • --rd-color-border-default
  • --rd-color-border-strong
  • --rd-color-text-default
  • --rd-color-text-muted
  • --rd-color-feedback-danger
  • --rd-color-focus-ring
  • --rd-radius-control
  • --rd-color-action-primary
  • --rd-color-action-on-primary