Duration Picker

A gooey, spring-animated picker for entering a duration in hours and minutes. Click the pen to spring the segments apart and start editing; click the tick to confirm and watch the pill merge back into one piece.

Last updated October 20, 2018

CreditsModifiedPublished

Copied from Rare UI.

  • Removed @radix-ui/react-slot and restored asChild via @base-ui/react/use-render (Base UI's Slot equivalent), so the toggle segment supports composition with no Radix dependency
  • Snappier springs per animation-review (gap 380/30/mass 0.9, width and icon 400/32, sway 320/26, error shake 700/14) to remove the upstream lag while keeping the gooey overshoot
  • active:scale-90 softened to active:scale-[0.96] with a 100ms ease-out press transition and a focus-visible ring on the toggle
  • Added a dir prop (auto-detected from the nearest [dir] ancestor); under RTL the gooey gap opens on the inline-end side, the squircle outer corners flip, and pl-2 became logical ps-2

Overview

Installation

$ pnpm dlx shadcn@latest add @persianlabsui/duration-picker

Usage

"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)} />

RTL

Under RTL the gooey gap opens on the inline-end side, the squircle's outer corners flip to the outer edge, and the labels can be swapped for Persian (hoursLabel="ساعت" minutesLabel="دقیقه").

API Reference

DurationPicker