dnd-kit

repository·main·Indexed 12 days ago

https://github.com/clauderic/dnd-kit

A modern, lightweight, and performant toolkit for building accessible drag and drop interfaces for the web. It is framework-agnostic at its core and provides specialized adapters for React, Vue, Svelte, and SolidJS, as well as a vanilla DOM implementation via @dnd-kit/dom.

Tokens
95.6K
Snippets
315
Records
500
Agent score
96%

What's inside dnd-kit

  1. What is @dnd-kit/abstract and when to use it

    main

    The @dnd-kit/abstract package provides the core abstractions and utilities for implementing drag and drop functionality. It serves as the foundation for building concrete implementation layers (such as @dnd-kit/dom).

    Note: This package is not intended for most end-users. You should only use it if you are planning to build a new concrete implementation layer on top of @dnd-kit.

  2. How DragDropProvider works

    main
    The DragDropProvider acts as a context provider for the drag and drop lifecycle. It manages a DragDropManager which orchestrates the interactions between sensors, plugins, and modifiers. By wrapping your application (or a specific section of it) in DragDropProvider, you ensure that all child components can access the shared drag and drop state and logic via Vue's dependency injection.
  3. Core concepts of @dnd-kit/abstract

    main

    The @dnd-kit/abstract architecture is built around several key abstractions that manage the lifecycle of a drag-and-drop interaction:

    • Entities: The fundamental participants in a drag operation, categorized as Draggable (elements that can be moved) and Droppable (elements that can receive items).
    • Sensors: Components that detect user interactions (like mouse or touch) and translate them into drag operations. They support multiple types and custom configurations.
    • Collision Detection: The system responsible for determining when a draggable element overlaps with a droppable element. It supports various strategies, priority-based resolution, and custom detectors.
    • Plugins: An extension system that allows you to add or modify core functionality through a plugin-based architecture and lifecycle management.
    • Modifiers: A system for transforming drag operations, such as modifying coordinates. Modifiers are chainable and can be configured with specific options.
  4. Enable cross-column item movement with useSortable and useDroppable

    main

    When creating sortable items that belong to different lists, use the group property in the useSortable hook. This enables the items to be recognized as part of the same sortable ecosystem across different containers.

    To handle dropping items into empty columns, the column container must implement the useDroppable hook. This ensures the column acts as a valid drop target even when it contains no sortable items.

  5. How DragDropProvider works with draggables and droppables

    main

    The DragDropProvider component is the central context provider for drag and drop interactions. It wraps your draggable and droppable elements and provides event listeners (like onDragEnd) to handle interaction logic.

    Critical Requirement: createDraggable and createDroppable rely on the context provided by DragDropProvider. They must be called from a component that is rendered inside the DragDropProvider. If you call them in the same component that renders the provider, the context will be unavailable and an error will be thrown.

    <script>
      import {DragDropProvider} from '@dnd-kit/svelte';
      import Draggable from './Draggable.svelte';
      import Droppable from './Droppable.svelte';
    
      let parent = $state(undefined);
    
      function onDragEnd(event) {
        if (event.canceled) return;
        parent = event.operation.target?.id;
      }
    </script>
    
    <DragDropProvider {onDragEnd}>
      {#if parent == null}
        <Draggable />
      {/if}
    
      <Droppable id="droppable">
        {#if parent === 'droppable'}
          <Draggable />
        {/if}
      </Droppable>
    </DragDropProvider>
  6. How to implement multiple droppable targets

    main

    You can create multiple droppable areas in your application using two patterns:

    1. Multiple calls in one component: Call useDroppable multiple times within a single component (ensuring each call uses a different id).
    2. Reusable components: Create a generic component that calls useDroppable and render that component multiple times throughout your application. Each instance must be passed a unique id via props.
  7. Core concepts of @dnd-kit/dom

    main

    Understanding the following abstractions is essential for using the @dnd-kit/dom layer:

    • DragDropManager: The central orchestrator that manages sensors, plugins, collision detection, and the overall drag and drop lifecycle.
    • Draggable: An abstraction representing a DOM element that can be moved.
    • Droppable: An abstraction representing a DOM element that can receive draggable elements.
    • Sensors: Components that detect user input (such as pointer or keyboard events) and translate them into drag operations.
    • Plugins: Extensions that add specific behaviors to the core drag and drop process, such as auto-scrolling, accessibility features, or visual feedback.
    • Modifiers: Functions that transform drag coordinates to constrain or modify how an element moves during a drag operation.
  8. What are Modifiers and how do they work?

    main

    Modifiers transform and constrain the movement of draggable elements during drag operations. They can restrict movement to specific axes (horizontal/vertical), constrain movement within boundaries (window/element), or implement custom logic like snapping to a grid.

    Key behaviors:

    • Order of execution: Modifiers are applied in the order they are provided in the array. It is recommended to place restrictions (like axis constraints) before transformations (like snapping).
    • Precedence: Modifiers configured on an individual Draggable element take precedence over global modifiers configured on the DragDropManager.
    • Lifecycle: A modifier is constructed with options, its apply() method is called during the drag operation to transform coordinates, and it can be destroyed to clean up resources.
  9. Understand the DragDropManager lifecycle

    main

    The DragDropManager follows a four-stage lifecycle:

    1. Initialization: The manager is created, default plugins/sensors are registered, and custom configuration is applied.
    2. Registration: Draggable and droppable elements register themselves, plugins initialize, and event listeners are bound.
    3. Operation: Drag operations are tracked, events are dispatched, and collisions are detected.
    4. Cleanup: Elements unregister, event listeners are removed, and resources are released (typically via destroy()).
  10. How the AutoScroller plugin works

    main

    The AutoScroller plugin automatically scrolls scrollable containers when a pointer approaches their edges during a drag operation. It works by detecting the nearest scrollable ancestor of the element under the pointer and computing scroll direction and speed based on proximity to the edge. The scroll speed increases linearly as the pointer gets closer to the edge.

    This plugin is included by default when creating a new DragDropManager.

  11. How Optimistic Sorting works

    main

    By default, Sortable uses the OptimisticSortingPlugin. This plugin physically moves DOM elements during a drag to provide immediate visual feedback without waiting for framework re-renders.

    Key behaviors during drag:

    1. DOM elements are moved to reflect the new order.
    2. The index and group properties on Sortable instances are updated.
    3. The source and target of the drag operation refer to the same element. Consequently, isDragSource and isDropTarget will both be true for the dragged item.

    Tracking changes: Because source and target are identical, you must use sortable-specific properties to track movement:

    • index: The current position (updated by the plugin).
    • initialIndex: The position when the drag started.
    • group: The current group.
    • initialGroup: The group when the drag started.