Implemented in the current 0.6.4 release line.
This document is now a current-state product contract, not a future
implementation plan. README.md remains the public API source of truth, and
WIREFRAME.md remains the component-level visual and DOM reference.
solverforge-ui ships one canonical read-only scheduling surface:
SF.rail.createTimeline(config)
The component is a generic dense scheduling timeline for SolverForge applications. It is intentionally numeric-axis only: consumers normalize domain timestamps, time zones, lane ordering, labels, badges, stats, overlays, and tones before passing a model to the library.
The low-level rail helpers remain shipped primitives for custom furnace-style resource layouts, but they are not the recommended dense scheduling integration path.
The public entrypoint is:
SF.rail.createTimeline(config)
Returned API:
elsetModel(model)setViewport(viewport)expandCluster(laneId, clusterId | null)destroy()
The component is read-only. It does not parse timestamps, own timezone policy, or support direct drag-rescheduling in this release line.
The model must already be normalized to integer minutes.
Rejected inputs include:
- string timestamps
Dateobjects- numeric strings
- fractional minutes
- malformed tick objects
- malformed overlay spans
Required model shape:
model.axis:startMinute,endMinute,days[],ticks[],initialViewportmodel.lanes[]:id,label, optionalbadges, optionalstats, optionaloverlays,mode,items[]items[]:id,startMinute,endMinute,label, optionalmeta, optionalsummary,tone, optionalclusterId, optionaldetailItems[]
Each lane may produce at most one overview group for a given clusterId.
Reusing the same clusterId for disjoint groups in the same lane is invalid
because expandCluster(laneId, clusterId) would be ambiguous.
Overview mode is for scanning dense schedules.
Shipped behavior:
- overlapping or tightly adjacent overview items collapse into aggregate blocks
- aggregate blocks can show direct summary labels, count, open state, and tone composition
- omitted summary fields are derived only when backing detail is available
- omitted
openCountandtoneSegmentsstay unknown when the supplied aggregatecountexceeds inspectable backing items - expanded clusters remain inline and keep the aggregate block visible as the collapse affordance
- focus and hover expose equivalent tooltip content
Detailed mode is for exact inspection.
Shipped behavior:
- detailed blocks preserve exact interval geometry
- adjacent intervals stay visually disjoint on one track
- true overlaps are packed onto separate track rows
- lane height follows the number of packed tracks
- timeline-specific minimum-width inflation is not applied to detailed blocks
Shipped behavior:
- sticky time header
- sticky lane labels
- one scrollable body viewport for dense solved schedules
- synchronized horizontal header/body movement
- drag-to-pan from the timeline viewport
- weekend shading and overlay bands behind schedule content
zoomPresetsdefaults to['1w', '2w', '4w', 'reset']zoomPresets: []intentionally removes zoom controls for fixed-horizon app surfaceslabelWidthdefaults to280- supported embeds with a body viewport of
500pxor wider compact the label column when needed to preserve at least320pxof visible schedule track - timelines created or updated before DOM attachment resynchronize layout after mount
The shipped validation surface includes:
- Node frontend tests for numeric-only normalization, overview grouping, detailed packing, cluster identity, viewport sync, zoom controls, detached mount resync, and dense fixture rendering
- browser smoke tests for
demos/full-surface.html,demos/timeline.html,demos/timeline-dense.html, anddemos/rail.html - acceptance screenshots under
screenshots/ - README and wireframe coverage for the public contract
Use these focused commands while working on the timeline:
make lint-frontend
make test-frontend
make test-browserUse make test-quick or make test before release work.
Whenever SF.rail.createTimeline() behavior changes, update the same release
surface together:
README.mdWIREFRAME.mddemos/README.md- runnable demos under
demos/ - focused tests under
tests/ - generated assets under
static/sf/
Do not document planned scheduling behavior as shipped unless it is wired into the generated assets and covered by README API reference text.
- Do not add a second scheduling namespace such as
SF.schedule,SF.timeline, orSF.scheduler. - Do not move shared scheduling layout semantics back into a consuming app.
- Do not add timestamp parsing or timezone policy to the library.
- Do not add compatibility-only layout branches.
- Do not make overview readability depend on showing every raw item label at once.
- Do not call a timeline behavior shipped without tests, demos, docs, and generated assets staying synchronized.