001500

Stops after 15m

Saved as 900000 ms

Try it: click a box, type 90, then press m.

Keyboard

↑↓
Step the focused unit
PageUpPageDown
Step by ten
HomeEnd
Jump to the unit's min or max
←→
Move between units
Backspace
Clear the unit

The CLI also installs the npm packages and registry items it builds on, and reads the style in your components.json to pick the Base UI or Radix build.

duration-input-usage.tsx
import { DurationInput } from "@/components/ui/duration-input"

export function TimeoutField({
  value,
  onChange,
}: {
  value: number | null
  onChange: (value: number | null) => void
}) {
  return (
    <DurationInput
      aria-label="Execution timeout"
      value={value}
      onValueChange={onChange}
      units={["h", "m", "s"]}
      max={86_400_000}
    />
  )
}

DurationInput

Segmented duration input with typed shorthand and unit navigation. The root has role=group, so pass aria-label or aria-labelledby.

Prop
valuenumber | nullControlled duration in milliseconds.
defaultValuenumber | nullDefaultnullInitial value when uncontrolled.
onValueChange(value: number | null) => voidCalled with the duration in milliseconds, or null when cleared.
units("w" | "d" | "h" | "m" | "s" | "ms")[]Default["h", "m", "s"]Visible duration segments.
minnumberDefault0Minimum duration in milliseconds.
maxnumberMaximum duration in milliseconds.
stepnumberDefault1Amount arrow keys step the focused segment by.
disabledbooleanDisables interaction across every segment.
namestringSubmits the milliseconds value through a hidden input.

Other props go to the <div>.

Choose the units

units sets which segments appear. Values stay in milliseconds whichever you pick.

20
02500

Limits and steps

min and max clamp the total in milliseconds, and step sets how far arrow keys move a segment.

0030

Between 5 minutes and 4 hours.

Forms

name submits the milliseconds through a hidden input.

000130
components/ui/duration-input.tsx
CtrlK