Shift planner

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

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 its shifts drawn from start to end (an overnight shift running into the next morning, its hours counted on the start day or split at midnight, said); above, each need's people against its count, short ones marked; a shift made or changed in place with its break as any time, in a window or at a set time, checked against the shift; conflicts that block publishing (overlaps, impossible breaks) apart from warnings (short rest, weekly hours over contract), filterable; automatic filling that proposes shifts drawn as proposals and says the needs no one could fill, waiting for accept or discard; and Publish, asked in place, with who was told.

Use it for

  • Scheduling hourly staff for a shop, café, clinic or warehouse week by week against staffing needs.
  • Publishing a schedule only when nothing blocks it, with proposals reviewed before they count.

Not for

Anatomy

  • header: the mark, <workplace> shifts, the week
  • needs: per day each need (role, window) with assigned of required and proposed, short ones marked
  • week: a row per person (name, role, hours this week against the contract), a cell per day with a 24-hour track (shifts as bars, yesterday's overnight spill lighter, proposals outlined, conflicts red), each shift as a button (start–end, next day), add a shift on an empty day
  • editor: who and which day, From and To, the hours worked or the overnight attribution in words, A break (any time, in a window, at a set time; minutes, at, between and; paid), the break in words or what's wrong, Remove, Cancel, Save shift
  • conflicts: the count and how many block, All/Blocking, each with Blocks or Warning; Overnight hours count (start day · split at midnight)
  • publishing: open needs, Fill open needs, Accept n proposals / Discard, the needs no one could fill with why; the publish state and Publish the week (asked in place), who was told

States

  • loading
  • an overnight shift (start day or split)
  • a break outside the shift, too long, window too short
  • overlap (blocks), short rest (warning), over weekly hours (warning)
  • needs short; proposals pending (publish waits); unfilled with reasons
  • published (who was told, who couldn't be reached)

Keyboard

  • Tab through the shifts and the add buttons; Enter opens the editor
  • Publish asks in place: Enter confirms, Escape backs out

Motion

Words and the editor fade in; nothing moves at rest.

Props

PropTypeDefaultDescription
people / weekStart / needs / workplacePerson[] / string / Need[] / string—People with role, weekly limit and least rest; the week's first day; the needs (role, window, how many).
shifts / defaultShifts / onShiftsChangeShift[]—Each shift's person, start day, start and end (an end at or before the start is the next day), role, break, and whether it is only proposed.
attribution / defaultAttribution / onAttributionChange"startDay" | "calendarDay"—Which day owns overnight hours.
onAutoFill / onPublish(open) => Promise<{ proposals, unfilled }> / (shifts) => Promise<{ notified, failed }>—onAutoFill: Propose shifts for the needs not covered; resolve with the proposals and the needs no one could fill. onPublish: Publish the week; resolve with who was told. Reject: still a draft, said.
people (required)Person[]—
weekStart (required)string—The week's first day (ISO date).
shiftsShift[]—
defaultShiftsShift[]—
onShiftsChange((s: Shift[]) => void)—
needs (required)Need[]—What the workplace needs this week.
attributionAttribution—
defaultAttributionAttribution—
onAttributionChange((a: Attribution) => void)—
onAutoFill((openNeeds: Need[]) => Promise<{ proposals: Shift[]; unfilled: { needId: string; reaso…—Propose shifts for the needs not covered; resolve with the proposals and the needs no one could fill.
onPublish((shifts: Shift[]) => Promise<{ notified: number; failed: number; }>)—Publish the week; resolve with who was told. Reject: still a draft, said.
workplace (required)string—The workplace's name.
canManageboolean—
loadingboolean—
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.

Built from

Dependencies

lucide-react

Import

import { ShiftPlanner } from "@beamline/shift-planner";

Get it

Shift planner 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 rotations: 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…
  • 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.