Try it out here:
In 2019, I worked with converting a jquery application to web components. Specifically replacing Sortable with something that would work well with Polymer. This was also before the browser DragEvent API got adopted by Safari. Most libraries used compromises that made them less usable. Some libraries would lose hold of the dragged item if it was dragged outside the specified region of the page, or would freeze. I didn’t find any library usable with Polymer and Shadow Dom that also made it easy to just drag and drop, with mouse or touchscreen, with a feature set similar to jQuery Sortable. So I made my own.
Liking the physicality of swiping on touchscreen, I decided to do the sorting with physicalized animations, letting you throw items, and animating them falling into place. Even though those animations are not necessary for usability, I needed the custom implementation in order to work around all the then existing limitations for achieving a good user experience. All the layered animations were just me taking the opportunity to make it more fun. It was never fully polished since I couldn’t rationalize giving this task too much time in the project.
In preparation for this article, I completely removed the dependency on Polymer, and also added support for grid and flexbox. There was the beginnings of support for drag and drop between nested containers, as you would do in a file browser. That part is not working with multiple moving containers that are also dynamically resizing to fit its content. But sorting columns of sortable items would work fine.
So this is <MV-SORTER> with visualized dropzones, customizable presentation and physicalized animations.
The default style sits in a separate
mv-sorter.css file so that it can be completely replaced. The default content adds shadows and highlights:
In addition, the example here used the additional style for the sortable items:
Supported attributes are:
- row: elements are displayes horizontal (default)
- column: elements are displayed vertical
- lock: Only move in selected axis
- group: Allow movement to other containers in the same group
- autosave: move element in DOM after drop
- disabled: make container inactive
Events you can listen to on the
- drop: details
- dropoutside: details
Methods availible on the
- reset(): move all items back to their original DOM positions
- commit(): update DOM placing items in their new place
- elements(): lists elements in the container, similar to what you would get from the DOM after a commit()
- elements_removed(): list elements moved to another contianer
- elements_added(): lists elements moved here from another container
is_altered tells you if anything has changed, like sort order or anything added or removed.
You can also add a
mv-draghandle in an element for using that for dragging, instead of the whole element.
Combining all this for a simple scrum-like board with sortable columns and items:
There are lots of things to improve. Using the new top-layer stacking context, and doing all animations relative page rather than as offset of original position would make things a lot cleaner.