Available on both renderers, including drag-to-move and edge-resize via
onDragEvent. The web
renderer (@super-calendar/dom) adds per-slot class styling; the React Native renderer
(@super-calendar/native) styles via theme.containers. Import from the package you’re using.ResourceTimeline lays a single day out horizontally: each resource is a row,
the x-axis is the day’s hours, and every event sits in its resource’s row at its
start time. It’s the classic scheduling board — rooms, people, or machines down the
side, time across the top — and the MIT answer to the “resource timeline” views
other libraries gate behind a paid tier.
How events map to rows
Each event is placed in the row whoseid matches its resource. By default that’s
read from event.resourceId; pass a resourceId accessor for a different shape:
layoutDayEvents), so nothing is hidden behind anything else.
Vertical orientation
On a narrow screen the horizontal axis has to scroll sideways, which reads poorly. Passorientation="vertical" to flip the layout into the time grid’s shape: the
hour axis runs down the left, each resource becomes a column, and the columns
flex to share the available width, so a phone shows the whole board at once.
hourHeight (default 48) sets the pixels per hour; hourWidth, rowHeight,
and labelWidth apply to the horizontal orientation only. Custom renderers get
height (the bar’s pixel height) in their ResourceEventArgs; width is 0 in
this orientation because the columns flex.
Paging resources
Columns flex to share the width, so past a handful of resources they get too narrow, especially at phone widths.resourcesPerPage caps how many lanes show
at once; resourcePage (0-based, clamped to the last page) picks which ones.
It’s controlled, like date: wire your own prev/next buttons to a state value.
Sizing & window
startHour/endHour— the visible hour window (default 0–24).hourWidth— pixels per hour along the horizontal axis (default 80); the track scrolls horizontally when it overflows. Horizontal only.hourHeight— pixels per hour down the vertical axis (default 48). Vertical only.rowHeight— height of each resource row (default 56). Horizontal only.labelWidth— width of the left resource-label column (default 140). Horizontal only.ampm— 12-hour axis labels.
Moving & resizing
PassonDragEvent to make the board interactive: drag a bar to move it along the
time axis or across lanes, or drag its trailing edge to resize. It’s called
with the proposed new start/end and the lane the bar was dropped in (the original
lane when it didn’t cross); retarget the event’s resource from that fourth
argument. Return false to reject the drop (the bar snaps back). Movement snaps
to dragStepMinutes (default 15). Only the currently visible lanes are drop
targets, so cap a long list with resourcesPerPage and page through it.
To keep the board time-only, reject any lane change: compare the dropped
resource.id to the event’s current one and return false when they differ.
On the web, drag with a mouse or pen; a bar being dragged carries data-dragging
for styling. On React Native, long-press a bar to pick it up, then drag along the
time axis or sideways into another lane; the same move and cross-lane moves are
also exposed as screen-reader actions on the bar. In the vertical orientation the
time axis runs down and resize moves to the bottom edge; lanes are the columns, so
a cross-lane drag goes sideways.
Creating and pressing empty space
The board takes the same empty-space interactions as the time grid, with the lane’s resource added to each callback so you know where as well as when:onPressCell(at, resource)— tap an empty slot;atis snapped todragStepMinutes.onCreateEvent(start, end, resource)— sweep out a new event on empty lane space: drag with a mouse or pen on the web, long-press then drag on React Native. A ghost previews the range while you drag.onLongPressEvent(event)/onLongPressCell(at, resource)— React Native long-presses. A bar’s long-press is claimed byonDragEventwhen set (soonLongPressEventfires only for non-draggable bars), and empty-space long-press is claimed byonCreateEventwhen set (soonLongPressCellfires only without it).
Business hours
businessHours shades the closed hours of each lane. It takes the same shape
as the Calendar’s prop plus the lane’s resource, so lanes can keep different
opening hours; return null for a fully closed lane. A date-only function
(the exact one you pass to Calendar) is accepted as-is.
renderBusinessHours. The board keeps positioning each band and calls you with
{ date, start, end, resource }; the themed tint is dropped so your output owns
the look. The band is decorative: it stays non-interactive and hidden from
assistive tech, so return visuals, not buttons or announced text:
React Native
The native renderer exposes the same board and props (date, resources, events,
orientation, resourceId, resourcesPerPage, resourcePage, startHour/endHour, hourWidth, hourHeight, rowHeight, labelWidth, ampm,
renderEvent, onPressEvent, onPressCell, onCreateEvent, businessHours,
renderBusinessHours), plus
onDragEvent / dragStepMinutes for long-press drag-to-move, cross-lane drag, and edge-resize
and the long-press variants onLongPressEvent / onLongPressCell. It reads the theme from context, so
restyle via theme.containers (see Theming):
dragStepMinutes (the lane moves retarget the
resource). VoiceOver / TalkBack users invoke them from the bar’s actions menu to
reschedule or reassign without a gesture, through the same onDragEvent. (The
visual resize grip is a pointer/touch affordance and isn’t a separate focus
target.)
Styling
Like the other views, every part is a slot:header, corner,
timeAxis, hourTick, resourceLabel, row, track, gridLines,
businessHours, backgroundEvent, event, eventBox, nowIndicator, and createGhost. Pass classNames /
styles, or a renderEvent for a fully custom bar. It also takes the shared
theme.
See the resource tab on the live demo.