--- ## TimeInput **Stability:** beta — the API shape is settled and documented; behaviour-level fixes may still land as breaking changes in a minor. Segmented time-of-day field — hour / minute (/ second) cells in a single unified control, with per-segment Arrow-key stepping, digit auto-advance, and 12- or 24-hour display. Fills the last form-family gap (Calendar, DatePicker and DateRangePicker cover dates; this covers time). The value has three states, read off the segments alone: `undefined` while every segment is empty, `null` while the time is half-typed (some segments filled, some blank, or, with a `step`, a mid-entry digit leaving the time off the raster), and a canonical 24-hour `HH:MM` (or `HH:MM:SS`) string once it is complete, regardless of display format. `step` sets a raster in seconds, as on ``. An `onfocusout` you pass lands on the root and runs after the `min`/`max` clamp, on every hop between segments too: the field was left when `relatedTarget` is outside `currentTarget`. **Import:** `import { TimeInput } from '@urbicon-ui/blocks';` ### Examples ```svelte ``` ```svelte ``` ```svelte ``` ### Variants - intent: danger, default, success, warning (default: default) - variant: filled, ghost, outlined (default: outlined) - size: lg, md, sm (default: md) - disabled: true (default: false) - fullWidth: true (default: false) - messageType: error, helper (default: helper) - readonly: true (default: false) - required: true (default: false) - tier: commit, modify (default: modify) ### Api | Prop | Type | Required | Default | Description | | --- | --- | :---: | --- | --- | | ...HTMLAttributes | `HTMLAttributes` | no | | HTML attributes (excluding: 'class' | 'id' | 'aria-label' | 'children') | | ...TimeInputVariants | `VariantProps` | no | | Styling variants from TimeInputVariants | | aria-label | `string` | no | | Accessible name for the field group when no visible `label` is set. | | class | `string` | no | | Extra classes merged onto the root wrapper. In the same Tailwind bucket `class` wins over the `slotClasses` entry for the element it lands on. Presets and provider defaults sit below both. | | disabled | `boolean` | no | false | Blocks input and dims the whole field. | | error | `string` | no | | Error message below the field. When set it overrides `helper`, colours the field danger, and marks the segments `aria-invalid`. | | format | `'12h' | '24h'` | no | '24h' | Display the hour as 12-hour with an AM/PM segment. The value stays 24-hour. | | fullWidth | `boolean` | no | false | Stretch the field to the full width of its container. | | helper | `string` | no | | Helper text below the field — hidden when `error` is present. | | icon | `Snippet` | no | | A custom leading icon; replaces the default clock. | | id | `string` | no | | Root id; the segments derive their ids and ARIA wiring from it. | | label | `string` | no | | Label text displayed above the field, linked via `aria-labelledby`. | | max | `string` | no | | Latest allowed time, canonical 24-hour `HH:MM`(`:SS`). Values above it are clamped down on blur, to the last `step` raster point at or below it. | | min | `string` | no | | Earliest allowed time, canonical 24-hour `HH:MM`(`:SS`). Values below it are clamped up on blur. It is also where the `step` raster starts. | | name | `string` | no | | Name for a hidden input carrying the canonical value, for native form submission; it submits `""` while the field is empty or half-typed. | | onValueChange | `(value: string | null | undefined) => void` | no | | Fires whenever the field changes the value (typing, the Arrow keys, Backspace, the clamp on blur) with the canonical 24-hour string, `null` while half-typed, or `undefined` once every segment is empty again. Setting `value` yourself does not fire it. | | preset | `string` | no | | Apply a named preset registered via ``. | | readonly | `boolean` | no | false | Shows the time but refuses edits; the segments stay focusable. | | required | `boolean` | no | false | Marks the label with an asterisk and sets `aria-required` on the segments. It does not block a native submit — the value lives in component state, so validate it yourself before you act on it. | | showIcon | `boolean` | no | true | Show the leading clock icon. | | slotClasses | `Partial>` | no | | Per-slot class overrides merged with tv() styles. Slots: wrapper (what `class` also targets) | label | requiredMark | field | icon | segment | separator | meridiem | message. In the same Tailwind bucket `class` wins over the `slotClasses` entry for the element it lands on. Presets and provider defaults sit below both. | | step | `number` | no | | Raster in seconds, counted from `min` (or midnight) as on ``: `900` is a 15-minute grid, `3600` whole hours. Unset, every minute is allowed (every second with `withSeconds`). - From a time on the raster, the Arrow keys move a segment to its next raster value and wrap inside it without carrying into the others. From a time off it (one you passed in, or a digit mid-entry), Up goes to the first raster point above and Down to the first below. `aria-valuemin`/`aria-valuemax` name the first and last raster value of each segment for the time shown. - A typed time off the raster snaps down to the raster point below it as soon as its segment is complete. While a digit is still mid-entry and the time it spells is off the raster, the value is `null`, so it never carries an off-raster time and always matches what the field shows. A time you pass in is shown as given, fixed segments included, and lands on the raster with the next edit or on blur. - The raster counts from `min`: with `min="09:10"` and `900`, a typed `10:00` lands on `09:55`. - A segment the raster pins to one value is shown but not typed: an hourly step fixes the minute (and second), a whole-minute step fixes the second. - Without `withSeconds` only the step's whole-minute points count: `30` allows every minute, `90` every third. - With a step that does not divide an hour (or a minute, with `withSeconds`), typing and the blur clamp reach every raster point, but the Arrow keys only move along points that keep the other segments; prefer a step that divides the hour. Must be a positive whole number; anything else is ignored, with a warning in dev. | | unstyled | `boolean` | no | | Remove all default tv() classes — only user-provided classes apply. | | value | `string | null | undefined` | no | | The time as the segments spell it, in one of three states: - `undefined` while every segment is empty, untouched or cleared back to empty. Leave the prop out (or bind `undefined`) for an empty field. - `null` while the time is half-typed: at least one segment holds a digit and at least one is blank, or, with a `step`, a mid-entry digit leaves the time off the raster. - A canonical 24-hour `HH:MM` / `HH:MM:SS` string once the time is complete; `format` never changes it. An AM/PM segment always holds a value, so it never makes a time half-typed. `""` reads as no time, like `null` and `undefined`. Passing no time clears the field: one that shows a complete time clears wherever focus is, a half-typed one only while focus is outside it. On a half-typed field with focus inside, no time is taken as the echo of the field's own report and ignored, so a consumer that stores no time as one value (`""` or `undefined`) cannot wipe the digits being typed; the cost is that a reset fired from inside a half-typed field (an Escape handler on it, or a clear button that keeps focus with a `mousedown` `preventDefault`) is ignored too, and nothing is written back, so value and segments disagree until the next edit. A reset has to change the value: a half-typed bound field already holds `null`, so reset it with `undefined`. Where neither works (a reset from inside, or a `string`-typed consumer that can only write `""`), remount the field with `{#key}`. A `null` you pass at mount renders empty and stays `null` until the user edits. Supports `bind:value`. | | withSeconds | `boolean` | no | false | Add a seconds segment. | | intent | `'danger' | 'default' | 'success' | 'warning'` | no | default | Controls the color theme and semantic meaning of the TimeInput. Affects the overall appearance and user perception. Available options: danger, default, success, warning. | | variant | `'filled' | 'ghost' | 'outlined'` | no | outlined | Controls the visual style and presentation of the TimeInput. Determines the component's visual treatment. Available options: filled, ghost, outlined. | | size | `'lg' | 'md' | 'sm'` | no | md | Controls the dimensions, padding, and text size of the TimeInput. Affects the component's physical footprint. Available options: lg, md, sm. | | messageType | `'error' | 'helper'` | no | helper | Controls the messageType behavior and appearance of the TimeInput component. Available options: error, helper. | | tier | `'commit' | 'modify'` | no | modify | Selects the semantic radius tier of the TimeInput — the shape family it belongs to (`--radius-commit`/`-modify`/`-contain`/`-bridge`). Shape is retuned per family in your theme, so this picks the family rather than a pixel value. Available options: commit, modify. | Inherited from: - Omit (omit-pattern) - Omit, 'class' | 'id' | 'aria-label' | 'children'> (omit-pattern) ### Types ```ts type SlotNames = keyof ReturnType & string ``` ```ts type VariantProps = Omit< Exclude[0], undefined>, 'class' > ``` ### Slots (slotClasses keys) `wrapper`, `label`, `requiredMark`, `field`, `icon`, `segment`, `separator`, `meridiem`, `message`