Shift rotations

A React block (a whole screen) in Beamline's HR & payroll app.

Rotating shift patterns from pattern to people: a pattern of one to four weeks painted day by day with a shift template, a rest day or nothing (pick the brush, press the days); each day draws its shift's hours on a 0–24 h track, coloured by the time of day it runs (a light morning tone through to a deep evening one; a split shows both), each week its hours, and beside the weeks what the pattern means for a person on it: hours a week, the longest run of shift days and the shortest rest between two shifts, flagged under the rest minimum (minRestHours, default 11), all counted around the cycle's end. Assigned to people from a date, each starting at a chosen week so they don't all rest the same days: their next four weeks drawn as a dated calendar with a count of who is on each shift every day, before draft shifts are made, and people not yet in shift planning refused by name. People: everyone with their planning date, rest days, hours a week and working days (press one to open their working hours), people added to planning from a date with their rest days a week, and a contract's working hours (hours a week, working days, most a day, rest between shifts) saved as a new version from a date or as a correction of the current one, the difference said. On a phone the pattern and the four-week calendar show one week at a time with arrows to step, each pattern day a line.

Use it for

  • Setting up repeating shift patterns and rolling them out to staff.
  • Changing someone's working hours without rewriting the past by mistake.

Not for

Anatomy

  • header: the mark, the rotation's name, the view (Pattern · Assign · People)
  • pattern: Repeats every (1–4 weeks), the brushes (each template, Rest, Nothing); the grid of weeks × weekdays (each day its shift's name, times and hours on a 0–24 h track; each week its hours); the summary; Save pattern; beside it, For a person on it: hours a week, longest run, shortest rest between shifts (flagged under minRestHours)
  • assign: People, From, Stagger by a week; per person their starting week and next 28 dated days, each its shift's letter in the shift's hue or rest hatched; under them On <shift> counts per day; who isn't in planning; Make draft shifts; what was made
  • people: Shift planning (who isn't in it, from, rest days, Add to planning) over everyone (planning since or Not in planning yet, hours a week, working days; press to open); Working hours of beside it (current since; hours a week, most a day, rest between; working days; save as a new version from a date or a correction, with the warning; Save)

States

  • empty days; rest days; split shifts
  • staggered or together
  • someone not in planning (refused)
  • drafts made
  • everyone in planning
  • a limit left empty (not checked)
  • new version or correction

Keyboard

  • the brushes are a radio group; each day is a button: Enter paints it with the brush
  • Tab through the people and dates

Motion

Swatches change on painting; words fade in. Nothing moves at rest.

Props

PropTypeDefaultDescription
templates / rotation / defaultRotation / onRotationChange / onSaveRotationShiftTemplate[] / Rotation / (r) => Promise—Templates with their intervals and a shade; the rotation as weeks of seven days (a template id, rest or null).
staff / defaultStaff / onStaffChangeStaffMember[]—Each person's planning start (null: not in planning), rest days and current contract version.
onAssign / onEnroll / onSaveContract / today(a) => Promise<{ drafted }> / (ids, from, restDays) => Promise / (id, v, mode) => Promise / string—Make draft shifts with each person's starting week; add to planning; save a contract as correct or new.
templates (required)ShiftTemplate[]—
rotationRotation—
defaultRotationRotation—
onRotationChange((r: Rotation) => void)—
onSaveRotation((r: Rotation) => Promise<unknown>)—
staffStaffMember[]—
defaultStaffStaffMember[]—
onStaffChange((s: StaffMember[]) => void)—
onAssign((a: { rotationId: string; personIds: string[]; from: string; offsets: Record<string, n…—Make draft shifts for people from a date, each starting at a week of the pattern; resolve with how many.
onEnroll((personIds: string[], from: string, restDays: number) => Promise<unknown>)—Add people to shift planning from a date.
onSaveContract((personId: string, v: ContractVersion, mode: "new" | "correct") => Promise<unknown>)—Save a contract's working hours: a correction of the current version, or a new one from a date.
today (required)string—
defaultView"assign" | "pattern" | "people"—
canManageboolean—
productstring—
classNamestring—Classes on the documented visual root; no override by default.
refRef<HTMLDivElement>—Receives the documented native target or imperative handle; omitted by default.
minRestHoursnumber—The rest between two shifts a pattern is checked against, in hours; a shorter one is flagged. Default 11.

Built from

Dependencies

lucide-react

Import

import { ShiftRotations } from "@beamline/shift-rotations";

Get it

Shift rotations is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. Get Beamline · Connect your agent

More in HR & payroll

  • Shift planner: A workplace's week of staff shifts against what it needs: a row per person with their week's hours against their contract, each day a 24-hour track with…
  • Roster publishing: The week's roster before it goes out: areas down the side and days across, each shift a chip with who works it and its hours, its state its tone (not…
  • My shift: The worker's own shift on their phone: today drawn to scale (the plan's areas as blocks on an hour axis, under them what was worked: on-plan time in…
  • Timesheet review: Timesheets for a manager: the day's counts at the head (scheduled, on shift, late, on break, to approve), the ones that filter being buttons, an…
  • Hours ledger: One worker's pay cycle of shifts, for the worker or their payroll admin: the wall-clock span and the paid hours as separate columns, a night shift…
  • Payroll run: A pay period from report to submission, one payroll account at a time (a worker on two accounts is on both runs, never combined): the workers on one…
  • Payroll cycles: The client's side of an outsourced payroll across countries: every entity's current cycle on one board, its stage drawn as steps, the one thing that…
  • Payroll approvals: Payroll approvals for a company paying through a payroll provider. Expenses are split by whose move it is (you, another approver, the employee answering…
  • Benefit changes: An employee's benefit changes after a life event. The centre puts their turn first: each task (a proof to upload, with its deadline in the warning tint…
  • Hiring pipeline: A recruiting team's pipeline across every open job. Stage groups (reviewing, interviewing, closing) are counted across jobs above job sections that fold…
  • Recruiter home: A recruiter's own work, in one place. Upcoming interviews with who sits in, today's first; feedback owed, overdue first and on the danger tone, written…
  • Stage reports: Reports on how applications move through stages, built from each application's stage intervals. By week: applications present in each stage (or from each…
  • Link booking: A candidate's booking link for one stage of one job: a column with the job, the stage's length, who they meet (each with their role), where and what the…
  • Team & members: The people page of a workspace: seats used against the plan, members and pending invitations in one list with search and a role filter, role changes that…

Part of Beamline UI: polished, editable React components and complete screens for custom applications. Build your own style from any look; tokens, fonts, radii, motion; not only colours.