Skip to content

feat(useDraggable): add public facing hook #7356

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft

Conversation

tomdavies73
Copy link
Contributor

@tomdavies73 tomdavies73 commented May 30, 2025

FYI: All commits will be squashed into one final commit, with any relevant issues also linked.

Proposed behaviour

This PR introduces a comprehensive drag-and-drop system built on top of Atlassian's Pragmatic Drag & Drop library.

The implementation provides a flexible, reusable solution for creating draggable lists with automatic reordering capabilities.

Consumers can now use the useDraggable hook which will be externally available to make any array of React Elements draggable.

Key Components Added:

Core Architecture:

  • DraggableContainer - Main container component that manages drag operations and list state
  • DraggableItem - Individual draggable item wrapper with drop target capabilities
  • useDraggable - Hook that simplifies usage by wrapping items automatically
  • Context providers for sharing state between container and items

Screenshot 2025-05-30 at 16 56 37

Key Features:

Dual Drag Modes:

  • continuous - Items reorder in real-time as user drags
  • onDrop - Items only reorder when dropped (better performance for large lists)

Smart State Management:

  • Automatic list synchronization when items are added/removed
  • Rollback to previous state on invalid drops (outside valid targets)
  • Tracks original order for reset functionality

Robust ID Handling:

  • Automatic unique ID generation for items
  • Duplicate ID detection with console warnings
  • Parent ID resolution for nested elements

Imperative API:

  • Exposed reOrder(itemId, toIndex) method for programmatic moves
  • Supports both direct item IDs and child element IDs

Edge Detection:

  • Visual feedback for drop zones (top/bottom edges)
  • Prevents dropping items onto themselves
  • Container boundary validation

Technical Implementation:

  • Built on @atlaskit/pragmatic-drag-and-drop for reliable cross-browser support
  • Uses React Context for efficient state sharing
  • Implements useImperativeHandle for external control

Benefits:

  • Developer Experience: Simple hook-based API with sensible defaults
  • Flexibility: Supports custom container/item elements and props
  • Reliability: Comprehensive error handling and state recovery
  • Performance: Efficient updates with minimal re-renders
  • Accessibility: Built on proven drag-and-drop foundation, the useImperativeHandle can be used for manual re-ordering. Supporting graceful degradation.

This implementation provides a production-ready drag-and-drop solution that can be easily integrated into existing components while maintaining full control over styling and behavior.

Current behaviour

Currently, consumers have to use third-party draggable libraries to build out draggable functionality. Internally, we use and re-use react-dnd which is now out of support and results in code repetition and complexity.

Checklist

  • Commits follow our style guide
  • Related issues linked in commit messages if required
  • Screenshots are included in the PR if useful
  • All themes are supported if required
  • Unit tests added or updated if required
  • Playwright automation tests added or updated if required
  • Storybook added or updated if required
  • Translations added or updated (including creating or amending translation keys table in storybook) if required
  • Typescript d.ts file added or updated if required
  • Related docs have been updated if required

QA

  • Tested in provided StackBlitz sandbox/Storybook
  • Add new Playwright test coverage if required
  • Carbon implementation matches Design System/designs
  • UI Tests GitHub check reviewed if required

Additional context

Testing instructions

@tomdavies73 tomdavies73 self-assigned this May 30, 2025
@tomdavies73 tomdavies73 requested review from a team as code owners May 30, 2025 15:20
@tomdavies73 tomdavies73 added DO NOT MERGE Work in progress This is a WIP PR so may not be ready for review labels May 30, 2025
@tomdavies73 tomdavies73 marked this pull request as draft May 30, 2025 15:26
…Draggable hook

Rebuilds the draggable component using the new useDraggable hook. During this work
the type of the `id` prop on `DraggableItem` has been limited to string only to align
with HTML types as the `id` prop is now passed to the DOM.

BREAKING CHANGE: The `id` prop on `DraggableItem` now only accepts a string type
rebuilds flat-table-row-draggable, flat-table-body-draggable and changes logic within flat-table-row

BREAKING CHANGE: consumers will now have to pass their own cells with draggable icons to indicate
draggable behaviour. This is no longer done as standard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DO NOT MERGE Work in progress This is a WIP PR so may not be ready for review
Development

Successfully merging this pull request may close these issues.

1 participant