Skip to content
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

Proposal: rebuild Studio's drag-and-drop as Vue composables #539

Open
bjester opened this issue Feb 1, 2024 · 0 comments
Open

Proposal: rebuild Studio's drag-and-drop as Vue composables #539

bjester opened this issue Feb 1, 2024 · 0 comments
Labels
category: supporting code Implementation of the system product: KDP Relevant to a specific in KDP product: Kolibri Relevant to a specific issue in Kolibri product: Studio Relevant to a specific issue in Studio TAG: design system type: proposal New feature or request

Comments

@bjester
Copy link
Member

bjester commented Feb 1, 2024

Summary

A drag-and-drop utility was built into Studio with its Vue refactor. It uses a combination of Vue component mixins, components, and Vuex to implement its behavior. We also have a drag-and-drop implementation in Kolibri, for sorting, which leverages the Sortable library.

With the deprecation of IE 11, it's more than feasible to integrate a broadly supported utility / mini-library that uses native browser capabilities for drag-and-drop and sorting functionality. If the implementation of it in Studio is viewed as a prototype, various improvements can be made to make it a utility that would be useful for all of our products. In addition, there are clear touch points in the Studio prototype for developing accessibility features-- allowing its functionality to be driven not only by mouse or touch, but keyboards too.

The Studio prototype was built to accommodate for nested collection + document structures, such as those we have in channels, i.e. folders and resources. This accommodation allows for straightforward integration into the codebase where may define these types of structures in templates/components, and for collection specific features such as the ability to drag a whole collection of draggable items and drop zones such as first or last child of a collection.

The architecture is broken down into a few different structures:

  1. Universe
  2. Region
  3. Collection
  4. Item
  5. Handle

Universes are given an ID / name and define DOM areas that contain Regions, Collections and Items. Collections and Items represent structures that can be dragged and dropped, but only within the same Universe (by name). For this reason, Collections and Items can only be implemented within the DOM area of a Universe. Multiple Universes can coexist on a page, without mixing the drag-and-drop functionality between them.

Regions define the actual drag-and-drop dropzone areas. There may be multiple Regions defined in a Universe. Regions can contain Collections or Items. Collections contain Items as children, where Items are the individual elemental items that can be dragged and dropped.

Collections and Items can be given a Handle through which drag-and-drop functionality can be invoked. A Handle could be the entire Item's element, or a descendant element serving as the handle. Collections aren't required to have Handles but can be defined similarly as Items.

Product

Kolibri, Studio, KDP, ++

Desired behavior

Using Studio's prototype, we could develop the following composables to replace the mixture of Vue components, mixins, and Vuex:

  1. useDraggableUniverse(id: string, ...)
  2. useDraggableRegion(id: string, ...)
  3. useDraggableCollection(id: string, ...)
  4. useDraggableItem(id: string, ...)

The above could connect directly to the component's element, or be used in combination with directives (there are some usages on Studio where the draggable components are used that aren't the immediate child of the component, meaning they would require refactoring into separate components to use the composables). Additionally, defining draggable handles could be another composable, or simply a directive.

The composables could manage state directly, instead of using Vuex.

A primary area for improvement over the existing functionality is the rendering of drop placeholders. The components and mixins modified the render function of components to modify the dom and inject dynamic drop placeholders when the user is dragging things. Perhaps one way to accomplish this is to use Shadow DOM to inject these placeholders without modifying Vue component rendering, but it needs some research and investigation.

Current behavior

Studio has a set of components which leverage the majority of their functionality from the draggable mixins. In order to manage state across many components, there's also a draggable Vuex module.

Kolibri has a set of components primarily geared for sorting implementations

Things the author wasn't pleased with in the initial Studio prototype:

  1. Logic and behavior was spread across the 3 areas making it difficult for others to inspect and understand
  2. Implementing the draggable components causes large diffs because you wrap template elements/components with them
  3. Implementing the draggable components creates template code that doesn't mean a whole lot
  4. The drop placeholder's handling and animations weren't the smoothest

(Optional) The Value Add

  • Past research suggested that using another library would require a significant wrapper layer to implement all of the functionality that was required on Studio
  • A small amount of utility is necessary to build on top of browser's native capabilities for drag-and-drop, with the rest being mostly support for its specific implementation, like document + collection structures and handling advanced usage in that regard
  • Vue composables would make the utility a lot more maintainable and easier to understand, and fit perfectly with the utility
  • The prototype's architecture and how it works (regardless of how it's broken down into mixins, Vuex, etc) is perfectly suited for integrating accessibility features such as keyboard control

(Optional) Possible Tradeoffs

  • KDS may not be the best place for it
  • This could be built off another library such as Sortable but the complexities in providing the same featureset may be more work than implementing directly on top of native capabilities
  • There are several capabilities apparent in Studio's prototype, for its UX features and unimplemented features, that aren't immediately clear in its connection to the code
  • There is some unknown in how to best improve the drop placeholders
  • There are some usages on Studio where the draggable components are used that aren't the immediate child of the component, and thus accompanying directives could be worthwhile but also duplicate some abilities
  • This requires research and planning before development
@bjester bjester added type: proposal New feature or request category: supporting code Implementation of the system product: Kolibri Relevant to a specific issue in Kolibri product: Studio Relevant to a specific issue in Studio product: KDP Relevant to a specific in KDP TAG: design system labels Feb 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category: supporting code Implementation of the system product: KDP Relevant to a specific in KDP product: Kolibri Relevant to a specific issue in Kolibri product: Studio Relevant to a specific issue in Studio TAG: design system type: proposal New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant