Skip to content

Range Time Input

Range Time Input widgets are Input Fields that allow the user to enter one or more time-of-day ranges using segmented keyboard inputs (hh:mm), with no dropdown. Each completed range is displayed as a pill that can be removed. Whether the widget renders in 12-hour or 24-hour mode follows the user’s locale, and in 12-hour mode an AM/PM segment is rendered at the locale’s position.

The widget emits an array of { start, end } objects, each holding an ISO time string (HH:mm:ss). The end time of every range must be strictly after its start time. To enter a single time, use the Time Input; for whole-day ranges, use the Range Date Input.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
label: 'Time Ranges',
}),
];

Use these props to customize your Range Time Input widget.

proptypedescription
endTimeAriaLabelstringAria label for the end time field group. Defaults to End time
hintstringA description to display below the input
hourFormat'12' | '24'Force 12- or 24-hour entry. Defaults to the user’s locale
iconstringA css class to display an icon inside the input
maxTimestringLatest allowed time (ISO time, inclusive)
maxTimeMessagestring | LocalizableError shown when a typed time is after maxTime
minTimestringEarliest allowed time (ISO time, inclusive)
minTimeMessagestring | LocalizableError shown when a typed time is before minTime
minuteStepnumberGranularity of the minute segment
rangeOrderMessagestring | LocalizableError shown when the end time is not strictly after the start time
removePillAriaLabelstringAria label for the remove pill action. Defaults to Remove time
separatorstringThe separator between start and end time fields. Defaults to -
startTimeAriaLabelstringAria label for the start time field group. Defaults to Start time

Use the property hint to add a description or validation instructions.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
hint: 'Enter one or more time ranges',
label: 'Time Ranges',
}),
];

Use the property icon to add an icon to the widget. The value of icon represents a set of CSS classes separated by spaces. The icon is displayed inside the input border.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
icon: 'schedule',
label: 'Time Ranges',
}),
];

Use the property separator to customize the text displayed between the start time and end time fields. By default the separator is -.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
separator: 'to',
label: 'Time Ranges',
}),
];

By default the 12-hour/24-hour layout comes from the locale’s hour cycle. Use the property hourFormat ('12' or '24') to force one of them.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
hourFormat: '24',
label: 'Time Ranges',
}),
];

Use the property minuteStep to control the ArrowUp/ArrowDown increment of the minute segment, useful for appointment-style forms where times snap to a grid (e.g. every 15 minutes). Typing a value is not restricted by the step. The default is 1.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
minuteStep: 15,
label: 'Time Ranges',
}),
];

Use the properties minTime and maxTime (ISO times, both inclusive) to specify the boundaries for accepted times. A completed time outside the boundaries raises an input error instead of a value; customize (and localize) the messages with minTimeMessage and maxTimeMessage. The end time of each range must be strictly after its start time, otherwise the rangeOrderMessage error is shown.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
hint: 'Office hours are 9:00 to 18:00',
minTime: '09:00:00',
maxTime: '18:00:00',
minuteStep: 15,
minTimeMessage: 'Office not open until 9:00',
maxTimeMessage: 'Office closed from 18:00',
rangeOrderMessage: 'End time must be after the start time',
label: 'Time Ranges',
}),
];

Use the properties removePillAriaLabel, startTimeAriaLabel and endTimeAriaLabel to customize the accessibility labels for screen readers. These properties are localizable.

range-time-input.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.rangeTimeInput('timeRanges', {
removePillAriaLabel: 'Delete range',
startTimeAriaLabel: 'From time',
endTimeAriaLabel: 'To time',
label: 'Time Ranges',
}),
];

Range Time Inputs can be styled as explained in the Styling Guide.

Following you will find a list with the CSS Variables and a quick description of what you will style.

CSS VariableDescription
--gui-intent-errorBorder and focus shadow color when invalid
--gui-border-focusBorder color when a pill or time segment is focused
--gui-shadow-focusBox shadow when a pill or time segment is focused
--gui-intent-primaryPill background color
--gui-color-whitePill text and remove button color
--gui-border-defaultPills wrapper border and separator border color
--gui-bg-defaultScroll shadow gradient color and dropdown background color
--gui-text-defaultActive piece (hour/minute) visual underline color
--gui-radius-mdPill and dropdown border radius
--gui-radius-fullPill count button and remove button border radius

This is the anatomy of the Range Time Input Widget in case you want to use your CSS styles.

range-time-input-anatomy.html
<gui-range-time>
<label for="fieldUid">
Label
<div class="gui-widget-hint" id="fieldUid_hint">Hint</div>
</label>
<div class="gui-widget">
<div class="gui-widget-input gui-parts-ring gui-range-time-input gui-range-time-input--icon" role="group" aria-label="Time range input">
<span class="gui-widget-icon schedule" data-icon="schedule"></span>
<!-- Completed ranges render as removable pills via the shared gui-pills element -->
<gui-pills class="gui-range-time-input__pills" role="list">
<div class="gui-pills__pill" role="listitem" tabindex="0">
<span class="gui-pills__pill-text">9:00 AM - 11:00 AM</span>
<button type="button" class="gui-pills__pill-remove" tabindex="-1" aria-label="Remove time">&times;</button>
</div>
<div class="gui-pills__pill" role="listitem" tabindex="0">
<span class="gui-pills__pill-text">2:00 PM - 2:30 PM</span>
<button type="button" class="gui-pills__pill-remove" tabindex="-1" aria-label="Remove time">&times;</button>
</div>
<!-- Collapsed into a count button when the pills overflow -->
<button type="button" class="gui-pills__pill gui-pills__pill--count">2</button>
</gui-pills>
<div class="gui-range-time-input__inputs">
<div class="gui-parts gui-range-time-input__field" role="group" aria-label="Start time">
<div class="gui-parts__touch-target gui-range-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-parts__part gui-range-time-input__part" data-type="hour" data-group="start" maxlength="2" placeholder="hh" tabindex="0">
<div class="gui-parts__visual-underline gui-range-time-input__visual-underline"></div>
</div>
<span class="gui-range-time-input__separator">:</span>
<div class="gui-parts__touch-target gui-range-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-parts__part gui-range-time-input__part" data-type="minute" data-group="start" maxlength="2" placeholder="mm" tabindex="-1">
<div class="gui-parts__visual-underline gui-range-time-input__visual-underline"></div>
</div>
<!-- Only rendered in 12-hour mode, at the locale's position -->
<div class="gui-parts__touch-target gui-range-time-input__touch-target">
<button type="button" class="gui-parts__part gui-parts__dayperiod gui-range-time-input__part gui-range-time-input__dayperiod" data-type="dayPeriod" data-group="start" tabindex="-1" aria-label="AM/PM">AM</button>
<div class="gui-parts__visual-underline gui-range-time-input__visual-underline"></div>
</div>
</div>
<span class="gui-range-time-input__separator">-</span>
<div class="gui-parts gui-range-time-input__field" role="group" aria-label="End time">
<div class="gui-parts__touch-target gui-range-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-parts__part gui-range-time-input__part" data-type="hour" data-group="end" maxlength="2" placeholder="hh" tabindex="-1">
<div class="gui-parts__visual-underline gui-range-time-input__visual-underline"></div>
</div>
<span class="gui-range-time-input__separator">:</span>
<div class="gui-parts__touch-target gui-range-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-parts__part gui-range-time-input__part" data-type="minute" data-group="end" maxlength="2" placeholder="mm" tabindex="-1">
<div class="gui-parts__visual-underline gui-range-time-input__visual-underline"></div>
</div>
<div class="gui-parts__touch-target gui-range-time-input__touch-target">
<button type="button" class="gui-parts__part gui-parts__dayperiod gui-range-time-input__part gui-range-time-input__dayperiod" data-type="dayPeriod" data-group="end" tabindex="-1" aria-label="AM/PM">AM</button>
<div class="gui-parts__visual-underline gui-range-time-input__visual-underline"></div>
</div>
</div>
</div>
</div>
</div>
</gui-range-time>