Files
devin-ai-integration[bot] 7be8c63efe feat(examples/calcom): add dndkit drag-and-drop sorting for event types and bookings (#639)
* feat(examples/calcom): add dndkit and drag handle for event types

- Install @dnd-kit/core, @dnd-kit/sortable, and @dnd-kit/utilities
- Add ListItemDragHandle component that appears on hover
- Add drag handle to each event type in the list

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* chore: improve handle appearance

* feat(examples/calcom): implement dnd sorting for event types

- Add DndContext and SortableContext wrappers for drag-and-drop
- Create SortableEventTypeItem component with useSortable hook
- Update ListItemDragHandle to accept dndkit listeners and attributes
- Handle drag end event to reorder items using arrayMove
- Follow dndkit best practices with sensors and collision detection

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix: sort JSX attributes in event-type-actions

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix: use DraggableAttributes type for dndkit attributes

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* refactor: extract reusable SortableList and SortableItem components

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): add sortable functionality to bookings/past page

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): restrict drag to y-axis only

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): enable whole-area dragging with activation constraint

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix(examples/calcom): fix hydration error and revert to drag handle only

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* revert: restore state from 942dc9de (before whole-area dragging)

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* refactor(examples/calcom): eliminate wrapper div in SortableItem

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* refactor(examples/calcom): use CSS variables for sortable styles

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): add data-dragging=false to non-dragged items

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* styling improvements

* rebuild registry

* separator improvements

* fix hydration error

* feat(examples/calcom): add drag overlay and remove axis constraint

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* Revert "feat(examples/calcom): add drag overlay and remove axis constraint"

This reverts commit 20c8c85ea6.

* feat(examples/calcom): add restrictToParentElement modifier

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): add data-over-position attribute for first/last detection

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* styling improvements

* feat(examples/calcom): add data-dragging-position attribute with first/middle/last for all items

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix(examples/calcom): update data-dragging-position during drag based on projected order

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* revert: restore to styling improvements state (7ec11e29)

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* styling updates

* refactor(examples/calcom): remove sortableOverPosition and data-over-position redundancies

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): use rectSortingStrategy for varying item heights

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): add DragOverlay for proper varying heights support

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* revert: restore to f2ad92cb (before DragOverlay and rectSortingStrategy)

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): enable whole-area dragging with activation constraint

- Add sortableListeners prop to ListItem component
- Apply listeners to ListItem div for whole-area pointer dragging
- Add distance activation constraint (8px) to PointerSensor
- Preserve keyboard accessibility via drag handle with attributes and listeners
- Quick clicks still trigger links, dragging (8px+ movement) initiates drag

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* Revert "feat(examples/calcom): enable whole-area dragging with activation constraint"

This reverts commit 8647a92032.

* wip: remove separators and use borders with negative px margin

* feat(examples/calcom): enable whole-area dragging with activation constraint

- Add sortableListeners prop to ListItem component
- Apply listeners to ListItem div for whole-area pointer dragging
- Add distance activation constraint (8px) to PointerSensor
- Preserve keyboard accessibility via drag handle with attributes and listeners
- Quick clicks still trigger links, dragging (8px+ movement) initiates drag

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* prevent unwanted interaction on drag

* minor improvements

* mc

* mc

* styling improvements

* styling improvements

* mc

* no radius

* chore: remove unneeded const

* refactor: improve overall styling on drag

* style: further improvements

* style: adjust z-index for list item component

* feat(examples/calcom): add accessibility announcements for screen readers

- Add announcements prop to DndContext with position-aware messages
- Screen readers now announce: pick up, move, drop, and cancel events
- Remove unused projectedIds from context (replaced with projectedIndex for announcements)
- Follows dnd-kit accessibility guide recommendations

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): add toast notifications with undo for reorder actions

- Show success toast when items are reordered
- Add Undo button to revert to previous order
- Implement for both event-types-list and bookings-list
- Uses optimistic UI pattern with ability to undo

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): add TouchSensor for touch device drag support

- Add TouchSensor with 250ms delay and 5px tolerance for touch devices
- Long-press to drag pattern prevents accidental drags while scrolling
- PointerSensor (distance: 4px) remains for mouse/trackpad for immediate response
- KeyboardSensor unchanged for accessibility

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix(examples/calcom): use MouseSensor instead of PointerSensor for touch support

PointerSensor handles both mouse and touch events via unified pointer events,
which was capturing touch before TouchSensor could activate. MouseSensor only
handles mouse events, allowing TouchSensor to properly handle touch with its
delay-based activation.

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix: toast

* fix(examples/calcom): close previous toast on new reorder, add undo confirmation

- Close existing reorder toast when a new reorder happens (only last action can be undone)
- Show 'Order reverted' info toast when undo is clicked
- Prevents state confusion from multiple undo actions

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix(examples/calcom): also close info toast when new reorder toast appears

- Store info toast ID in currentToastIdRef so it gets closed on next reorder
- Ensures clean toast state when user performs multiple reorders

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* revert: restore multiple toasts behavior (remove auto-close logic)

- Remove auto-close of previous toasts on new reorder
- Keep undo confirmation toast ('Order reverted')
- User will handle disabling undo buttons on toasts behind

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(examples/calcom): implement LIFO undo for reorder toasts

- Only the most recent reorder action can be undone (sequential undo)
- Clicking undo on older toasts does nothing (enforces LIFO order)
- Uses a stack to track undo history
- Passes isReorderToast in toast data for potential visual styling

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* feat(ui/toast): disable action buttons on older reorder toasts

- Find the most recent reorder toast (with data.isReorderToast)
- Disable action buttons on all other reorder toasts
- Provides visual feedback that only the most recent action can be undone

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* fix(ui/toast): add disabled button logic to source file

The previous commit modified packages/ui/src/components/toast.tsx which
gets overwritten by sync-ui script. This adds the same changes to the
source file at apps/ui/registry/default/ui/toast.tsx

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* revert: restore auto-close toast behavior without confirmation

- Revert UI primitive changes (toast.tsx)
- Auto-close previous toast when new reorder happens
- Remove confirmation toast on undo
- Only one undo toast visible at a time

Co-Authored-By: pasquale@cal.com <pasquale@cal.com>

* chore: rebuild registry

* minor improvements

* fix: separator test

* chore: improve as per cubic suggestions

* fix(sortable): optimize dependency array in useEffect for better performance

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: pasquale@cal.com <pasquale@cal.com>
Co-authored-by: pasqualevitiello <pasqualevitiello@gmail.com>
2026-01-19 12:02:07 +01:00
..