Duration Picker

A gooey, spring-animated picker for entering a duration in hours and minutes.

Dependencies

motionfigma-squircleflubberreact-use-measure@radix-ui/react-slot

Interaction Type

Click the pen to spring the segments apart and start editing — the hours field is focused for you. Type your values; anything past the ceiling (24 hr / 60 min by default) clamps to the max and shakes so you know it was corrected. Click the tick to confirm and watch the pill merge back into one piece.

Props

Options you can pass to customize this component.

Prop
Type
Description
value
{ hours: number; minutes: number }

Controlled value. Pair with onChange and the picker will mirror whatever you pass in. Leave it out to let the component manage its own state.

defaultValue
{ hours: number; minutes: number }

Starting value for uncontrolled usage. Ignored when value is provided.

onChange
(value: DurationValue) => void

Fires on every keystroke with the current clamped value — listen here if you want to react while the user types.

onConfirm
(value: DurationValue) => void

Fires once with the final value when the tick is clicked. This is usually the one you want for saving.

onEditingChange
(editing: boolean) => void

Notifies you when the picker enters or leaves edit mode — handy for blocking navigation or dimming surrounding UI while open.

defaultEditing
boolean

Render the picker already open in edit mode.

maxHours
number

Ceiling for the hours field. Typing past it clamps to this value and shakes the input.

maxMinutes
number

Ceiling for the minutes field. Same clamp-and-shake behavior as maxHours.

hoursLabel
string

Text rendered after the hours field — swap it for a translation or a terser 'h'.

minutesLabel
string

Text rendered after the minutes field.

disabled
boolean

Dims the control and blocks entering edit mode. Standard form-field behavior.

className
string

Extra classes merged onto the root. Every inner part also carries a data-slot attribute (duration-picker, -segment, -input, -toggle) plus data-editing / data-disabled states, so you can restyle from CSS alone.

Installation

npx shadcn@latest add swamimalode07/rare-ui/duration-picker

How to use

"use client"
import DurationPicker, { type DurationValue } from "@/components/ui/duration-picker"
import { useState } from "react"
export function Demo() {
const [duration, setDuration] = useState<DurationValue>({ hours: 1, minutes: 30 })
return (
<DurationPicker
value={duration}
onChange={setDuration} // fires while typing
onConfirm={(d) => console.log("saved", d)} // fires when the tick is clicked
/>
)
}
// Zero-config: it also works fully uncontrolled
// <DurationPicker onConfirm={(d) => console.log("saved", d)} />

Source Code

Click the code icon in the top-right corner to view the source code.

Keep in mind

Most components here are recreations of great work from around the web. I don't claim to be the original creator - this is my attempt to reverse-engineer, replicate, and often add a few extra features. I've tried to credit everyone; if I missed someone, let me know.

Contact

Found a bug or issue? Feel free to drop a DM.

License & Usage

  • •MIT with the Commons Clause and an attribution requirement. Free to use, modify and ship in personal and commercial projects, closed source included. You own the code once it is in your project.
  • •Credit is required. Any project shipping a Rare UI component must credit Rare UI with a visible link back to rareui.com, in a footer, an about page, a credits screen or a README.
  • •Don't strip the credit or the copyright notice from the source you copied.
  • •Don't sell, sublicense or redistribute the components themselves, on their own, bundled into a template, kit, theme or paid course, or ported to another framework.
  • •Don't republish them. No mirrors, no re-uploads, no listing them as your own work.
  • •Don't repackage the registry as a competing component library.
  • •Don't claim authorship of a component or of Rare UI itself.
  • •The LICENSE file in the repository is the full text and governs. Ask first if your use doesn't fit these rules.
Duration Picker
Hr.
Min.