Rime

TimeField and TimeRangeField

A time of day with typed input and a popup picker; the range variant pairs start and end on one row.

TimeField lets people type a time the way they say it ("3pm", "0930", "14:30") and offers a popup picker as a second path: scrollable hour, minute and AM/PM columns that auto-center on the current value. The value is "HH:MM" 24h regardless of display format, so it sorts, compares and serialises predictably.

format="12h" shows "9:30 AM" and parses am/pm; the default is 24h. step sets the minute granularity for the popup list (default 15; set to 1 for a free picker). min and max bound both the parse and the picker — a chosen time outside the bounds is kept on screen with a reason, not silently wiped. TimeRangeField pairs two TimeFields with an en dash between them and flags end at or before start as invalid so the row disagrees with itself until the parent fixes it.

Installation

npx shadcn@latest add KezLahd/rime/time-field

Also installs: base, field, icon, text-input.

Usage

import { TimeField, TimeRangeField, type Time, type TimeRange } from "@/components/ui";

<TimeField value={at} onChange={setAt} />

Examples

Open

inline shows the picker open under the field, in place.

Single time and range

API

Generated from the component's TypeScript types and JSDoc (scripts/gen-ui-registry.mjs), so it always matches the source.

TimeField

TimeField props
PropTypeDefaultDescription
valueRequiredTime | null
onChangeRequired(value: Time | null) => voidnull when cleared or when the typed text can't be read as a time.
format"12h" | "24h""24h"24h is the default. 12h shows "9:30 AM" and parses am/pm.
stepnumber15Minute granularity for the popup list (default 15). Set to 1 for a free picker.
minTime
maxTime
invalidboolean
disabledboolean
requiredboolean
idstring
namestring
placeholderstring
aria-labelstring
classNamestring
inlinebooleanfalseKeep the popup rendered open under the field (for docs).

TimeRangeField

TimeRangeField props
PropTypeDefaultDescription
valueRequiredTimeRange
onChangeRequired(value: TimeRange) => void
format"12h" | "24h""24h"
stepnumber15
requireEndAfterStartbooleantrueWhen true, flag an end at or before start as invalid. Default true.
minTime
maxTime
disabledboolean
classNamestring
aria-label-startstring
aria-label-endstring

Theme tokens

Per-component tokens are undeclared by default, so the default shown is the fallback the CSS uses. Set one at :root (or in theme.css) to restyle every instance. Live values are read from this page, so they follow the Rime Studio.

TimeField and TimeRangeField per-component tokens
TokenDefaultLive value
--field-focus-borderrgba(var(--rgb-brand), 0.7) / var(--focus-color)…
--field-focus-ringvar(--focus-halo)…

System tokens it reads

TimeField and TimeRangeField system tokens
TokenDefaultLive value
--danger-inktokens.css…
--durtokens.css…
--easetokens.css…
--ease-outtokens.css…
--focus-colortokens.css…
--focus-halotokens.css…
--ink-bodytokens.css…
--ink-brandtokens.css…
--ink-disabledtokens.css…
--ink-headingtokens.css…
--ink-mutedtokens.css…
--linetokens.css…
--r-lgtokens.css…
--r-smtokens.css…
--r-xstokens.css…
--rgb-brandtokens.css…
--shadow-floattokens.css…
--surface-solidtokens.css…
--surface-sunkentokens.css…
--text-smalltokens.css…
--wash-activetokens.css…
--wash-hovertokens.css…
--wash-subtletokens.css…
--z-popovertokens.css…

Accessibility

  • The field accepts spoken-style input ("3pm", "9:30 am") and reports a reason when the text can't be read as a time, named by aria-describedby.
  • The popup is a role="dialog" with hour, minute and (12h only) AM/PM listboxes; arrow keys move focus between cells and Enter picks.
  • Alt+Down from the field opens the popup. Escape closes it and returns focus to the toggle, so a Modal containing the field doesn't close with it.

Do and don't

Do

  • Use step={15} or step={30} for scheduling flows; most times a human picks are on the quarter or half hour.
  • Pass min and max for opening hours or an event window so the picker only lists times that work.

Don't

  • Don't use a free-text input for a time; the picker catches typos and ambiguous formats cheaply.

For AI agents

This page as markdown, rendered from the same registry entry. Point an agent at it (or add .md to this page's URL), or at /llms.txt for the index.

Open time-field.md

Related: date-field, date-range-filter, date-time-field