Active Foundation · Example
A time on a 24-hour and a 12-hour clock
A time on a 24-hour and a 12-hour clockClient
Value: 09:30 · state: valid
Value: 14:05 · state: valid
Full source examples/ui/time-field.tsx
// apps/docs/examples/ui/time-field.tsx'use client';
import {useState} from 'react';
import { composePresentationContext, toIanaTimeZone, toLocalTimeString,} from '@workspace/active-format';import { TimeField, type TimeFieldState,} from '@workspace/active-ui/components/composed/time-field';import { Field, FieldDescription, FieldError, FieldLabel,} from '@workspace/active-ui/components/primitives/field';
const ZONE = toIanaTimeZone('Europe/Amsterdam');const OPENS = toLocalTimeString('08:00');const CLOSES = toLocalTimeString('18:00');const H24 = composePresentationContext('en', {timeFormat: 'H24'}, ZONE);const H12 = composePresentationContext('en', {timeFormat: 'H12'}, ZONE);
const REASONS: Record<'format' | 'range' | 'step', string> = { format: 'Write a time such as 9:30.', range: 'Choose a time between 08:00 and 18:00.', step: 'Choose a quarter of an hour.',};
function Describe({ id, value, state,}: { id: string; value: string; state: TimeFieldState;}) { return state.status === 'invalid' ? ( <FieldError id={id}>{REASONS[state.rejection]}</FieldError> ) : ( <FieldDescription id={id}> Value: <code>{value || "''"}</code> · state: {state.status} </FieldDescription> );}
/** * A time of day, typed: on a 24-hour clock with a quarter-hour grid and * office hours as limits, and on a 12-hour clock. The value is always * `HH:mm` on the 24-hour clock; a time off the grid or outside the limits is * invalid and never rounded. */export default function TimeFieldExample() { const [meeting, setMeeting] = useState('09:30'); const [meetingState, setMeetingState] = useState<TimeFieldState>({ status: 'valid', }); const [reminder, setReminder] = useState('14:05'); const [reminderState, setReminderState] = useState<TimeFieldState>({ status: 'valid', }); return ( <div className="grid w-full max-w-xs gap-6"> <Field data-invalid={meetingState.status === 'invalid' || undefined}> <FieldLabel htmlFor="time-meeting">Meeting (24-hour)</FieldLabel> <TimeField id="time-meeting" value={meeting} onValueChange={setMeeting} onStateChange={setMeetingState} locale={H24} step={{unit: 'minute', value: 15}} min={OPENS} max={CLOSES} aria-describedby="time-meeting-state" /> <Describe id="time-meeting-state" value={meeting} state={meetingState} /> </Field> <Field data-invalid={reminderState.status === 'invalid' || undefined}> <FieldLabel htmlFor="time-reminder">Reminder (12-hour)</FieldLabel> <TimeField id="time-reminder" value={reminder} onValueChange={setReminder} onStateChange={setReminderState} locale={H12} aria-describedby="time-reminder-state" /> <Describe id="time-reminder-state" value={reminder} state={reminderState} /> </Field> </div> );}