Move and resize
PassonDragEvent to make events draggable. Move an event (long-press it on
native, click-drag it on web), or drag the grip at its bottom edge to
change the end or its top edge to change the start. Drag vertically to
change the time, horizontally to move it to another day (within the visible
range). New start/end are snapped to dragStepMinutes (default 15).
Move an event past midnight
A move keeps its duration, so dragging an event down past the end of the day lets its end run into the next one: the box cuts off at the day boundary and the remainder previews at the top of the next column, exactly where the committed event will render. The start stays in the day you dropped it on (it stops onedragStepMinutes step before the end of the day), so a move to a different day is
still the horizontal drag.
onDragEvent then receives a start and end on different dates. Dragging any
day’s segment of the resulting multi-day event moves the whole thing, so it never
gets clipped to the day you grabbed. All visible segments preview the move together,
including segments that enter a new column. Both dates shift together to preserve
the event’s duration. For example, moving a Tuesday 17:00 to Thursday 21:00 event
one day earlier previews Monday 17:00 to Wednesday 21:00, whichever segment you grab.
Use a resize grip to change just the start or end.
Hide the drag handle
By default a small grip shows at each draggable event’s bottom edge. SetshowDragHandle={false} to hide that indicator while keeping drag-to-move and
drag-to-resize fully working, so events stay editable without the visual marker.
Lock specific events
onDragEvent makes every event draggable, which is the right default: most
calendars let you reschedule anything. When a few events must never move (a
confirmed booking, an event someone else owns, a holiday), set draggable: false
on those events. They keep their normal appearance and still respond to taps, they
just can’t be picked up or resized. Nothing else needs to change.
disabled: true, which
also dims it.)
Allow only move or only resize
Split the two withstartEditable (can be moved) and durationEditable (can be
resized), per event or grid-wide via eventStartEditable / eventDurationEditable
(both default true). A draggable: false event stays fully locked regardless.
Reject a drop
Returnfalse from onDragEvent to refuse a particular placement — the event
snaps back to where it started (on the time grid a cross-week drop snaps the view
back too, so the rejection is visible). Use it for rules that depend on where the
event lands: overlaps, out-of-bounds slots, or business-hours limits. The library
is expo-free, so fire your own feedback (a haptic, a toast) right where you reject.
eventOverlap={false} and
the grid rejects any drag or resize that would land an event on top of another,
without you checking in onDragEvent. For your own rules, eventsOverlap and
overlapsOtherEvents are exported from @super-calendar/core.
Haptics on grab
onDragStart fires the instant an event is picked up for a move or resize,
before anything is committed. The library is expo-free, so bring your own
haptics:
Move an event to another week
While moving an event, drag it past the left or right edge of the day columns and hold briefly. The view pages to the previous/next period and the event lifts into a floating copy that keeps following your finger, so the drag stays live across the page change and you drop it on any day of the newly revealed week. Both renderers needonChangeDate set (they already do for paging); the page only advances on a
deliberate dwell at the very edge, so a normal in-view drag never trips it.
On native the pager’s own swipe is frozen for the moment it pages, so the view
advances under your held finger instead of waiting for you to lift.
In-view move, cross-day within the visible columns, and resize all work by gesture
as usual on both.
Screen-reader rescheduling
Dragging is a gesture, so on the React Native renderer draggable events also carry accessibility actions for VoiceOver / TalkBack users: move earlier, move later, (when the event owns its end) extend / shorten, and move to next / previous week (per-mode: the page span), each stepping bydragStepMinutes or a
whole page. They run through the same commit path as a drag, so onDragEvent
fires exactly as it would from a gesture (and can still return false to reject).
The built-in event renderer wires these up automatically; a custom renderEvent
should spread the accessibilityActions and onAccessibilityAction it receives
onto its pressable to keep the event operable by assistive tech.
Drag to create
PassonCreateEvent to sweep out a new event on empty grid space:
long-press and drag on native, click-drag on web. The handler receives
the snapped start/end on release (a stationary press yields a one-step
range). On native it supersedes onLongPressCell; on web, dragging empty space
creates instead of scrolling (use the wheel to scroll), and Escape cancels an
in-progress sweep before it commits.
A live ghost box previews the range as you sweep. Tap (no drag) on empty space still fires
onPressCell with the pressed date+time, so you can support both “tap to create a point” and
“drag to create a range.”On the month grid
The same two handlers work inmonth mode on both renderers. Nothing extra to
enable: pass onCreateEvent, onDragEvent, or both.
Drag to create a day span
Press an empty day and drag across others to sketch an all-day span, then release.start is midnight of the first day and end is midnight after the last
(exclusive). On native you long-press first, so a tap and a page swipe are
never hijacked, and a stationary hold creates that single day; on web a plain
click without dragging creates nothing and still fires onPressDay.
onSelectDrag reports the same sweep as it happens, with the ordered inclusive
[start, end] days, so a selection highlight can follow the drag rather than
appearing only on release. Set it, onCreateEvent, or both; either enables the
gesture. See Date selection for wiring it to useDateRange.
Drag to reschedule
Pick an event bar up and drop it on another day. Both ends shift by the same number of calendar days, so the time of day and the duration are preserved (a multi-day event keeps its length). Grab it with a long-press on native and a press-drag on web. The carried bar fades and the target day is tinted while you drag.draggable: false and startEditable: false
lock an event, eventStartEditable={false} locks the whole grid, returning
false rejects a drop, and eventOverlap={false} rejects one that would land on
top of another event. onDragStart fires on grab, for haptics. There is no resize
on the month grid, so durationEditable has no effect there.
Styling the drag states
Both states are tinted with the theme’srangeBackground token by default (see
Theming), and the bar being carried fades. On the dom renderer
each day in a create sweep also carries data-creating and the day an event is
about to land on carries data-drop, so you can restyle either (see
Styling); give the day slot a class to take the tint over
entirely.
On the year grid
The twelve mini months take the same sweep:onSelectDrag reports the ordered
inclusive [start, end] days as you drag, and onCreateEvent reports the
all-day range once on release. Hold a day and drag on a device, press and drag on
the web. Days being swept carry data-creating on the dom renderer.
onDragEvent applies to month mode, not year.
Tuning the snap
dragStepMinutes (default 15) controls how move, resize, and create snap on the
week/day grid. The month and year grids always snap to whole days.