Browse docs
Browse docs
TimePicker is a form-connected time-of-day field: a read-only trigger paired
with a time-list popover. Pick a slot from the list. It integrates with
DashForm and RBAC automatically — the name prop connects the field to the
form schema.
The stored value is a canonical 24-hour "HH:mm" string, or null. 12-hour
notation is a display concern (hour12) — never the storage format. The field
carries no date and no time zone.
import { DashForm } from '@dashforge/forms';
import { TimePicker } from '@dashforge/tw';
<DashForm onSubmit={(data) => console.log(data)}>
<TimePicker
name="meetingTime"
label="Meeting time"
rules={{ required: 'Please pick a time' }}
/>
</DashForm>A basic field — click the trigger and pick a time from the popover.
import { TimePicker } from '@dashforge/tw';
<TimePicker name="meetingTime" label="Meeting time" />minTime / maxTime bound the selectable range; stepMinutes sets the
list granularity.
09:00–17:00, 15-minute steps
import { TimePicker } from '@dashforge/tw';
<TimePicker
name="slot"
label="Appointment slot"
minTime="09:00"
maxTime="17:00"
stepMinutes={15}
helperText="09:00–17:00, 15-minute steps"
/>hour12 renders the trigger and list in 12-hour notation. The stored value
stays the canonical 24-hour "HH:mm".
import { TimePicker } from '@dashforge/tw';
<TimePicker name="alarm" label="Alarm" hour12 defaultValue="14:30" />| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | Field name — the bridge registration key. Required. |
label | ReactNode | — | Field label. |
helperText | ReactNode | — | Hint text below the control. |
rules | RegisterOptions | — | Validation rules forwarded to the form bridge. |
required | boolean | false | Adds the label asterisk. |
error | boolean | — | Explicit error state (overrides the bridge's auto error). |
disabled | boolean | false | Disables the field. |
placeholder | string | — | Shown when no time is selected. |
layout | 'stacked' | 'inline' | 'stacked' | Label / control layout. |
value | string | null | — | Controlled value ("HH:mm"). |
defaultValue | string | null | — | Uncontrolled initial value. |
onChange | (value: string | null) => void | — | Fired with the new time. |
minTime / maxTime | string | "00:00" / "23:30" | Selectable bounds, "HH:mm". |
stepMinutes | number | 30 | Step between list options, in minutes. |
hour12 | boolean | false | Render the trigger + list in 12-hour notation. |
visibleWhen | (engine: Engine) => boolean | — | Reactive visibility predicate. |
access | AccessRequirement | — | RBAC access requirement. |
fullWidth | boolean | false | Stretches the field to its container width. |
sx | string | — | Tailwind class override for the root element. |
slotProps | TimePickerSlotProps | — | Per-slot className overrides. |
testId | string | — | Test id applied to the field root. |
sx overrides the root element's Tailwind classes; slotProps targets the
inner slots — root, label, requiredMark, trigger, helperText,
errorText.
<TimePicker name="meetingTime" label="Meeting time" sx="max-w-xs" />"HH:mm" storage. The bridge value is always the canonical
24-hour form, even when hour12 is set.DatePicker; for date +
time in one control use DateTimePicker.<TimePicker value={time} onChange={(v) => setTime(v)} label="Meeting time" />Inside DashForm the field registers automatically — validation, error
gating, and touch tracking flow through the bridge.
<TimePicker
name="cutoffTime"
label="Cut-off time"
access={{ resource: 'schedule', action: 'update', onUnauthorized: 'disable' }}
/>