Skip to content

Time picker

In review
Live · web

Field + popover · 12-hour · AM / PM

Reminder time

Selected: 2:30 PM

Inline · 12 / 24h · 5-min step · no past times

09Hour
45Minute

Setting the hour · pick the hour, then the minute

Step 5 min · selectable from 9:41 AM onward

Selected: 9:45 AM

States · empty placeholder · disabled

Snooze until
Locked (server-set)
// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform;
// this is the intended API, not yet exported from @dizyx/nockerl-react (promotion tracked).
// Neither app ships a custom time picker, so the web island is designed from the
// laws, pairing with DatePicker's field + popover + accent vocabulary.)
export function ReminderForm() {
const [at, setAt] = useState<{ hour: number; minute: number }>({ hour: 14, minute: 30 });
return (
<>
{/* Field + popover, 12-hour with AM/PM. */}
<TimePicker label="Reminder time" value={at} onChange={setAt} />
{/* Always-open inline clock, 24-hour, 5-minute step, no past times. */}
<TimePicker
label="Run at"
value={at}
onChange={setAt}
inline
use24Hour
minuteStep={5}
min={{ hour: 9, minute: 41 }}
/>
</>
);
}
PropTypeDefaultDescription
label *stringPersistent field label above the trigger (never placeholder-as-label).
value *{ hour: number; minute: number } | nullSelected time, hour in 0 to 23 (controlled). null renders the empty Set a time prompt.
onChange *(t: { hour: number; minute: number }) => voidFires on a dial pick, a spinbutton step/type, or an AM/PM flip.
inlinebooleanfalseWhen true, the clock panel is always open (no field trigger / popover).
use24HourbooleanfalseHides the AM/PM toggle and labels the dial 0 to 23. Toggleable in-panel via the 12h/24h switch.
minuteStepnumber1Quantises the minute (e.g. 5); the minute ring shows the stepped marks.
min{ hour: number; minute: number }Inclusive earliest selectable time. Earlier picks render dimmed but legible.
max{ hour: number; minute: number }Inclusive latest selectable time. Later picks render dimmed but legible.
disabledbooleanfalseInert and clearly seen (never faded to invisible). The trigger is non-interactive.
Cross-platform drift (tracked for reconciliation)
  • Stock native pickers, an original web island. The Kotlin and Swift tabs document the stock Material 3 / SwiftUI pickers, themed with Nockerl tokens. The time code in the canonical apps formats rather than picks (SimpleDateFormat("h:mm a") on Android, durations in Voice). The web island is designed originally from the laws (recessed field-trigger + dial face, lifted panel card, cyan selected number + hand, mono digits, segmented AM/PM + 12h/24h toggles) so it pairs with the date picker as one date-and-time set.
  • Dial vs. wheel vs. columns (settled): the entry mode defaults to the platform idiom (Material dial, SwiftUI wheel, the web dial + spinbuttons) under shared prop names: one contract, native default per surface.
  • Minute step + bounds: the standing ruling is a shared minuteStep / min / max API everywhere. Web already exposes it; Material 3 (no native step) and SwiftUI (in: range only) adopt the shared contract.