input[kuiTimePicker] is the trigger. Pair it with kui-time-picker-panel inside a sibling kui-dropdown, the same composition input[kuiDatePicker] uses with kui-calendar.

time-picker.ts
import { KuiDropdown, KuiField, KuiTimePicker, KuiTimePickerPanel } from '@kikita-labs/ui';

Bind value with a signal of Date | null. The panel needs no bindings: inside the same kui-field the directive finds it and wires value both ways and pushes the format, steps, seconds, limits and disabled functions into it.

Type a time or choose from the columns.

<div class="time-picker-example">
  <kui-field label="Meeting time" hint="Type a time or choose from the columns.">
    <input kuiTimePicker [(value)]="time" />
    <kui-dropdown panelRole="dialog" panelWidth="auto" maxHeight="280px">
      <kui-time-picker-panel />
    </kui-dropdown>
  </kui-field>
</div>

Every column centers on its selected cell when the panel opens and after each selection. Selecting a cell does not close the panel, so hours, minutes and seconds can all be picked; close with Enter, Escape, an outside click or the panel's Done button. Now sets the current time without closing.

format 12h renders a 1 to 12 hours column and an AM/PM toggle. showSeconds adds a third column, and the step inputs thin the columns to every Nth value.

12-hour clock with seconds in 15-minute and 15-second steps.

<div class="time-picker-example">
  <kui-field label="Slot" hint="12-hour clock with seconds in 15-minute and 15-second steps.">
    <input
      kuiTimePicker
      [(value)]="time"
      format="12h"
      [showSeconds]="true"
      [minuteStep]="15"
      [secondStep]="15"
    />
    <kui-dropdown panelRole="dialog" panelWidth="auto" maxHeight="300px">
      <kui-time-picker-panel />
    </kui-dropdown>
  </kui-field>
</div>

minTime and maxTime bound the day; disabledHours, disabledMinutes and disabledSeconds return the values to disable. Typing is never rejected, only flagged with aria-invalid.

09:00 to 18:00, lunch hours and 17:30 to 17:59 are not available.

<div class="time-picker-example">
  <kui-field
    label="Office hours"
    hint="09:00 to 18:00, lunch hours and 17:30 to 17:59 are not available."
  >
    <input
      kuiTimePicker
      [(value)]="time"
      [minTime]="minTime"
      [maxTime]="maxTime"
      [disabledHours]="disabledHours"
      [disabledMinutes]="disabledMinutes"
    />
    <kui-dropdown panelRole="dialog" panelWidth="auto" maxHeight="280px">
      <kui-time-picker-panel />
    </kui-dropdown>
  </kui-field>
</div>

kui-time-picker-panel also works on its own. Without a kui-dropdown ancestor it draws its own background and border, and Now and Done still work (Done has nothing to close).

01
02
03
04
05
06
07
08
09
10
11
12
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<div class="time-picker-example">
  <kui-time-picker-panel [(value)]="time" [showSeconds]="true" />
</div>

The input masks typing to the locale and keeps the last valid value.

  • Typing digits inserts the locale separator (2214 becomes 22:14, or 22.14 in da-DK); characters that could never be part of a value are stripped, and the input length is capped per format.
  • Each group clamps to its valid maximum once both digits are typed (99:99 becomes 23:59) and snaps to the nearest step.
  • For 12h the AM/PM suffix is optional: a fully typed hh:mm commits at once and keeps the previous period.
  • aria-invalid is set for an incomplete group such as 12:3 and for a value in an excluded range or on a disabled slot, without discarding the last valid value.
  • The caret always lands at the end of the field after typing, and digits are Latin in every locale.

Set defaults.timePicker once for the application or for a subtree. Each option resolves as local input > defaults.timePicker.<option> > built-in default.

import { provideKikitaUi } from '@kikita-labs/ui';

export const appConfig: ApplicationConfig = {
  providers: [
    provideKikitaUi({
      defaults: {
        timePicker: {
          /* options below */
        },
      },
    }),
  ],
};
NameTypeDefaultDescription
clearableboolean — When true, field controls with clear affordances show a clear button by default.
format'24h' | '12h' — Display and parse format.
hourStepnumber — Step of the hour column.
minuteStepnumber — Step of the minute column.
secondStepnumber — Step of the second column, used when seconds are shown.
showSecondsboolean — Shows the seconds column.
chevronIconKuiIconGlyph — Icon of the options toggle. Takes precedence over defaults.icons.pickerChevron. See Structural Icons.
clearIconKuiIconGlyph — Icon of the clear button. Takes precedence over defaults.icons.clear. See Structural Icons.

Set any of these on the component or an ancestor to restyle one part. Each token is optional: when it is not set, the part uses the role or scale token in the default column.

NameTypeDefaultDescription
--kui-timepicker-chevron-color-expandedCSS custom property--kui-color-primary-textChevron color, expanded
--kui-timepicker-panel-bgCSS custom property--kui-color-surfacePanel background
--kui-timepicker-panel-borderCSS custom property--kui-color-borderPanel border color
--kui-timepicker-col-focus-ring-colorCSS custom property--kui-color-focusCol focus ring color
--kui-timepicker-opt-colorCSS custom property--kui-color-textOpt color
--kui-timepicker-opt-color-disabledCSS custom property--kui-color-text-disabledOpt color, disabled
--kui-timepicker-opt-bg-selected-hoverCSS custom property--kui-color-primary-fill-hoverOpt background, selected hover
--kui-timepicker-footer-borderCSS custom property--kui-color-borderFooter border color
NameTypeDefaultDescription
--kui-timepicker-control-overlay-padding-inlineCSS custom property--kui-space-3Control overlay padding, inline
--kui-timepicker-panel-gapCSS custom property--kui-space-3Panel gap
--kui-timepicker-panel-paddingCSS custom property--kui-space-3Panel padding
--kui-timepicker-panel-radiusCSS custom property--kui-radius-lgPanel corner radius
--kui-timepicker-col-radiusCSS custom property--kui-radius-smCol corner radius
--kui-timepicker-opt-sizeCSS custom property--kui-control-height-smOpt size
--kui-timepicker-opt-radiusCSS custom property--kui-radius-smOpt corner radius
--kui-timepicker-opt-font-sizeCSS custom property--kui-text-sm-sizeOpt font size
--kui-timepicker-footer-gapCSS custom property--kui-space-2Footer gap
--kui-timepicker-footer-padding-topCSS custom property--kui-space-2Footer padding, top
--kui-timepicker-padding-inline-startCSS custom property34pxInput start padding that clears the clock icon
--kui-timepicker-padding-inline-endCSS custom property34pxInput end padding that clears the chevron
--kui-timepicker-padding-inline-end-clearableCSS custom property56pxInput end padding that clears the clear button and the chevron

Every text the component owns (accessible names, visible words, announcements) is a typed message with an English default. Override it for the application with provideKikitaUi({ messages }), or for a subtree with provideKuiMessages.

NameTypeDefaultDescription
openPickerstring — Name of the button that opens the panel. Default Open time picker.
closePickerstring — Name of the button that closes the panel. Default Close time picker.
hoursstring — Name of the hour column. Default Hours.
minutesstring — Name of the minute column. Default Minutes.
secondsstring — Name of the second column. Default Seconds.
periodstring — Name of the day period column. Default AM/PM.
nowstring — Footer action that sets the current time. Default Now.
donestring — Footer action that closes the panel. Default Done.
hourPlaceholderstring — Placeholder token for hours. Default hh.
minutePlaceholderstring — Placeholder token for minutes. Default mm.
secondPlaceholderstring — Placeholder token for seconds. Default ss.

Inputs verified against @kikita-labs/ui v2.0.0 public typings.

NameTypeDefaultDescription
[(value)]Date | nullnullSelected time. Only the hours, minutes and seconds are meaningful. Auto-wired both ways into a sibling kui-time-picker-panel inside the same kui-field.
format'24h' | '12h' | undefinedundefinedDisplay and parse format. Resolves as format, then defaults.timePicker.format, then the hour cycle of the locale (12h in en-US, 24h in ru-RU). Pushed into the panel.
hourStep / minuteStep / secondStepnumber1Thins the hour, minute and second columns to every Nth value; typed values snap to the step. Static numeric values are coerced and invalid or non-positive values use 1. Fall back to defaults.timePicker. Pushed into the panel.
showSecondsbooleanfalseAdds a seconds column and group. Falls back to defaults.timePicker.showSeconds.
minTime / maxTimeDate | undefinedundefinedEarliest and latest selectable time of day, inclusive; only hours, minutes and seconds are read. Out-of-range cells are disabled and a typed out-of-range time is only marked aria-invalid.
disabledHours(() => readonly number[]) | undefinedundefinedReturns the hours to disable. A typed value on one is marked aria-invalid, not rejected.
disabledMinutes((hour: number) => readonly number[]) | undefinedundefinedReturns the minutes to disable for a given hour.
disabledSeconds((hour: number, minute: number) => readonly number[]) | undefinedundefinedReturns the seconds to disable for a given hour and minute; used only with showSeconds.
clearableboolean | undefinedundefinedShows the clear button once there is a value. Resolved as local input, defaults.timePicker.clearable, defaults.field.clearable, then true.
disabled / readonlybooleanfalsedisabled uses the native attribute on the input and the chevron. readonly shows the value but never opens the popover.
placeholderstring | undefinedlocale layoutDefaults to the hour, minute and second placeholder messages joined with the locale separator, plus the day period for 12h.
messagesPartial<KuiTimePickerMessages> | undefinedundefinedPer-instance text overrides: button and column names, Now, Done and the placeholder tokens.
idstring | undefinedundefinedFalls back to the control id of the parent kui-field.
invalid, errors, touched, (touch)FormValueControl<Date | null>-The Signal Forms contract, with the same shape as the date picker. invalid is also set by an incomplete group or a value in an excluded range.
kui-time-picker-panelcomponent-The scrollable hour, minute and second columns with Now and Done. It works inside a kui-dropdown (auto-wired to the input) or standalone with [(value)]; standalone it draws its own background and border.
--kui-timepicker-col-gap / -icon-color / -cell-bg-selected / -cell-text-selected / -cell-bg-hoverCSS custom properties-Column gap, clock icon colour and the selected and hover cell colours.
--kui-timepicker-affordance-size / -suffix-gapCSS custom properties20px / 2pxChevron and clear target size and the gap between the trailing buttons.
KuiTimePickerOptionsinterface-Shape of defaults.timePicker: clearable, format, hourStep, minuteStep, secondStep, showSeconds, chevronIcon and clearIcon.

The input is a combobox that opens a non-modal dialog, the same pattern as the date picker.

  • The input has role="combobox", aria-haspopup="dialog", aria-expanded and aria-controls for the popover panel.
  • Each column is a focusable role="listbox" named Hours, Minutes or Seconds with role="option" cells and aria-selected; the selected cell is also distinct by fill and weight, not colour alone, and the focus ring is styled explicitly.
  • AM/PM is a kui-segmented radio group, keyboard accessible as part of the kit.
  • ArrowDown on the closed input opens the popover and focuses the first column; Enter toggles it; Escape closes it and keeps focus in the field; Tab closes it and moves on.
  • In a column ArrowUp and ArrowDown move cyclically and apply at once, Home and End jump to the first and last value, and Enter closes the popover keeping the selection.
  • Disabled uses the native attribute on the input and the chevron. Pair an invalid value with the error of kui-field for an announced alert.

Documented limits of the installed package.

  • Range picking (from and to) is not implemented.
  • Now only clamps into minTime and maxTime, not around the disabled function results, so it can land on a disabled slot and is then marked invalid.
  • aria-controls does not point at the real dropdown panel id before the first open, the same gap as the date picker.
  • The leading clock icon is a structural glyph with no override slot yet; the clear and chevron icons have one.