Time Field
A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment.
Import
tsimport { TimeField } from "@kobalte/core/time-field";// orimport { Root, Label, ... } from "@kobalte/core/time-field";
tsimport { TimeField } from "@kobalte/core/time-field";// orimport { Root, Label, ... } from "@kobalte/core/time-field";
Features
- Times can optionally include a time zone. All modifications follow time zone rules such as daylight saving time.
- Support for locale-specific formatting, number systems, hour cycles, and right-to-left layout.
- Each time unit is displayed as an individually focusable and editable segment, which allows users an easy way to edit times using the keyboard, in any format and locale.
- Time segments are editable using an easy to use numeric keypad, and all interactions are accessible using touch-based screen readers.
- Can be controlled or uncontrolled.
- Integrates with HTML forms.
Anatomy
The time field consists of:
- TimeField: The root container for the time field.
- TimeField.Label: The label that gives the user information on the time field.
- TimeField.Input: The container for the segments.
- TimeField.Segment: The component that represents a unit of a time.
- TimeField.Description: The description that gives the user more information on the time field.
- TimeField.ErrorMessage: The error message that gives the user information about how to fix a validation error on the time field.
- TimeField.HiddenInput: The native html input that is visually hidden in the time field.
tsx<TimeField><TimeField.Label /><TimeField.Input><TimeField.Segment /></TimeField.Input><TimeField.Description /><TimeField.ErrorMessage /><TimeField.HiddenInput /></TimeField>
tsx<TimeField><TimeField.Label /><TimeField.Input><TimeField.Segment /></TimeField.Input><TimeField.Description /><TimeField.ErrorMessage /><TimeField.HiddenInput /></TimeField>
Example
Usage
Default Value
A TimeField displays a placeholder by default. An initial, uncontrolled value can be provided to the TimeField using the defaultValue prop.
Time values are objects: { hour?: number; minute?: number; second?: number; }.
tsx<TimeField defaultValue={{hour: 11, minute: 45}}><TimeField.Input>{(segment) => (<TimeField.Segment segment={segment()} />)}</TimeField.Input></TimeField>
tsx<TimeField defaultValue={{hour: 11, minute: 45}}><TimeField.Input>{(segment) => (<TimeField.Segment segment={segment()} />)}</TimeField.Input></TimeField>
Controlled Value
The value prop can be used to make the value controlled. The onChange event is fired when the time value changes.
Selected time: {"hour":9,"minute":45}
tsximport { createSignal, Show } from "solid-js";function ControlledValueExample() {const [value, setValue] = createSignal({ hour: 9, minute: 45 });return (<><TimeField value={value()} onChange={setValue}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField><p>Selected time:{" "}<Show when={value()} fallback={"--"}>{value()}</Show></p></>);}
tsximport { createSignal, Show } from "solid-js";function ControlledValueExample() {const [value, setValue] = createSignal({ hour: 9, minute: 45 });return (<><TimeField value={value()} onChange={setValue}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField><p>Selected time:{" "}<Show when={value()} fallback={"--"}>{value()}</Show></p></>);}
Granularity
The granularity prop allows you to control the smallest unit that is displayed by a TimeField. By default, times are displayed with "minute" granularity. More granular time values can be displayed by setting the granularity prop to "second" or an object with time slots as keys and boolean values.
tsx<TimeField granularity="second"><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField>
tsx<TimeField granularity="second"><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField>
Minimum and Maximum Values
The min and max props can be used to perform builtin validation. This marks the time field as invalid using ARIA if the user enters an invalid time.
tsx<TimeFielddefaultValue={{ hour: 9, minute: 45 }}min={{ hour: 9 }}max={{ hour: 17 }}hourCycle={12}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.ErrorMessage>Select time between 9 AM and 5 PM.</TimeField.ErrorMessage></TimeField>
tsx<TimeFielddefaultValue={{ hour: 9, minute: 45 }}min={{ hour: 9 }}max={{ hour: 17 }}hourCycle={12}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.ErrorMessage>Select time between 9 AM and 5 PM.</TimeField.ErrorMessage></TimeField>
Placeholder Value
A placeholder time can be shown instead of dashes, also influences the starting time.
tsx<TimeField placeholder={{ hour: 9 }}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField>
tsx<TimeField placeholder={{ hour: 9 }}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField>
Hour Cycle
By default, TimeField displays times in either 12 or 24 hour format depending on the user's locale. This can be overridden using the hourCycle prop.
tsx<TimeField hourCycle={12}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField>
tsx<TimeField hourCycle={12}><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input></TimeField>
Description
The TimeField.Description component can be used to associate additional help text with a time field.
tsx<TimeField><TimeField.Label>Time</TimeField.Label><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.Description>Select a meeting time.</TimeField.Description></TimeField>
tsx<TimeField><TimeField.Label>Time</TimeField.Label><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.Description>Select a meeting time.</TimeField.Description></TimeField>
Error message
The TimeField.ErrorMessage component can be used to help the user fix a validation error. It should be combined with the validationState prop to semantically mark the time field as invalid for assistive technologies.
By default, it will render only when the validationState prop is set to invalid, use the forceMount prop to always render the error message (ex: for usage with animation libraries).
tsximport { createSignal } from "solid-js";function ErrorMessageExample() {const [value, setValue] = createSignal(undefined);return (<TimeFieldvalue={value()}onChange={setValue}validationState={value() === undefined ? "invalid" : "valid"}><TimeField.Label>Time</TimeField.Label><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.ErrorMessage>Please select a time.</TimeField.ErrorMessage></TimeField>);}
tsximport { createSignal } from "solid-js";function ErrorMessageExample() {const [value, setValue] = createSignal(undefined);return (<TimeFieldvalue={value()}onChange={setValue}validationState={value() === undefined ? "invalid" : "valid"}><TimeField.Label>Time</TimeField.Label><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.ErrorMessage>Please select a time.</TimeField.ErrorMessage></TimeField>);}
HTML forms
The name prop can be used for integration with HTML forms.
tsxfunction HTMLFormExample() {const onSubmit = (e: SubmitEvent) => {// handle form submission.};return (<form onSubmit={onSubmit}><TimeField name="time"><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.HiddenInput /></TimeField><div><button type="reset">Reset</button><button type="submit">Submit</button></div></form>);}
tsxfunction HTMLFormExample() {const onSubmit = (e: SubmitEvent) => {// handle form submission.};return (<form onSubmit={onSubmit}><TimeField name="time"><TimeField.Input>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Input><TimeField.HiddenInput /></TimeField><div><button type="reset">Reset</button><button type="submit">Submit</button></div></form>);}
API Reference
TimeField
TimeField is equivalent to the Root import from @kobalte/core/time-field.
| Prop | Description |
|---|---|
| value | Time ({ hour?: number; minute?: number; second?: number; }) The current value (controlled). |
| defaultValue | Time The default value (uncontrolled). |
| onChange | (value: Time) => void Handler that is called when the value changes. |
| hourCycle | 12 | 24 Whether to display the time in 12 or 24-hour format. By default, this is determined by the user's locale. |
| granularity | 'hour' | 'minute' | 'second' | { hour: boolean; minute: boolean; second: boolean; } Determines the smallest unit that is displayed in the time field. Defaults to "minute". |
| forceLeadingZeros | boolean Whether to always show leading zeros in the hour field. |
| placeholder | Time A placeholder time shown when no value is selected, and acts as the starting point for interactions. |
| min | Time The minimum allowed time that a user may select. |
| max | Time The maximum allowed time that a user may select. |
| name | string The name of the time field. Submitted with its owning form as part of a name/value pair. |
| validationState | 'valid' | 'invalid' Whether the time field should display its "valid" or "invalid" visual styling. |
| required | boolean Whether the time field is required. |
| disabled | boolean Whether the time field is disabled. |
| readOnly | boolean Whether the time field is read only. |
| translations | TimeFieldIntlTranslations The localized strings of the component. |
| Data attribute | Description |
|---|---|
| data-valid | Present when the time field is valid according to the validation rules. |
| data-invalid | Present when the time field is invalid according to the validation rules. |
| data-required | Present when the time field is required. |
| data-disabled | Present when the time field is disabled. |
| data-readonly | Present when the time field is read only. |
TimeField.Label, TimeField.Input, TimeField.Segment, TimeField.Description and TimeField.ErrorMessage share the same data-attributes.
TimeField.Segment
| Prop | Description |
|---|---|
| segment | TimeSegment A segment of the time field. |
| Data attribute | Description |
|---|---|
| data-separator | Present when the segment is a separator. |
| data-type | Always present. |
| data-placeholder | Present when the segment's value is a placeholder. |
TimeField.ErrorMessage
| Prop | Description |
|---|---|
| forceMount | boolean Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
Rendered elements
| Component | Default rendered element |
|---|---|
TimeField | div |
TimeField.Label | span |
TimeField.Input | div |
TimeField.Segment | div |
TimeField.Description | div |
TimeField.ErrorMessage | div |
TimeField.HiddenInput | input |
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Backspace | Deletes the value in the current segment and moves focus to the previous segment when empty. |
| Delete | Deletes the value in the current segment and moves focus to the previous segment when empty. |
| ArrowRight | Moves focus to the next segment. |
| ArrowLeft | Moves focus to the previous segment. |
| ArrowUp | Increments the given segment. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
| ArrowDown | Decrements the given segment. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
| PageUp | Increments the given segment by a larger amount, rounding it to the nearest increment. The amount to increment by depends on the segment, for example 2 hours, 15 minutes, and 15 seconds. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
| PageDown | Decrements the given segment by a larger amount, rounding it to the nearest decrement. The amount to decrement by depends on the segment, for example 2 hours, 15 minutes, and 15 seconds. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
| Home | Decrements the given segment by the segment's minimum value. |
| End | Increments the given segment by the segment's maximum value. |