logo dile-components dile-components

dile-sortable

Container that lets the user reorder its children dragging them by a handle, with the mouse, a finger or the keyboard.

The component does not move the DOM. It previews the movement with transforms and, when the item is dropped, emits dile-sortable-change with the from and to indexes. You reorder your data and render again. In Lit, use repeat() with a stable key so the children keep their state. The moveItem(array, from, to) helper returns a reordered copy of an array.

Installation

npm i @dile/ui

Usage

Import the component (and the helper if you need it).

import '@dile/ui/components/sortable/sortable.js';
import { moveItem } from '@dile/ui/components/sortable/index.js';

Each child must contain a handle marked with data-sortable-handle. The handle can be inside the child's shadow DOM.

html`
  <dile-sortable @dile-sortable-change=${(e) => this.items = moveItem(this.items, e.detail.from, e.detail.to)}>
    ${repeat(this.items, (item) => item.id, (item) => html`
      <div class="row">
        <span data-sortable-handle tabindex="0" aria-label="Move ${item.name}">≡</span>
        ${item.name}
      </div>
    `)}
  </dile-sortable>
`
<script type="module">
  import { moveItem } from '@dile/ui/components/sortable/index.js';
  import '@dile/ui/components/sortable/sortable.js';
  const list = document.getElementById('sortableDemo');
  let items = ['First', 'Second', 'Third', 'Fourth'];
  const render = () => {
    list.innerHTML = items.map((item) => `
      <div style="display:flex;gap:0.5rem;align-items:center;padding:0.5rem;margin-bottom:0.25rem;background:#f4f4f4;border-radius:4px">
        <span data-sortable-handle tabindex="0" style="cursor:grab;touch-action:none" aria-label="Move ${item}">≡</span> ${item}
      </div>`).join('');
  };
  list.addEventListener('dile-sortable-change', (e) => {
    items = moveItem(items, e.detail.from, e.detail.to);
    render();
  });
  render();
</script>
<dile-sortable id="sortableDemo"></dile-sortable>

Handles

Properties

Events

Styling

Custom property Description Default
--dile-sortable-transition-duration Duration of the movement of the other items 150ms
--dile-sortable-dragging-shadow Shadow of the dragged item 0 6px 16px rgba(0, 0, 0, 0.18)
--dile-sortable-dragging-background-color Background of the dragged item (unset)

With prefers-reduced-motion: reduce, the movement of the other items is not animated.