Skip to content

Hours Dial

Set a window of the day on a 24-hour face, with two handles that may run past midnight.

import { HoursDial, HoursDialValue } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use an hours dial for a stretch of the day: a sleep schedule, quiet hours, a shift, opening hours. The face is a whole day, midnight at the top and turning clockwise, with a ruler of quarter-hour ticks all the way round. A hollow handle marks the start and a solid one the end; the ticks between them light in the tone, and the center reads the length large in mono with the two times under it. For one bounded value on an arc, such as a temperature or a volume, use a Dial; for a single time, a Time Picker.

import { HoursDial } from '@youj/react'

<HoursDial
  label="Sleep schedule"
  caption="Asleep"
  value={sleep}
  onValueChange={setSleep}
/>

The value is { start, end } in minutes after midnight (0–1439); an end before the start runs past midnight, so { start: 1350, end: 420 } is 22:30 to 07:00. step (15 minutes) is what an arrow key moves and what a drag snaps to, and largeStep (an hour) is what Page Up and Down move. The handles never meet: the window stays at least a step long and a step short of a whole day. tone colors the lit stretch (the accent, a chart color or neutral), caption puts a mono capital over the length, and the times read in the provider's locale (12- or 24-hour as it writes them). It's uncontrolled with defaultValue.

Reference

Propsvalue, defaultValue, onValueChange… (11)

Props

HoursDial props
PropType
valueHoursDialValue–
defaultValueHoursDialValue

default { start: 22 * 60 + 30, end: 7 * 60 }

{ start: 22 * 60 + 30, end: 7 * 60 }
onValueChange(value: HoursDialValue) => void–
stepnumber

Minutes per arrow key and the snap of a drag; a divisor of 60 suits best.

default 15

15
largeStepnumber

Minutes per Page Up/Down.

default 60

60
toneHoursDialTone
'accent''neutral''chart-1''chart-2''chart-3''chart-4''chart-5'

The lit stretch's color.

default 'accent'

'accent'
localestring

Default: the YoujProvider locale.

–
labelstring

Accessible name of the pair of handles. Default: the labels' "Time range".

–
captionReactNode

A mono capital over the length: "Asleep".

–
disabledboolean

default false

false
soundboolean

Plays the tick cue at every step.

default true

true
Other props pass through: extends ComponentProps<'div'>.
StylingParts and data attributes

Styling

Parts: hours-dial (with data-tone, data-dragging set to start, end or window while a pointer holds it, and data-disabled), hours-dial-face, hours-dial-band, hours-dial-ruler, hours-dial-range, hours-dial-numerals, hours-dial-start and hours-dial-end (the handles, with data-dragging), hours-dial-center, hours-dial-label, hours-dial-value and hours-dial-times.

MotionKeyboard or click, drag, hover or drag · reduced motion

Motion

Motion tokens
MomentTokens
Keyboard or clickthe handles and the lit stretch glide to the new times together, the short way round, retargeting mid-flight
spring.snappy

0.2s, bounce 0

0.2s, bounce 0
Draga handle, or the whole window, follows the pointer 1:1, snapping to the step
duration.instantease.standard

80ms · cubic-bezier(0.2, 0, 0, 1)

80mscubic-bezier(0.2, 0, 0, 1)
Hover or dragthe handle grows a little
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)

Reduced motion

Every change jumps.

Reduced motion

The handles and the lit stretch jump to each new time.

AccessibilityKeyboard, focus

Accessibility

  • It's a group named by label (default: the labels' "Time range") holding two sliders, "Start" and "End", each valued in minutes after midnight. Their value text is the time and the window's length in the locale ("10:30 PM, 8 hours, 30 minutes in all").
  • Arrows move a handle by the step, Page Up and Down by an hour, Home to midnight and End to the last step before it; steps wrap round midnight. A press on the face focuses the handle it moves, so the keys carry on from there.
  • A clock turns clockwise in every script, so the face and its keys keep their direction under RTL: right and up move later. The text in the center follows the page.
  • Every step plays the tick cue, like a detent, behind sound (on by default).
  • Its words come from the labels (hoursDial, hoursDialStart, hoursDialEnd, hoursDialValue), translated by the language packs.