question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

drag & drop next steps

See original GitHub issue

Visual editor

This RFC tries to specify a paradigm for our visual editor. For internal tooling we want something that allows for flexible layout, yet is constrained enough to require minimal manual tweaking.

Regular components

  • All components conform to the width given to them by the layout algorithm. For some components this means they will have to centre themselves in a box (e.g. a button my take width from its content, which may be more narrow than the available width) some components will have an option to expand to the full width of their box (e.g. fullWidth property on TextField). Other components will horizontally adapt to any width imposed on them (e.g. image, datagrid)
  • All components define the height they want to be rendered at. For some components this will be always the same, e.g. textinputs have a fixed height. And for some it will be configurable. e.g. data grid or image

Layout components

In terms of layout we identify two types of components, columns and rows.

column

a column works vertically. It acts as a component on the horizontal axis (adapt to the width imposed to it by the layout algorithm). It serves as the container for rows. Its only possible children are rows and its only possible parent is a row. A only needs to be manually created when the user wants to build something like a sidebar.

  • A column only has rows as its children. Dropping a component on a column where there is no row, implicitly creates a row. Removing the last child from a row, removes that row from the page.

rows

Rows are never created explicitly, they are implicitly created depending on the drop position of certain elements

  • A row has the same width as the column it’s under.
  • A row is a 12 column grid layout into which its children take their place.
  • A child of a row takes up a certain amount of columns (span). The user can adjust the span of an element with drag handles on the left and right side of the element.

page

On the top level, a page acts as a column

Drop algorithm

We must avoid layout shifting as much as possible, therefor we will not live preview elements as they are dragged on the page. Dragging a new element only highlights cursors as available drop targets. Dragging an existing element, to move it around, stays in place until the drop is performed.

The biggest challenge of drag and drop visual editor is to calculate a predictable insertion position for the drop target. I propose the following algorithm:

  • around top level rows there is a 5px (?) band which always takes precedence as a drop target to create a new row that contains the element being dragged. We may shift the page rows apart by the same gap during dragging if this can be done with minimal layout shift.

For any other [X,Y] mouse position during the drag

  • find the most deeply nested component under the mouse
  • divide the component into 4 quadrants by connecting its corners diagonally, determine which quadrant the mouse is over to determine the side of the box that will be the drop target.
    • is it left or right: insert a new component to the left of the right within the same parent row as the one of the element that’s hovered (TODO: what if there’s no more space left in the row, a.k.a. all of its columns are occupied? Disable the drop at this location?)
    • is it top or bottom:
      • If the element is the only child of its row, add another row above or below that row with the dropped element as its only child
      • If the element has siblings in its row, replace it with a new column containing two rows, one with the original hovered element and one with the dropped element
  • TODO: we need to special case moving around an element within its own row.

This algorithm takes care of the most common situations, top level inserts and inserting at the deepest level. In very deeply nested layouts it may be necessary to insert an element in between two nested layout components. I expect this to be an edge case for internal applications, but it can be solved by designating a keyboard modifier (shift or Cmd) that opens a context menu with all the container components in the same axis which can then be hovered to specify the exact insert position.

Resizing components

Should changing the width of a component or moving it around in its row be constrained by the available columns. Or should rows be allowed to overflow. Will overflow behavior be necessary to allow responsive design? (e.g. width = 3 columns when lg, 6 columns when sm,…)

Benchmark

This RFC borrows some ideas from makeswift.com. Stronlgy encouraged to familiarize yourself with its editor canvas implementation.

considerations

  • make column count configurable? count, gap,…
  • on the component level, we could mandate a minimum span?
  • For elements that have configurable height we can add a drag handle at the bottom, but that doesn’t have to be part of this RFC
  • For top level rows we may want to add an option to constrain the width, to create a fluid responsive container

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
prakhargupta1commented, May 17, 2022

I guess https://github.com/mui/mui-toolpad/issues/359 will be a part of this enhancement?

0reactions
apedroferreiracommented, Aug 1, 2022

Closing this issue as basic functionality for everything mentioned here seems done to me, even though there’s lots of room to improve these features of course.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Drag & Drop Step - Testim overview
Learn how to record and modify Drag & Drop steps in your tests. Suggest Edits. Drag & Drop interactions are automatically recorded when...
Read more >
Drag and drop steps
Drag and drop steps occur in pairs, with a "Click and hold" step for moving an element, and a "Release" step for the...
Read more >
Drag–and–Drop: How to Design for Ease of Use
First, make sure that your handle icon is keyboard accessible with the Tab key; this enables “grabbing” the draggable item via the spacebar....
Read more >
Move and copy items with drag and drop on iPad
With drag and drop, you can use a finger to move text and items within an app ... Touch and hold the item...
Read more >
HTML Drag and Drop API - MDN Web Docs
This overview of HTML Drag and Drop includes a description of the interfaces, basic steps to add drag-and-drop support to an application, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found