Time Picker
Time-of-day input with a scrollable hour, minute and second panel.
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.
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.
<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.
<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.
<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).
<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 (
2214becomes22:14, or22.14in 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:99becomes23:59) and snaps to the nearest step. - For
12hthe AM/PM suffix is optional: a fully typedhh:mmcommits at once and keeps the previous period. aria-invalidis set for an incomplete group such as12:3and 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 */
},
},
}),
],
};| Name | Type | Default | Description |
|---|---|---|---|
| clearable | boolean | — | When true, field controls with clear affordances show a clear button by default. |
| format | '24h' | '12h' | — | Display and parse format. |
| hourStep | number | — | Step of the hour column. |
| minuteStep | number | — | Step of the minute column. |
| secondStep | number | — | Step of the second column, used when seconds are shown. |
| showSeconds | boolean | — | Shows the seconds column. |
| chevronIcon | KuiIconGlyph | — | Icon of the options toggle. Takes precedence over defaults.icons.pickerChevron. See Structural Icons. |
| clearIcon | KuiIconGlyph | — | 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.
| Name | Type | Default | Description |
|---|---|---|---|
| --kui-timepicker-chevron-color-expanded | CSS custom property | --kui-color-primary-text | Chevron color, expanded |
| --kui-timepicker-panel-bg | CSS custom property | --kui-color-surface | Panel background |
| --kui-timepicker-panel-border | CSS custom property | --kui-color-border | Panel border color |
| --kui-timepicker-col-focus-ring-color | CSS custom property | --kui-color-focus | Col focus ring color |
| --kui-timepicker-opt-color | CSS custom property | --kui-color-text | Opt color |
| --kui-timepicker-opt-color-disabled | CSS custom property | --kui-color-text-disabled | Opt color, disabled |
| --kui-timepicker-opt-bg-selected-hover | CSS custom property | --kui-color-primary-fill-hover | Opt background, selected hover |
| --kui-timepicker-footer-border | CSS custom property | --kui-color-border | Footer border color |
| Name | Type | Default | Description |
|---|---|---|---|
| --kui-timepicker-control-overlay-padding-inline | CSS custom property | --kui-space-3 | Control overlay padding, inline |
| --kui-timepicker-panel-gap | CSS custom property | --kui-space-3 | Panel gap |
| --kui-timepicker-panel-padding | CSS custom property | --kui-space-3 | Panel padding |
| --kui-timepicker-panel-radius | CSS custom property | --kui-radius-lg | Panel corner radius |
| --kui-timepicker-col-radius | CSS custom property | --kui-radius-sm | Col corner radius |
| --kui-timepicker-opt-size | CSS custom property | --kui-control-height-sm | Opt size |
| --kui-timepicker-opt-radius | CSS custom property | --kui-radius-sm | Opt corner radius |
| --kui-timepicker-opt-font-size | CSS custom property | --kui-text-sm-size | Opt font size |
| --kui-timepicker-footer-gap | CSS custom property | --kui-space-2 | Footer gap |
| --kui-timepicker-footer-padding-top | CSS custom property | --kui-space-2 | Footer padding, top |
| --kui-timepicker-padding-inline-start | CSS custom property | 34px | Input start padding that clears the clock icon |
| --kui-timepicker-padding-inline-end | CSS custom property | 34px | Input end padding that clears the chevron |
| --kui-timepicker-padding-inline-end-clearable | CSS custom property | 56px | Input 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.
| Name | Type | Default | Description |
|---|---|---|---|
| openPicker | string | — | Name of the button that opens the panel. Default Open time picker. |
| closePicker | string | — | Name of the button that closes the panel. Default Close time picker. |
| hours | string | — | Name of the hour column. Default Hours. |
| minutes | string | — | Name of the minute column. Default Minutes. |
| seconds | string | — | Name of the second column. Default Seconds. |
| period | string | — | Name of the day period column. Default AM/PM. |
| now | string | — | Footer action that sets the current time. Default Now. |
| done | string | — | Footer action that closes the panel. Default Done. |
| hourPlaceholder | string | — | Placeholder token for hours. Default hh. |
| minutePlaceholder | string | — | Placeholder token for minutes. Default mm. |
| secondPlaceholder | string | — | Placeholder token for seconds. Default ss. |
Inputs verified against @kikita-labs/ui v2.0.0 public typings.
| Name | Type | Default | Description |
|---|---|---|---|
| [(value)] | Date | null | null | Selected 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' | undefined | undefined | Display 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 / secondStep | number | 1 | Thins 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. |
| showSeconds | boolean | false | Adds a seconds column and group. Falls back to defaults.timePicker.showSeconds. |
| minTime / maxTime | Date | undefined | undefined | Earliest 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[]) | undefined | undefined | Returns the hours to disable. A typed value on one is marked aria-invalid, not rejected. |
| disabledMinutes | ((hour: number) => readonly number[]) | undefined | undefined | Returns the minutes to disable for a given hour. |
| disabledSeconds | ((hour: number, minute: number) => readonly number[]) | undefined | undefined | Returns the seconds to disable for a given hour and minute; used only with showSeconds. |
| clearable | boolean | undefined | undefined | Shows the clear button once there is a value. Resolved as local input, defaults.timePicker.clearable, defaults.field.clearable, then true. |
| disabled / readonly | boolean | false | disabled uses the native attribute on the input and the chevron. readonly shows the value but never opens the popover. |
| placeholder | string | undefined | locale layout | Defaults to the hour, minute and second placeholder messages joined with the locale separator, plus the day period for 12h. |
| messages | Partial<KuiTimePickerMessages> | undefined | undefined | Per-instance text overrides: button and column names, Now, Done and the placeholder tokens. |
| id | string | undefined | undefined | Falls 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-panel | component | - | 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-hover | CSS custom properties | - | Column gap, clock icon colour and the selected and hover cell colours. |
| --kui-timepicker-affordance-size / -suffix-gap | CSS custom properties | 20px / 2px | Chevron and clear target size and the gap between the trailing buttons. |
| KuiTimePickerOptions | interface | - | 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-expandedandaria-controlsfor the popover panel. - Each column is a focusable
role="listbox"named Hours, Minutes or Seconds withrole="option"cells andaria-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-segmentedradio 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
errorofkui-fieldfor an announced alert.
Documented limits of the installed package.
- Range picking (from and to) is not implemented.
- Now only clamps into
minTimeandmaxTime, not around the disabled function results, so it can land on a disabled slot and is then marked invalid. aria-controlsdoes 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.