Skip to content

Day Ring

Show scheduled runs on a daily dial, with overlaps and the next run highlighted, such as a job schedule.

import { DayRing, ScheduleJob, ScheduleOverlap } 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 a day ring where people plan recurring work around the clock: cron jobs, backups, report exports, maintenance windows. Each job gets its own track, so a day of runs reads at a glance, and where runs of different jobs collide a warning zone brackets them and a marker points at it from outside the ruler. For a timeline of what already happened, use a Timeline; for one bounded value, a Gauge.

import { DayRing, findOverlaps } from '@youj/react'

const jobs = [
  { id: 'backup', name: 'backup-db', runs: [120], duration: 40 },
  { id: 'reindex', name: 'reindex-search', runs: [150], duration: 25 },
  { id: 'sync', name: 'sync-crm', runs: [15, 255, 495, 735, 975, 1215], duration: 10 },
]

<DayRing jobs={jobs} timeZone="UTC" />
findOverlaps(jobs) // [{ start: 150, end: 160, jobs: ['backup', 'reindex'] }]

runs are the starts today, in minutes after midnight, in timeZone (default: the browser's). A job with a duration draws its runs as arcs as long as they take; without one, as ticks. tone picks the job's color (the chart colors in turn by default), and paused draws it dim and dashed and leaves it out of every collision. highlight keeps one job lit, dims the rest and counts down to its next run: point it at the row a person is hovering in your own list. now pins the clock (tests, screenshots); by default it's live, and on the server there's no hand or countdown until the browser has the time.

Reference

Propsjobs, now, timeZone… (7)

Props

DayRing props
PropType
jobsRequiredreadonly ScheduleJob[]–
nowDate | number

The time the hand shows. Default: the live clock.

–
timeZonestring

The time zone the runs are in. Default: the browser's.

–
highlightstring

A job id: its runs stay lit, the others dim, and the center counts down to its next run.

–
localestring

Default: the YoujProvider locale.

–
labelstring

Accessible name. Default: the labels' "Daily schedule".

–
nextLabelstring

The center's caption over the countdown. Default: the labels' "Next run".

–
formatTime(minute: number) => string

Formats a minute of the day. Default: the locale's 24-hour HH:mm.

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

Styling

Parts: day-ring, day-ring-svg, day-ring-ruler, day-ring-elapsed, day-ring-hour, day-ring-track, day-ring-overlap (with data-jobs), day-ring-runs (a job's group, with data-job, data-tone, data-paused, data-highlighted and data-dimmed), day-ring-run (with data-minute), day-ring-hand, day-ring-center, day-ring-label, day-ring-next, day-ring-value and day-ring-description. It fills its box's width up to 20rem; the center's type scales with it.

MotionFirst view, hand, A run moves… · reduced motion

Motion

Motion tokens
MomentTokens
First viewthe runs appear as a radar pass: each fades in a step later the further round the day it sits
duration.deliberate

560ms

560ms
Handturns from midnight to now on the smooth spring, with the elapsed shading on the same spring; then it steps each minute
spring.smooth

0.36s, bounce 0

0.36s, bounce 0
A run movesit glides round its track to the new time
duration.slowease.standard

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

340mscubic-bezier(0.2, 0, 0, 1)
Highlightthe other jobs fade down
duration.fastease.standard

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

140mscubic-bezier(0.2, 0, 0, 1)
Collisionszones fade in and out as runs move or jobs pause
duration.baseease.enter

220ms · cubic-bezier(0.16, 1, 0.3, 1)

220mscubic-bezier(0.16, 1, 0.3, 1)

Reduced motion

Drawn in place; a run that moves jumps. The countdown still ticks.

Reduced motion

Every run and the hand are drawn in place, with no radar pass; runs that move jump. The countdown keeps ticking: it's information, not motion.

AccessibilityARIA, announcements

Accessibility

  • The ring is an image (role="img") named by label (default: the labels' "Daily schedule") and described in words: how many runs a day, how many collisions, the next run, and one sentence per collision ("backup-db and reindex-search overlap at 02:30").
  • The countdown isn't live, so it doesn't talk every second; announce a start yourself if the page needs it.
  • A dial turns clockwise in every script, so the ring keeps its direction under RTL; the text in the center follows the page.
  • Its words come from the labels (dayRing, nextRun, runsIn, scheduleRunAt, scheduleRuns, scheduleOverlaps, scheduleOverlapAt), translated by the language packs.