Changes to @umriss-ui/schedule
This document describes what changes for callers of the package: exports, props, behaviour.
The numbers. The middle digit rises when something is added; the last one
when something is repaired. As long as the first digit is 0, no number
promises compatibility — which is why whatever changes existing behaviour stands
under a heading "Changed" of its own, no matter which digit rose.
From 0.34.0 the packages share one number - five, and six from 0.40.0, when the dashboard joined: they are released together, and a package without a change of its own still gets a heading for it.
Release candidates. The package started as a release candidate under the
tag next. With 0.1.0 it is released: the tag is gone, and the interface
moves from here under the rule above.
0.40.0 – No change of its own (Oct. 2026)
Released with the other five packages under their one number. No change of its own.
0.39.0 – No change of its own (Oct. 2026)
Released with the other four packages under their one number. No change of its own.
0.38.0 – No change of its own (Oct. 2026)
Released with the other four packages under their one number. No change of its own.
0.37.0 – No change of its own (Oct. 2026)
Needs @umriss-ui/core and @umriss-ui/charts 0.37; the peer ranges are
^0.37.0. No change of its own.
0.36.0 – No change of its own (Oct. 2026)
Needs @umriss-ui/core and @umriss-ui/charts 0.36; the peer ranges are
^0.36.0. No change of its own.
0.35.0 – React 19 is the floor, and a hover that leaves the plan alone (Oct. 2026)
Needs @umriss-ui/core and @umriss-ui/charts 0.35; the peer ranges are
^0.35.0.
Changed
React 19 is required. The peers
reactandreact-domare>=19;0.34.0is the last version that serves React 18.refis a prop of the schedule.SchedulePropsdeclares it asRef<ScheduleHandle>, and the component is noforwardRefobject any more. The handle arrives as it did.The package ships ES2022 syntax. An application that serves older browsers transpiles it itself.
Otherwise
A hover redraws what the hover shows. A pointer moving along a bar published the whole plan again and drew both canvases on every event; it now publishes the tooltip and the cursor and draws the overlay alone. At 5,000 subtasks the frame of a hover ends after 17 ms where it took 24 ms - the figure of a plan of 200.
A pan or a zoom lays the plan out once per frame, however many events the frame holds, and a dependency wholly outside the view is not stroked.
0.34.0 – A view is set, not handed back (Oct. 2026)
From this version all five packages carry one number and are released
together. Needs @umriss-ui/core and @umriss-ui/charts 0.34; the peer ranges
are ^0.34.0.
Changed
initialViewis read once, andsetViewis new. A differentinitialViewon a later render is now ignored, as React ignores a changeddefaultValue; it used to be applied whenever its content differed from the last one handed in. To go to a view later, call the newsetView(view)thatuseSchedulereturns: it applies a whole view, and what the view leaves out goes back to its default.setViewis not reported throughonViewChange, which reports what the planner did, so two schedules kept in step byonViewChange: (v) => other.setView(v)in both directions do not answer each other. A caller that kept the reported view in state and handed it back asinitialViewwritessetViewinstead: restoring a kept view issetView(kept), and the state that mirrors the schedule's view becomesviewfrom the hook.
0.7.1 – Core 0.33.0, charts 0.16.0 (Oct. 2026)
Needs @umriss-ui/core 0.33 and @umriss-ui/charts 0.16; the peer ranges move to ^0.33.0 and ^0.16.0.
Added
- The unit tests run against React 18.3.1 and 19 in CI, and a schedule is rendered to a string with no
windowin a test (tests-unit/ssr.test.tsx): its labelled frame and empty canvases.
Changed
Every entry begins with
"use client";. The built filedist/schedule.jsstarts with the directive, then the stylesheet import, so a bundler that splits server from client code takes each as client code. The directive is written to the built entries only; the sources are unchanged.Every export is a client component. A hook called in a Server Component now fails with React's message about a client reference, not one about
useState.
0.7.0 – The summary counts the milestones (Oct. 2026)
Needs @umriss-ui/core 0.32; the peer range moves to ^0.32.0.
Added
- Milestones in the summary: the plot's description names how many milestones the plan shows ("2 milestones."), and nothing where there are none. Needs
@umriss-ui/corewith the newscheduleSummaryargument.
0.6.0 – Milestones (Oct. 2026)
Needs @umriss-ui/core 0.31 and @umriss-ui/charts 0.15; the peer ranges move to ^0.31.0 and ^0.15.0.
Added
<Milestones data />. A point in time on a lane, drawn as a diamond above the work: plain data{ id, lane, at, label? }, declared inside theSchedulelikeBlockedTimesand handed out byuseSchedule. It is read-only - not dragged, no intent, no finding. The tooltip names it by label (or id) and time, and the keys walk to it in time order among the work of its lane. New typesMilestoneandMilestonesProps; the words come from core's newscheduleMilestonewording ("Milestone: Release"), so it needs a core with it.
Changed
ScheduleTooltipTargetandScheduleHithave a third kind,"milestone". Atooltipfunction of your own that readstarget.taskortarget.violatedwithout checkingtarget.kindfirst no longer type-checks; add a case for the milestone (target.milestone) or returnnullfor it.
0.5.7 – Charts 0.14.0 (Oct. 2026)
Needs @umriss-ui/charts 0.14; the peer range moves to ^0.14.0. Nothing else changes for a caller.
0.5.6 – Core 0.30.0, charts 0.13.0 (Oct. 2026)
Needs @umriss-ui/core 0.30 and @umriss-ui/charts 0.13; the peer ranges move to ^0.30.0 and ^0.13.0. Nothing else changes for a caller.
0.5.5 – Core 0.29.0 (Oct. 2026)
Needs @umriss-ui/core 0.29; the peer range moves to ^0.29.0. Nothing else changes for a caller.
0.5.4 – Core 0.28.0 (Oct. 2026)
Needs @umriss-ui/core 0.28; the peer range moves to ^0.28.0. Nothing else changes for a caller.
0.5.3 – Core 0.27.0 (Oct. 2026)
Needs @umriss-ui/core 0.27; the peer range moves to ^0.27.0. Nothing else changes for a caller.
0.5.2 – Core 0.26.0 (Oct. 2026)
Needs @umriss-ui/core 0.26; the peer range moves to ^0.26.0. Nothing else changes for a caller.
0.5.1 – Charts 0.12.0 (Oct. 2026)
Needs @umriss-ui/charts 0.12; the peer range moves to ^0.12.0. Nothing else changes for a caller.
0.5.0 – Declared through useSchedule, with a view of its own (Oct. 2026)
Released together with @umriss-ui/charts and @umriss-ui/table, which
break in the same release. A schedule is declared through useSchedule, as a
table is through useTable and a chart through useChart (ADR-0048), and it
holds its own view - the span in view and the folded lane groups -, taken
as a start and reported whole (ADR-0047). The free components and the
controlled pairs are removed, not deprecated.
Changed
Moving over. Every export and prop that went, and what stands in its place:
| Was | Is |
|---|---|
import { Schedule, Lane, LaneGroup, Subtasks, Dependencies, BlockedTimes } |
const { Schedule, Lane, … } = useSchedule() - one Schedule per call; a ref on it still gives the ScheduleHandle |
Schedule initialDomain (required) |
useSchedule({ initialView: { domain } }); without a span the schedule shows the extent of its subtasks |
Schedule collapsedGroups (controlled) |
view.folded, and toggleGroup, foldAll, unfoldAll from useSchedule; or a new initialView: { folded } |
Schedule defaultCollapsedGroups |
useSchedule({ initialView: { folded } }) |
Schedule onCollapsedGroupsChange |
useSchedule({ onViewChange }), view.folded |
Schedule onDomainChange |
useSchedule({ onViewChange }), view.domain |
Scheduleand its parts are no exports of their own.useSchedule()hands them out; they keep their identity over every render. Their props stay public types.- A span is optional.
initialDomainwas required; without adomainin the view the schedule shows the extent of its subtasks, lead-in and lead-out included, widened or narrowed around its middle intozoomLimits- fitted once, not after every change of the data, so a dragged bar does not make the plan jump; without subtasks the local day of today. - A view handed in applies by its content.
initialDomainwent back to a new pair of values;initialViewapplies whenever it differs in content from the last one handed in - the folded groups compared as a set -, the same view again changes nothing, and what it leaves out is reset. A group id no group carries falls out. A known limit: a view handed in that equals one the schedule reported less than a second ago, and that has not come back yet, is taken for the schedule's own report coming back late and is not applied - so that linked schedules do not jump back mid-pan. An application that restores a just-reported view within that second sees no change. - One report for both.
onViewChange(view)replacesonDomainChangeandonCollapsedGroupsChange: every change once, always the whole view, a pan or zoom at most once per frame, not the view the schedule starts with.selectedTaskandonSelectedTaskChangeare a selection, not the view, and stay as they are; so doeszoomLimits.
Added
useSchedule({ initialView, onViewChange })withview,setDomain(span | null)(null= the subtasks' extent),toggleGroup(id),foldAll()andunfoldAll()on what it hands back.- Types:
ScheduleParts,ScheduleOptions,ScheduleView. - The demo has a page 'View' (keep a view across a reload and restore
it); 'Linked schedules' keep in step through a shared view, and Lane
groups' "Fold groups from outside" folds through the setters, at the
anchor
#fold-from-outside- the old#controlledlands there.
0.4.0 – Every export explained, and lane counts in every language (Oct. 2026)
The package explains itself where it is used: every export carries a comment,
every default a @default tag, and the demo lists all of it in an API index
(ADR-0044). A group's lane count is fitted anew when the language changes.
Needs @umriss-ui/core 0.25 and @umriss-ui/charts 0.10; the peer ranges move
to ^0.25.0 and ^0.10.0.
Added
- The First schedule page says what a screen reader meets: a section
Accessibility after Keyboard names the plot's role, name and summary, the
readout after a key, the label to pass and what forced colours and reduced
motion change. Every other page with a schedule in its examples has a
Keyboard section linking First schedule's keys; Dependencies and Pan and
zoom also list the keys of their own feature there. In the demo, the
Markdown twins and
docs/llms-full.md; the schedule is unchanged. - Every export carries a comment: what a component, a function or a type is
for, and for a function
@paramand@returnswhere its type alone does not say it. The editor shows it on hover, from the package's.d.ts. Nothing else changes. - A prop's default stands in a
@defaulttag where its comment used to say it in words: the editor shows it on hover, and the props table in its Default column. Nothing else changes. docs/llms-full.mddefines every type a props table names: a type without a table of its own (Intent, the charts'WorkingCalendar) stands under "Types on this page" of each page that names it, with its comment and its members or its declaration.- The demo has an API index:
/schedule/api/, the last entry of the sidebar, lists every export of@umriss-ui/schedule, grouped as components, functions, constants and types, alphabetical - each value with its comment and its declaration, each type with a link to its table or its definition, and the pages that use it. A hook or a function a page names, in its text or its import line, leads to its entry.docs/llms-full.mdends with the same index, in place of the appendix "The rest of the API". The library is unchanged. - Every prop of a props table is shown, or named as an exception: new
examples for groups that start folded (
defaultCollapsedGroups), one handover drawn its own way (a dependency'sattachandends) and a tooltip that says what a bar covers and a line joins (subtask,blocked,dependency,from,to); the list of findings now writesdepartureandarrival, and "Report the pointer" names the lane, as its lead promised. The two props left without an example,classNameandstyle, are pass-throughs; the demo's list says so. The schedule is unchanged.
Fixed
- A group's lane count is measured anew when the language changes: a wording switched under a mounted schedule (English to German, say) left the counts as the old wording had fitted them, so "2 Bahnen" stood beside a cut name. Now the name wins over the count in every language, as it already did after a reload - measured anew whenever the header column changes size or anything it shows changes, a custom label's content included.
docs/llms-full.mdnames the peers in its install line:npm install @umriss-ui/schedule @umriss-ui/core @umriss-ui/charts, read from the manifest. It had named the schedule alone, and an install after it lacked core and charts.
0.3.16 – Core 0.24.0 (Oct. 2026)
Needs @umriss-ui/core 0.24; the peer range moves to ^0.24.0. Nothing else changes for a caller.
0.3.15 – Core 0.23.0 (Oct. 2026)
Needs @umriss-ui/core 0.23; the peer range moves to ^0.23.0. Nothing else changes for a caller.
0.3.14 – Core 0.22.0 (Oct. 2026)
Needs @umriss-ui/core 0.22; the peer range moves to ^0.22.0. Nothing else changes for a caller.
0.3.13 – Core 0.21.0 (Oct. 2026)
Needs @umriss-ui/core 0.21; the peer range moves to ^0.21.0. Nothing else changes for a caller.
0.3.12 – Core 0.20.0 (Oct. 2026)
Needs @umriss-ui/core 0.20; the peer range moves to ^0.20.0. Nothing else changes for a caller.
0.3.11 – Charts 0.9.0 (Oct. 2026)
Needs @umriss-ui/charts 0.9; the peer range moves to ^0.9.0. Nothing else changes for a caller.
0.3.10 – Core 0.19.0 (Oct. 2026)
Needs @umriss-ui/core 0.19; the peer range moves to ^0.19.0. Nothing else changes for a caller.
0.3.9 – Core 0.18.0 (Sep. 2026)
Needs @umriss-ui/core 0.18; the peer range moves to ^0.18.0. Nothing else changes for a caller.
0.3.8 – Core 0.17.0 (Sep. 2026)
Needs @umriss-ui/core 0.17; the peer range moves to ^0.17.0. Nothing else changes for a caller.
0.3.7 – Room on a phone (Sep. 2026)
Needs @umriss-ui/core 0.16 and @umriss-ui/charts 0.8.2; the peer ranges move to ^0.16.0 and ^0.8.2.
Changed
- On narrow days a date covers a run of days - 1, 2, 7, 14 or 28, counted from Mondays - in both bands: a ten-day plan on a phone wrote a date under every midnight, and they ran into each other.
- A lane group's name wins over its count: where a name in the header column would be cut, every count in that column gives way.
- A text lane label may take a second line where its row is tall enough for two.
0.3.6 – Core 0.15.0 (Sep. 2026)
Needs @umriss-ui/core 0.15; the peer range moves to ^0.15.0. Nothing else changes for a caller.
0.3.5 – Found by search (Sep. 2026)
Fixed
- The package's description and keywords say what it is in the words a
search uses, and the demo it links to addresses every page by a path
(
…/schedule/<page>/) instead of a hash, with the page's text readable before the demo starts. Old#/<page>links still land. Nothing in the package's code changed.
0.3.4 – Core 0.14.0 (Sep. 2026)
Needs @umriss-ui/core 0.14; the peer range moves to ^0.14.0. Nothing else changes for a caller.
0.3.3 – What you are working with (Sep. 2026)
Changed
- A selection steps the rest of the plan back. The subtask that was
clicked keeps its task's full colour, the other subtasks of its task go
halfway to grey, and all other work - bars, dependencies, the strips of a
folded group - goes grey. The grey is the colour's own lightness without
its hue, so a label keeps its colour and greyed work never reads as
"muted", which grows lighter instead. Findings keep their colours. A task selected by its dependency, or throughselectedTaskalone, stays whole in its colour; the ghost of a drag is always in full colour. Under forced colours the selected task stays in the text colour and the rest takesGrayText. Nothing to change for a caller: the picture follows the selection the schedule already has.
0.3.2 – Core 0.13.0 (Sep. 2026)
Needs @umriss-ui/core 0.13; the peer range moves to ^0.13.0. Nothing else changes for a caller.
0.3.1 – Core 0.12.0 (Sep. 2026)
Needs @umriss-ui/core 0.12; the peer range moves to ^0.12.0. Nothing else changes for a caller.
0.3.0 – Dependencies and blocked time (Sep. 2026)
Needs @umriss-ui/core 0.11 and @umriss-ui/charts 0.8: it reads the renamed wording keys, the new ones for blocked time, and the charts' working-time functions; the peer ranges move to ^0.11.0 and ^0.8.0.
Added
- Blocked time per lane.
<BlockedTimes data={…} />takes a list ofBlockedTime—{ id, lane, from, to, label? }, plain data keyed by lane like a subtask — for leave, maintenance and any other time a lane is not available. It is drawn hatched behind all the work on the lane, in forced colours too, wherever the layer is declared. - A finding: a subtask in blocked time.
inBlockedTime(subtasks, blocked)returns every subtask that covers blocked time on its lane (lead-in and lead-out included) asInBlockedTime—{ subtask, blocked, lane, from, to }.findings()takes the blocked time as an optional third argument, andFindingshas the fieldinBlockedTime. The schedule marks the covered time like an overlap; the tooltip and the keys' readout name it ("In blocked time (Leave)"), and the plot's description counts it where there is any.ScheduleTooltipTargetof kind"subtask"carriesblocked, the blocked times the subtask covers. - Blocked time is part of where a subtask may go. A drag — inside the plot
or from outside — does not put work into blocked time it did not already
cover: the ghost stays where it was allowed, the cursor says no, a line ties
the ghost to the pointer, and its label says "Blocked time" (
data-blockedon the ghost label). Alt with an arrow key steps over blocked time instead of into it; Alt+Shift does not stretch into it. Work the data already put there is never locked in. - A demo page, Blocked time.
Changed
Neutral names for the schedule's terms (ADR-0035). The schedule is for any plan of work on lanes, and its names said "plant": a transport is now a dependency with a lag, setup and teardown are lead-in and lead-out, and a late transport is a violated dependency — with every name built on them. One hard cut, no deprecated aliases. What the terms do is unchanged: a dependency still joins two subtasks of one task, from an end to a start, and its anchors decide whether it is violated.
]/[andt/Shift+T still walk along it. The tooltip, the ghost, the readout and the summary say "Lead-in", "Lead-out", "Dependency" and "Violated dependency" (German "Vorlauf", "Nachlauf", "Abhängigkeit", "Abhängigkeit verletzt").Before Now Subtask.setupSubtask.leadInSubtask.teardownSubtask.leadOutPlaceIntent.setup,.teardownPlaceIntent.leadIn,.leadOutPlacingItem.setup,.teardownPlacingItem.leadIn,.leadOutSetupIntent(kind: "setup", fieldsetup)LeadInIntent(kind: "leadIn", fieldleadIn)TeardownIntent(kind: "teardown", fieldteardown)LeadOutIntent(kind: "leadOut", fieldleadOut)"setup","teardown"inintents"leadIn","leadOut"TransportDependencyTransport.durationDependency.lagleaves: "teardown"(the default)leaves: "leadOut"arrives: "setup"(the default)arrives: "leadIn"TransportRoute,TransportAttachment,TransportEndsDependencyRoute,DependencyAttachment,DependencyEnds<Transports>,TransportsProps<Dependencies>,DependenciesPropsLateTransport(fieldtransport)ViolatedDependency(fielddependency)lateTransports()violatedDependencies()Findings.lateTransportsFindings.violatedDependenciesScheduleTooltipTarget:kind: "transport",transport,late;lateTransportskind: "dependency",dependency,violated;violatedDependenciesScheduleHit:kind: "transport",transport;part: "setup" | "teardown"kind: "dependency",dependency;part: "leadIn" | "leadOut"ghost data-findingsvaluelate-transportviolated-dependencygrip data-gripvaluessetup,teardownleadIn,leadOut
0.2.0 – By keyboard and screen reader (Sep. 2026)
Needs @umriss-ui/core 0.10 and @umriss-ui/charts 0.7: it reads the schedule's wording keys; the peer ranges move to ^0.10.0 and ^0.7.0.
Added
- The Windows contrast mode (
forced-colors: active, forced-colors 03). The browser forces the page around the plot and none of its pixels, so the plot paints itself in the system colours, as the charts do: the work in the text colour, lines inGrayText, and the selection colour kept for the Active subtask alone, as an outline around its bar. Overlaps and late transports are drawn in the text colour and dashed, the present inGrayText. The frame, the tooltip, the grips and the ghost's label keep an edge. Nothing changes outside forced colours. docs/llms-full.md, the package's documentation as one Markdown file for a coding agent, in the npm package and pinned to its version: every demo page with its import line, its examples' source, its props tables and why it is built as it is, and the declaration of every other export. The same text stands online as https://romanhaendler.github.io/umriss-ui/schedule/llms-full.txt, with an index of the pages beside it (llms.txt).- The schedule by keyboard and screen reader (schedule-a11y, ADR-0030's
pattern; ADR-0033 where it departs from it). The plot is one tab stop (
role="application", role description "schedule", the schedule'sariaLabel) with an Active subtask: ←/→ walk a lane in time order, ↑/↓ go to the nearest subtask on the lane above or below (a folded group is one row), Home/End to the lane's first and last, PageUp/PageDown by a tenth of the view.]ortfollows a transport out from its subtask and on to the next stop,[or Shift+T goes back -tbecause a German keyboard reaches the brackets only with AltGr. The view pans and scrolls to bring the active subtask into it. The active subtask is drawn and tooltipped as the hover is; the pointer takes it over by moving, and keys walk on from the pointer's. - Space and Enter select the active subtask's task, reported through
onSelectedTaskChangeas a click is. - Editing by key: Alt+←/→ proposes a move by one step of the snap raster,
Alt+Shift+←/→ a new end - the same
moveandstretchintents a drag of that length reports, and only whereintentslists them. - What a screen reader hears: once the keys rest (150 ms), a polite readout
of the lane, the task, the subtask, its day and times and every finding by
name; never after the pointer. The plot is described by a summary - lanes,
subtasks in view, the visible span, the plan's overlaps and late transports -
and the key help. New wording entries in
@umriss-ui/core, English and German:scheduleRoleDescription,scheduleSummary,scheduleKeyHelp.
0.1.8 – Core 0.9.0 (Sep. 2026)
Admits @umriss-ui/core 0.9, which only adds a token; the peer range moves to ^0.9.0. Nothing else changes.
0.1.7 – Core 0.8.0: a fold that turns (Sep. 2026)
Needs @umriss-ui/core 0.8: it reads core's pressed surfaces and motion tokens; the peer range moves to ^0.8.0.
Changed
The lane-group fold is core's
AngleGlyph– the same chevron, at the one stroke width (1.4 instead of 1.5).The fold chevron of a lane group has a surface. Under the pointer it now takes the sunken surface of core's quiet keys, and a stronger one while pressed, like the table's expander; it only darkened its type before. Its focus is the ring alone - the ring no longer darkens the type as well.
Fixed
- The fold chevron of a lane group turns. Its transition named a curve token
that does not exist (
--u-ease-standard), which made the whole declaration invalid, so the chevron has always jumped. It now reads--u-ease-out.
0.1.6 – Core 0.7.0 (Sep. 2026)
Changed
- A finding in the tooltip reads core's
--u-color-danger-text- lighter in the dark theme, 4.5:1 on its surface. The peer range moves to@umriss-ui/core^0.7.0.
0.1.5 – Core 0.6.0 (Sep. 2026)
Changed
- The schedule takes
@umriss-ui/core0.6. Nothing in the schedule changed; the peer range moves to^0.6.0, so that it installs beside@umriss-ui/table0.3, which needs core's new wording.
0.1.4 – Core 0.5.0 (Sep. 2026)
Changed
- The schedule takes
@umriss-ui/core0.5. Nothing in the schedule changed; the peer range moves to^0.5.0, so that it installs beside@umriss-ui/calculation, which needs core's new wording.@umriss-ui/chartsstays at^0.4.0.
0.1.3 – Core 0.4.0 and charts 0.4.0 (Sep. 2026)
Changed
- The schedule takes
@umriss-ui/core0.4 and@umriss-ui/charts0.4. The peer ranges move to^0.4.0. The schedule places its day and shift boundaries with the local offset that charts now exports (localOffset); its own copy is gone. What it draws is unchanged.
0.1.2 – Phones, touch and a review (Sep. 2026)
Changed
- The lane headers take at most 40 % of the schedule.
headerWidthis nowmin(headerWidth px, 40%), so that on a phone the plot keeps the larger part. - The wheel over the lane headers scrolls the lanes, as it does over the plot; Ctrl or ⌘ there zooms around the plot's first instant.
- A finger's tap may wander ten pixels and still select; the mouse keeps its three.
Fixed
- A pinch that ends with one finger still down pans on with that finger, instead of doing nothing until it is lifted; a third finger no longer breaks the pinch.
- A pan ended by
pointercancelgives the cursor back. - A schedule unmounted during a drag stops its auto-pan and the timer of a
folded group it rested over; before, the auto-pan ran on and kept reporting
onDomainChange. - A new
calendar- an inline array counts, being new on every render - under a view panned past the old calendar's ends no longer turns the domain into NaN and the plot blank. - A lane or group id containing a space no longer breaks the fold control's
aria-controls.
0.1.1 – The README catches up (Sep. 2026)
Nothing in the code changed. The README names the online demo, the design
language and the licence, as the other three packages do. The peer ranges are
^0.3.1 on @umriss-ui/core and @umriss-ui/charts, released beside it.
0.1.0 – The first release (Sep. 2026)
No longer a release candidate: the tag next is gone, pnpm add @umriss-ui/schedule is the whole install line, and @umriss-ui/core and
@umriss-ui/charts are released versions too. What the candidate 0.1.0-rc.0
was is still here; three deliveries stand on top of it, newest first, each with
its own report below.
The numbers keep their meaning from here: the middle digit rises when something
is added, the last one when something is repaired, and whatever changes
existing behaviour stands under a heading "Changed" of its own. As long as the
first digit is 0, no number promises compatibility.
Lanes that fold, and one language for the bars (Sep. 2026)
Delivery report for .scratch/schedule-lane-groups/spec.md, tickets 01–11.
Added
<LaneGroup id label>puts structure over the lanes — halls, lines, machine groups, to any depth. It is declared by composition, so a group reads in JSX as it reads in the plant, and a lane never names its group.A group is never a lane (ADR-0025). Nothing sits on it: a subtask names a machine, a finding belongs to a machine,
canMoveTois asked about a machine and every intent names one. Folding a group changes none of it.<Schedule …> <LaneGroup id="hall-a" label="Hall A"> <LaneGroup id="turning" label="Turning line"> <Lane id="lathe-1" label="Lathe 1" /> <Lane id="lathe-2" label="Lathe 2" /> </LaneGroup> <Lane id="press-1" label="Press 1" /> </LaneGroup> <Lane id="paint" label="Paint shop" /> </Schedule>collapsedGroups,defaultCollapsedGroupsandonCollapsedGroupsChangesay which groups are folded — controlled, with an uncontrolled default: the shapeselectedTaskhas. It is not an intent. Folding says what is on screen and nothing about the plan, so a caller that applies every intent it receives will never find a fold among them.A folded group shows a miniature: every lane in it as a thin strip, at a smaller scale, with its work in the tasks' own colours. Transports arrive at a strip, a finding inside a fold is marked on the strip and on the row, and a strip can be hovered, tooltipped and selected. A strip carries no appearance, no bar label, no progress rail and no grips — that is what unfolding is for.
The header of a group carries a chevron button with
aria-expandedandaria-controls, the group's label and how many lanes it holds; children indent one step per level. It is the first thing the schedule puts into the tab order, and it has a focus ring of its own. Two wording entries in English and in@umriss-ui/core/wording/de, plus the lane count.A drag held over a folded group opens it after a moment, so work can be moved into a group without preparing the view first. It closes again when the drag ends, and the caller's list is never written to — the application did not fold anything, and hears nothing.
Changed
- Every appearance is drawn differently. The words a caller writes are
unchanged and so is
resolveAppearance; the picture is not. Each statement now owns exactly one property of the drawing, so that several on one bar stay several statements:"provisional"is hollow - no fill at all, the surface shows through, with its dashed outline in the task colour at full weight. It used to be a 45-per-cent fill, which read as a setup; empty is not faint."fixed"carries a cap at each end of the main time, three pixels, in the colour the bar's label takes, set just inside the end. The hatch across its face is gone: it lay under the label, and it was the loudest mark in the picture for the calmest statement."muted"is at full height in the task colour mixed half into the surface, opaque and without an outline. It used to be drawn at half height, which read as a different kind of thing and cost it its label."open"fades at whichever edge of the view the bar passes, left as well as right. A bar that began before the view used to say nothing at all.
- A
progressrail lies within the main time and above the bar's lower edge. It measures the work, so it stops where the main time does. - A hatch now means one thing only: a lane a drag may not put its work on. It is no longer a mark on any bar.
- A refused lane is visible before it is met. The lanes
canMoveToturns down are marked from the first frame of a drag - drawn back and hatched, and their headers with them ([data-lane][data-refused], to style beside the schedule). Over one of them the cursor says no and a hairline ties the ghost to the pointer it is not following. - A refused lane no longer costs the whole gesture. A drop after one still
reports the move in time; only the lane change is dropped.
canMoveTois asked once per lane when a drag takes hold, and again at the drop. ScheduleHandleanswers for a folded lane with its strip:clientPointOfandpositionAtread the place a lane is actually drawn, so a caller's own marks keep pointing at the work when a group folds.
A plan one can read (Sep. 2026)
Delivery report for .scratch/schedule-legibility/spec.md, tickets 01–06.
The formats of @umriss-ui/core became English in the same delivery
(ADR-0024), which is what the dates and numbers of a schedule follow.
Added
labelwrites a line into every bar: the order, the article, whatever a planner reads first. It is real DOM text, cut off with an ellipsis where the bar is too narrow, left out where nothing would be readable, and held at the view's edge for a bar that began before it. Its colour follows the brightness of the bar's.route,anchorandendsdecide how a transport is drawn: a curve, a straight line or orthogonal segments; from the middle of a bar or from the edge facing the other stop; with or without a dot at each end. All three are options of the schedule and all three are overridable per transport. They change the picture and never a finding -leavesandarrivesalone decide whether a transport is late.appearanceandprogresson a subtask:"provisional"(a dashed outline),"fixed"(a hatch),"muted"(drawn slim),"open"(fading where it continues past the view), and a share of the work that is done, drawn as a rail along the bar. Each is a pattern or an outline and not only a colour, and none of them uses the faint fill that means a setup or a teardown.canMoveTo(subtask, lane)narrows where a drag may land. The ghost stays on the last lane that was allowed and says "Not this lane"; a refused drop reports nothing. It is asked for work dragged in from outside as well. Two wording entries come with it.
The schedule in daily use (Sep. 2026)
Delivery report for .scratch/schedule-refinement/spec.md, tickets 01–09.
Read Changed first: the wheel does something else now.
Changed
- The wheel scrolls the lanes and lets the page scroll on once they are at their end. Ctrl or ⌘ with the wheel, and a pinch, zoom; a horizontal wheel or Shift with a vertical one pans through time. Before this, every wheel movement zoomed, which trapped the wheel on a long page and left twenty lanes unreachable by it.
onSelectedTaskChangecarries the clicked subtask as a second argument (null for a click on a transport or on nothing), and is called again when another subtask of the same task is clicked. A caller that reads only the first argument is unaffected.
Added
- A tooltip on a hovered subtask or transport: the order, the stop, its
times, setup and teardown, the transport's route and duration, and the
findings on it.
tooltip={false}switches it off; a function replaces its content and receives aScheduleTooltipTargetwith the findings. nowdraws a line across the lanes at the present:truefollows the clock by the minute, an instant fixes it there. Off by default.- A drag near the edge of the plot pans the plot along, faster the closer to the edge, so a subtask reaches a time that was not in view in one gesture.
snaptakes a raster with an offset ({ step, offset }): shifts at 06:00, 14:00 and 22:00 are eight hours offset by six. A snapped time that would land in time an operating calendar removes moves on to the seam, so an intent never asks for a time the plant does not run.shiftTask(subtasks, task, by)returns one move intent per stop of a task - the whole order moved, distances kept.- The place intent and
placing: work that is not on the plan can be dragged in from any list, with the platform's drag and drop. The application declares what it is dragging inplacingwhile it drags; a drop on a lane reports{ kind: "place", item, task, lane, from, to, setup, teardown }.subtaskFromPlace(intent, id)builds the subtask,applyIntentleaves the data alone for it, andripplepushes nothing until the subtask exists. Without"place"inintentsno drop is accepted. onDomainChangereports the visible span after the planner pans or zooms - for keeping a second schedule, or a chart's time axis, in step. A span handed in throughinitialDomainis not reported back.- A ref handle (
ScheduleHandle):positionAt(clientX, clientY),clientPointOf(time, lane?),visibleDomain().
0.1.0-rc.0 – The schedule (Sep. 2026)
Delivery report for .scratch/schedule/spec.md (ADR-0022, ADR-0023). Not yet
published.
Added
SchedulewithLane,SubtasksandTransportsdeclared as children. Lane headers at the left as text, a day band above the plot and a time band below it that steps from the day down to the quarter hour with the zoom. Subtasks drawn with main time, setup and teardown in their task's colour; transports as lines from an end to a start, anchored per transport (leaves,arrives). Canvas colours followcolor-scheme.- Findings drawn and never resolved: an overlap on a lane — setup and teardown included — offset and marked; a late transport dashed in the finding colour.
- Pan and zoom: drag the background in both directions, the wheel and a
pinch zoom around the pointer, a horizontal wheel pans;
zoomLimits. An operating calendar (calendar) cuts removed time out of the axis. - Interaction:
onInteractionreports click, context menu and hover with the hit (subtask and part, transport, lane, nothing), the client point, the time and the lane. A click selects the whole task;selectedTaskandonSelectedTaskChangecontrol it. - Controlled editing:
intentsandonIntent— move, lane, stretch at the edges, setup and teardown grips on the selected subtask — with a ghost that shows its times and findings while the drag is in flight; Escape cancels.snap: the tick raster by default, a step, orfalse. - The arithmetic:
findings,overlaps,lateTransports,ripple,applyIntent,snapTime,occupied,departure,arrival, and the typesTask,Subtask,Transport,Intentand its five kinds.