Skip to main content
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 whose id matches its resource. By default that’s read from event.resourceId; pass a resourceId accessor for a different shape:
Overlapping events in the same row stack into sub-lanes (via the shared layoutDayEvents), so nothing is hidden behind anything else.

Vertical orientation

On a narrow screen the horizontal axis has to scroll sideways, which reads poorly. Pass orientation="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.
A common pattern is switching on the viewport, like the example app does:
Everything else carries over: overlapping events share their column as side-by-side sub-lanes, drag-to-move follows the vertical axis, and resize moves to the bottom edge. On React Native the resource headers stay fixed while the hours scroll, so give the timeline a bounded height (a flexed or fixed-height parent); on the web the track scrolls inside the component when you constrain its height. 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.
Both props work in either orientation (they window rows in the horizontal layout too) and on both renderers.

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

Pass onDragEvent 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; at is snapped to dragStepMinutes.
  • 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 by onDragEvent when set (so onLongPressEvent fires only for non-draggable bars), and empty-space long-press is claimed by onCreateEvent when set (so onLongPressCell fires 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.
To render the closed region yourself (a label, an icon, a pattern), add 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):
Because dragging is gesture-only, native draggable bars also carry screen-reader actions: move earlier / later, extend / shorten, and move to the adjacent lanes, each stepping by 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.