Time Picker API
View componentThe full prop reference for the Time Picker component. A MUI-style time field with a 12-hour analog clock panel.
Import
import { TimePicker } from '@structyl/styled';Props
TimePicker (default export / TimePickerRoot)
The main time picker component with popover trigger, clock panel, and form integration. Supports controlled and uncontrolled value states.
| Prop | Type | Default |
|---|---|---|
| value# | Date | { hour: number; minute: number; second?: number; period?: 'am' | 'pm' } | null | undefinedControlled time value (Date or TimeValue object) | — |
| defaultValue# | Date | { hour: number; minute: number; second?: number; period?: 'am' | 'pm' } | null | undefinedInitial time value when uncontrolled | — |
| onChange# | (value: Date | null, context: { validationError: TimeValidationError | null; source: 'view' | 'field' | 'shortcut' | 'unknown' }) => voidFired when time changes via any source (clock, keyboard, etc.) | — |
| onValueChange# | (v: { hour: number; minute: number; second?: number; period?: 'am' | 'pm' }) => voidFired with TimeValue object when time changes | — |
| onAccept# | (value: Date | null, context: { validationError: TimeValidationError | null; source: 'view' }) => voidFired when user accepts selection (OK button or closeOnSelect) | — |
| onError# | (error: 'minTime' | 'maxTime' | 'minutesStep' | 'shouldDisableTime' | null, value: Date | null) => voidFired when validation error state changes | — |
| disabled# | booleanDisables the picker and all interactions | false |
| readOnly# | booleanMakes the picker read-only; prevents value changes | false |
| ampm# | booleanShow AM/PM selector and use 12-hour format (overrides hour12 if provided) | true |
| hour12# | booleanUse 12-hour format (overridden by ampm if both present) | — |
| withSeconds# | booleanInclude seconds picker clock view | false |
| closeOnSelect# | booleanClose popover after selecting a value | false |
| disableOpenPicker# | booleanDisable the trigger button (popover cannot be opened) | false |
| minTime# | DateMinimum selectable time (validation + clock disabling) | — |
| maxTime# | DateMaximum selectable time (validation + clock disabling) | — |
| minutesStep# | numberStep for minute picker; disables non-aligned minutes on clock | 1 |
| shouldDisableTime# | (value: Date, view: 'hours' | 'minutes' | 'seconds' | 'meridiem') => booleanCustom validation function to disable specific times | — |
| skipDisabled# | booleanHide disabled clock positions instead of showing them grayed out | — |
| timeSteps# | { hours?: number; minutes?: number; seconds?: number }Increment steps for each clock view | — |
| referenceDate# | DateFallback date used when value is a TimeValue object (for time-only conversion) | — |
| views# | ('hours' | 'minutes' | 'seconds')[]Restrict which clock views are available | — |
| locale# | stringBCP 47 locale string for Intl formatting (future) | — |
| label# | React.ReactNodeVisible label above the trigger button | — |
| placeholder# | React.ReactNodeText displayed when no time is selected | 'HH:mm' |
| helperText# | React.ReactNodeSmall text below the trigger (e.g. error or hint) | — |
| required# | booleanShow required asterisk in label | — |
| error# | booleanHighlight field as erroneous; sets aria-invalid and error text color | — |
| format# | Intl.DateTimeFormatOptions | stringFormat for displaying selected time in trigger (e.g. 'HH:mm:ss' or Intl options) | { timeStyle: 'short' } |
| id# | stringHTML id for the trigger button and label association | — |
| name# | stringHTML name for the trigger button (future form integration) | — |
| className# | stringCSS class for the root wrapper div | — |
| triggerClassName# | stringCSS class for the trigger button | — |
| contentClassName# | stringCSS class for the popover content wrapper | — |
| columnClassName# | stringCSS class for clock number buttons | — |
| rootProps# | React.ComponentPropsWithoutRef<'div'>Props forwarded to the root div (onClick, style, role, tabIndex, data-*, aria-*) | — |
| ref# | React.Ref<HTMLDivElement>Ref forwarded to the root wrapper div | — |
TimePicker.Root
Primitive headless root that provides context for segments and manages controlled time state. Extends div.
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanReplace with child element (Radix compound pattern) | — |
| value# | Date | { hour: number; minute: number; second?: number; period?: 'am' | 'pm' } | null | undefinedControlled time value | — |
| defaultValue# | Date | { hour: number; minute: number; second?: number; period?: 'am' | 'pm' } | null | undefinedInitial time value when uncontrolled | — |
| onChange# | (value: Date | null, context: { validationError: TimeValidationError | null; source: 'view' }) => voidFired when time changes from segments | — |
| onValueChange# | (v: { hour: number; minute: number; second?: number; period?: 'am' | 'pm' }) => voidFired with TimeValue when time changes | — |
| onAccept# | (value: Date | null, context: { validationError: TimeValidationError | null; source: 'view' }) => voidFired on closeOnSelect | — |
| onError# | (error: TimeValidationError | null, value: Date | null) => voidFired when validation error changes | — |
| disabled# | booleanDisables all segments and interactions | — |
| readOnly# | booleanPrevents value changes | — |
| hour12# | booleanUse 12-hour format for hours segment | false |
| ampm# | booleanEnable AM/PM period segment (overrides hour12) | — |
| withSeconds# | booleanInclude seconds segment | false |
| closeOnSelect# | booleanTrigger onAccept on value change | false |
| minTime# | DateMinimum selectable time | — |
| maxTime# | DateMaximum selectable time | — |
| minutesStep# | numberMinutes increment (>1 fails validation for non-aligned values) | — |
| disablePast# | booleanDisable times before current moment | — |
| disableFuture# | booleanDisable times after current moment | — |
| shouldDisableTime# | (value: Date, view: 'hours' | 'minutes' | 'seconds' | 'meridiem') => booleanCustom validation predicate | — |
| disableIgnoringDatePartForTimeValidation# | booleanUse full Date context for minTime/maxTime comparison (future) | — |
| referenceDate# | DateFallback date for TimeValue to Date conversion | — |
| label# | React.ReactNodeForm label (future) | — |
| name# | stringHidden input name (future) | — |
| format# | Intl.DateTimeFormatOptions | stringDisplay format (future) | — |
| onOpenChange# | (open: boolean) => voidControlled open state change (future) | — |
| onSelectedSectionsChange# | (newValue: 'all' | 'hours' | 'minutes' | 'seconds' | 'meridiem' | number | null) => voidSegment selection changed (future) | — |
| onViewChange# | (view: 'hours' | 'minutes' | 'seconds' | 'meridiem') => voidClock view changed (future) | — |
| selectedSections# | 'all' | 'hours' | 'minutes' | 'seconds' | 'meridiem' | number | nullControlled selected segment (future) | — |
| defaultSelectedSections# | 'all' | 'hours' | 'minutes' | 'seconds' | 'meridiem' | number | nullInitial selected segment (future) | — |
| view# | 'hours' | 'minutes' | 'seconds' | 'meridiem'Controlled active clock view (future) | — |
| defaultView# | 'hours' | 'minutes' | 'seconds' | 'meridiem'Initial active clock view (future) | — |
| timeSteps# | { hours?: number; minutes?: number; seconds?: number }Increment steps per view | — |
| views# | ('hours' | 'minutes' | 'seconds' | 'meridiem')[]Allowed clock views (future) | — |
| inputRef# | React.Ref<HTMLInputElement>Ref to hidden input (future) | — |
| localeText# | Record<string, React.ReactNode>i18n string overrides (future) | — |
| locale# | stringBCP 47 locale (future) | — |
| formatDensity# | 'dense' | 'spacious'Spacing density for format (future) | — |
| orientation# | 'landscape' | 'portrait'Clock layout orientation (future) | — |
| readOnlyInput# | booleanMake text non-editable (future) | — |
| reduceAnimations# | booleanDisable CSS transitions (future) | — |
| keepOpenDuringFieldFocus# | booleanKeep popover open while segment focused (future) | — |
| desktopModeMediaQuery# | stringResponsive layout trigger (future) | — |
| disableOpenPicker# | booleanHide popover trigger icon (future) | — |
| autoFocus# | booleanAuto-focus first segment (future) | — |
| ampmInClock# | booleanAM/PM indicator in analog clock (future) | — |
| skipDisabled# | booleanSkip disabled values on navigation (future) | — |
| thresholdToRenderTimeInASingleColumn# | numberSingle-column clock threshold (future) | — |
| slotProps# | Record<string, unknown>Per-slot prop overrides (future) | — |
| slots# | Record<string, React.ElementType | null | undefined>Slot component overrides (future) | — |
| sx# | Record<string, unknown> | (theme: unknown) => Record<string, unknown>MUI system sx prop (future) | — |
| timezone# | stringIANA timezone string (future) | — |
| viewRenderers# | Partial<Record<'hours' | 'minutes' | 'seconds' | 'meridiem', (params: { view: TimePickerView; value: Date | null; onChange: (value: Date | null) => void }) => React.ReactNode | null>>Custom view render functions (future) | — |
| open# | booleanControlled open state (future) | — |
| defaultOpen# | booleanInitial open state (future) | — |
| onOpen# | () => voidPopover opened (future) | — |
| onClose# | () => voidPopover closed (future) | — |
| openTo# | 'hours' | 'minutes' | 'seconds' | 'meridiem'Initial clock view (future) | 'hours' |
TimePicker.Segment
Spinbutton for individual time segments (hour, minute, second, period). Responds to arrow keys and keyboard input.
| Prop | Type | Default |
|---|---|---|
| segment# | 'hour' | 'minute' | 'second' | 'period'Which segment this spinbutton represents | — |
| className# | stringCSS class for the segment span | — |
| ref# | React.Ref<HTMLSpanElement>Ref to the span element | — |
TimePicker.Separator
Visual separator between segments (e.g. colons between HH:mm:ss).
| Prop | Type | Default |
|---|---|---|
| children# | React.ReactNodeSeparator content | ':' |
| className# | stringCSS class for the span | — |
| ref# | React.Ref<HTMLSpanElement>Ref to the span element | — |
TimePicker.Value
Formatted display of the selected time. Supports Intl.DateTimeFormat or custom format strings.
| Prop | Type | Default |
|---|---|---|
| format# | Intl.DateTimeFormatOptions | stringFormat spec (Intl options or template string with HH/H/hh/h/mm/m/ss/s/aa/a tokens) | { timeStyle: 'short' } |
| locale# | stringBCP 47 locale for Intl formatting | — |
| placeholder# | React.ReactNodeText shown when no time is selected | 'Pick a time' |
TimePicker.Panel
Standalone analog clock panel for time selection. Used internally by the main TimePicker but can be used independently.
| Prop | Type | Default |
|---|---|---|
| value# | Date | nullCurrent selected time | — |
| onChange# | (value: Date) => voidFired as user adjusts clock hands | — |
| onAccept# | (value: Date) => voidFired when OK button clicked | — |
| onCancel# | () => voidFired when Cancel button clicked | — |
| ampm# | booleanShow AM/PM toggle | true |
| withSeconds# | booleanInclude seconds clock view | — |
| minutesStep# | numberMinute increment; disables non-aligned positions on clock | — |
| timeSteps# | { hours?: number; minutes?: number; seconds?: number }Step size per view | — |
| minTime# | DateMinimum selectable time (disables positions on clock) | — |
| maxTime# | DateMaximum selectable time (disables positions on clock) | — |
| shouldDisableTime# | (value: Date, view: 'hours' | 'minutes' | 'seconds' | 'meridiem') => booleanCustom validation to disable clock positions | — |
| skipDisabled# | booleanHide disabled positions instead of showing them faded | — |
| views# | ('hours' | 'minutes' | 'seconds' | 'meridiem')[]Restrict which clock views are available | — |
| referenceDate# | DateFallback date when value is undefined | — |
| columnClassName# | stringCSS class for clock number buttons | — |
| title# | React.ReactNodeHeader text above clock | 'SELECT TIME' |
| showActions# | booleanShow OK/Cancel buttons | true |
| className# | stringCSS class for the panel wrapper | — |
| ref# | React.Ref<HTMLDivElement>Ref to the panel div | — |
Source code
If you didn't find what you need here, read the component implementation .