Time field
The Time Field allows users to enter a time (HH:MM) by typing or using a dropdown with split hour and minute columns. It supports configurable hour/minute steps with free typing by default, plus an optional strict mode that enforces steps that require matching a stepped option. The control favours predictability (no reordering or injected suggestions), solid keyboard flow, and clear validation.
<sl-text-field id="first-name" value="John" aria-label="First name"></sl-text-field>When to use
The following guidance describes when to use the text field component.
Precise input and fast selection
Use the Time Field when the task requires an exact clock time and you want to accelerate entry with predictable stepped options. The split-column dropdown provides quick, scannable choices for common schedules (e.g., every 5/10/15/30 minutes) while still allowing direct typing. This is ideal for meetings, bookings, reminders, and any workflow where consistent, granular time values matter.
Keyboard navigation
Use the Time Field when forms must support speed and accessibility for keyboard-centric users. The input accepts typed values, opens the dropdown via keyboard, and allows navigation of hour/minute columns with the arrow keys. This is especially useful in dense forms, operational tooling, or power-user interfaces where mouse interaction is secondary.
When not to use
Text fields may not be the best choice in the following scenarios:
relative timeframes
Avoid the Time Field when only approximate periods or relative notions of time are needed (e.g., “morning,” “after lunch,” “end of day”). In these cases, prefer radios, a segmented control, or a select that reflects coarse time choices without implying exact HH:MM precision.
Anatomy
| Item | Name | Description | Optional |
|---|---|---|---|
| 1 | Container | Wraps input and trigger, provides focus ring and error visuals. | no |
| 2 | Input | Editable text field for time entry. | no |
| 3 | Placeholder | Hint text when no value is set (e.g., “HH:MM”). | no |
| 3 | Icon Button | Opens the dropdown. | no |
States
- Idle: Empty, showing the placeholder, or with a formatted time as the value.
- Hover: Visual hover effects that show the user that the field is interactive.
- Focus: Display the focus ring. It's shown when the field is active by clicking or keyboard navigation.
- Invalid: When an incorrect value is entered, the field is styled to indicate the error.
- Disabled: Non-interactive, muted.
Figma Options
With these options you can tweak the appearance of the text field in Figma. They are available in the Design Panel so you can compose the text field to exactly fit the user experience need for the uses case you are working on.
| Item | Options | Description |
|---|---|---|
| Open | on or off | The text field is available in two sizes. If not specified the default value is md (medium). |
| Variant | default valid invalid | When you're working on a scenario where you show what happens when a field is skipped or filled in incorrectly you can choose a different variant to show this. |
| Size | md lg | The text field is available in two sizes. If not specified the default value is md (medium). |
| Placeholder | on or off | If the setting is enabled, the placeholder will be visible, whereas if it is disabled, the user's input will be displayed. Default value is off. |
| Text | value | Use placeholder text to give the user a short hint about what they need to input (e.g. a sample value or a short description of the expected format). Placeholder is not a replacement for labels. It's an optional feature that disappears once users begin entering their data. |
| Placeholder text | value | Use placeholder text to give the user a short hint about what they need to input (e.g. a sample value or a short description of the expected format). Placeholder is not a replacement for labels. It's an optional feature that disappears once users begin entering their data. |
| Label | value | Provide users with additional context about button functionality by adding a label, ensuring clarity and ease of use. |
Behaviours
Free Typing (Default)
Users can type any valid HH:MM time, regardless of whether it is a step time. The component validates for format and parsability (e.g., two-digit hours/minutes within valid ranges). Step alignment is not enforced unless enforceSteps=true.
Stepped Options (Shortcuts)
When steps are configured, the dropdown shows fixed, non-reordering stepped options in the hour and/or minute columns. These options act as shortcuts while typed input remains unrestricted. The dropdown content and order remain unchanged regardless of the user's input.
Enforced Steps (Optional)
When enforceSteps=true, only stepped values are valid. If a user types an invalid time, a validation message appears after the field is blurred (i.e., when the user leaves the field). The typed value remains visible until corrected. The dropdown content and order still do not change.
Keyboard Navigation
Press Tab to focus the field, and then press Enter/Space to open the dropdown. Use the Arrow keys to navigate the hour and minute columns. Typing in the input updates the value; in strict mode, off-step values are validated when the field loses focus. Press Esc to close the dropdown and return focus to the input.
How to Open the Dropdown
Click on the field or dropdown button, or press Enter/Space when the field has focus.
Formatting & Validation
The control accepts and normalises valid times as HH:MM. Optional minTime / maxTime constraints may be applied with clear validation messages. When enforceSteps=true, error text should indicate the required step pattern (e.g., “Select a time in 15-minute steps: 00, 15, 30, 45”).
Related components
- Text Field: If you want a free-form text input.
- Select: Selecting from predefined numeric options.
<sl-text-field id="last-name" aria-label="Last name" value="Smith"></sl-text-field>API
Component has a range of properties to define the experience in different use cases.
Properties
| Name | Attribute | Type | Default | Description |
|---|---|---|---|---|
customValidity | custom-validity | string | undefined | The error message to display when the control is invalid. | |
dirty | - | boolean | false | A control is dirty if the user has changed the value in the UI. |
disabled | disabled | boolean | undefined | Whether the time field is disabled; when set no interaction is possible. | |
form | - | HTMLFormElement | null | The form associated with the control. | |
formValue | - | unknown | The value used when submitting the form. | |
static hourStep | hour-step | number | 1 | The default step between each hour option. |
hourStep | - | The step between each hour option. | ||
labels | - | `NodeListOf<HTMLLabelElement>` | null | The labels associated with the control. | |
locale | locale | string | The component's locale. | |
max | max | string | undefined | undefined | The maximum time selectable in the field. |
min | min | string | undefined | undefined | The minimum time selectable in the field. |
static minuteStep | minute-step | number | 5 | The default step between each minute option. |
minuteStep | - | The step between each minute option. | ||
name | name | string | undefined | The name of the form control. | |
nativeFormValue | - | FormValue | Returns the form value as used in a native `<form>`. This is always a string, File, FormData or null. | |
placeholder | placeholder | string | undefined | undefined | The placeholder for the time field. |
readonly | readonly | boolean | undefined | false | Whether the time field is readonly. |
required | required | boolean | undefined | false | Whether the time field is a required field. |
showValid | - | boolean | false | Optional property to indicate the valid state should be shown. |
showValidity | show-validity | 'valid' | 'invalid' | undefined | Whether to show the validity state. | |
start | start | string | undefined | undefined | The start time; the time that has the initial focus when the picker is opened without a value. If will use the current time if not explicitly set. |
touched | - | boolean | false | A control is marked touched once the user has triggered a blur event on it. |
valid | - | boolean | Returns whether the form control is valid or not. | |
validationMessage | - | string | String representing a localized (by the browser) message that describes the validation constraints that the control does not satisfy (if any). The string is empty if the control is not a candidate for constraint validation, or it satisfies its constraints. For true localization, see `getLocalizedValidationMessage()` instead. | |
validity | - | ValidityState | Returns the validity state the control is in. | |
validityState | - | 'valid' | 'invalid' | 'pending' | Returns the current validity state. | |
value | value | unknown | undefined | The value for this form control. |
Methods
| Name | Parameters | Return | Description |
|---|---|---|---|
renderHours | TemplateResult[] | ||
renderMinutes | TemplateResult[] | ||
reportValidity | boolean | Returns whether the control is valid. If the control is invalid, calling this will also cause an `invalid` event to be dispatched. After calling this, the control will also report the validity to the user. | |
getLocalizedValidationMessage | string | This returns a localized validation message. It does not support all `ValidityState` properties, since some require more context than we have here. If you need to support more, you can override this method in your own form control. | |
setCustomValidity | message: string | Promise<string> | void | Sets a custom validation message for the form control. If the message is not an empty string, that will make the control invalid. By setting it to an empty string again, you can make the control valid again. |
Events
| Name | Event type | Description |
|---|---|---|
sl-blur | SlBlurEvent | Emits when the focus leaves the component. |
sl-change | SlChangeEvent<string> | Emits when the value changes. |
sl-focus | SlFocusEvent | Emits when the component gains focus. |
sl-form-control | SlFormControlEvent | Emits when the form control is added to the DOM. |
sl-update-state | SlUpdateStateEvent | Emits when the UI state (dirty, pristine, touched or untouched) of the form control changes. |
sl-update-validity | SlUpdateValidityEvent | Emits when the validity of the form control changes. |
sl-validate | SlValidateEvent | Emits when the form control can be validated. |
Keyboard interactions
Here's an overview of the common keyboard interactions associated with a text field:
| Command | Description |
|---|---|
| Tab | When focus is outside the text field, moves focus to the input container. If focus is on the input container, moves focus to the end enhancer (if provided, and interactive). |
WAI-ARIA
In the component itself we use multiple aria-attributes to assure the component works well with a range of assistive technologies. For some attributes however it is not possible for the Design System to add a meaningfull value, because it relies on the context or way a component is used.
Attributes that we recommend you add in certain scenarios are mentioned below.
| Attribute | Value | Description |
|---|---|---|
aria-label | string | Defines a string that tells the user what information they need to enter in this text field. Needs to be added when the text-field is not wrapped with sl-form-field and there is no sl-label. |
aria-labelledby | string | Used to connect with single header/element that describes the text field, when there is no label component connected to. |
aria-required | boolean | Informs the user that an element is required. When set to ‘true’, screen readers notify users that the element is required. If there is already a required attribute added, it is recommended to avoid adding aria-required. |
aria-disabled | boolean | Announces the text field component as disabled with a screen reader. See [Note 1] below. |
Notes:
- The
aria-disabledshould not be used as a one-for-one replacement for thedisabledattribute because they have different functionalities:
disableddims the text field visually, takes it out of the tab-focus sequence, prevents actions (click, enter) on it and announces it as 'dimmed' or 'disabled' in a screen reader.aria-disabledonly does the latter. You will need to disable the functionality yourself. This might be useful for scenarios where you don't want to take the text field out of the navigation flow.
When disabled is added to a text field there is no need to also add aria-disabled. Everything aria-disabled does, disabled does as well. You can read more on the difference and in which scenarios which option might be preferable on the MDN page about aria-disabled.