Interval Dropdown Time Picker
A native select of times generated on a fixed interval, so the value always lands on the grid.
3 frameworksBeginner
Hours and minutes selects that edit a single total-minutes value with a live summary.
<div class="w-full max-w-sm">
<span class="mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300">Duration</span>
<div class="grid grid-cols-2 gap-3">
<div>
<label for="dur-hours" class="mb-1 block text-xs text-gray-500 dark:text-gray-400">Hours</label>
<select id="dur-hours" class="w-full appearance-none rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:focus-visible:ring-blue-400">
<option value="2" selected>2</option>
</select>
</div>
<div>
<label for="dur-minutes" class="mb-1 block text-xs text-gray-500 dark:text-gray-400">Minutes</label>
<select id="dur-minutes" class="w-full appearance-none rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:focus-visible:ring-blue-400">
<option value="30" selected>30</option>
</select>
</div>
</div>
<p class="mt-3 text-sm text-gray-600 dark:text-gray-400" aria-live="polite">Total: <span class="font-semibold tabular-nums text-gray-900 dark:text-gray-100">2h 30m</span></p>
</div>| Prop | Type | Default | Description |
|---|---|---|---|
valuerequired | number | - | The metric's current value, pre-formatted. |
onChangerequired | (minutes: number) => void | - | On change |
maxHours | number | 12 | Max hours |
minuteStep | number | 5 | Minute step |
className | string | - | Additional classes merged onto the root element. |
The component edits one `value` in total minutes and reports it back the same way, so callers never juggle two fields; a polite `aria-live` line echoes the running total. Bound the range with `maxHours` and thin the minute list with `minuteStep`.