Skip to content

Drag & drop interface and Elm UI

Andrea Peltrin edited this page Sep 5, 2022 · 10 revisions

Using the drag & drop interface for Elm Designer works mostly fine. A lot of Elm UI primitives are written naturally as a multi-way tree and are translated at runtime to the browser DOM tree.

There are a few odds things that do not fit this tree model and this causes inconsistencies in the editor.

Nearby elements (above, left, etc.)

These in Elm UI are not direct children of the parent element. Instead, such elements are added as attributes, using the above and similar functions: https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element#above.

Currently it is not clear how to represent this scenario in the outline UI. An element above another doesn't have a parent-child relation with the latter. For now Elm Designer needs a common parent to position one element relative to its siblings.

One could envision a way to "link" two different UI elements and tell the editor to place one of those elements above, to the right, to the left, in front, etc. However, this would look strange because at DOM level both need to be close to each other.

Text inputs and sliders

Input widgets are generally made of multiple pieces, typically a input plus a label, which sometimes has a Label msg type (https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element-Input#text) while other times has a Element msg type (https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element-Input#button).

Elm Designer groups these pieces together and emit the most common usage: an input element with a textual label. Other solutions would be:

  • We could split the input and the label into two document nodes and allow the label to be a direct children on the input - but this feels a bit strange since input doesn't contain the label.
  • We could think about the text input as a node with two children: an input and a textual label. This potentially creates a node without a text input but with a label, which cannot even be serialized in Elm UI, while the opposite is true (https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/Element-Input#labelHidden).

Every element is wrapped in another element

The function ElmUI.wrapElement is called for every document node during rendering. This is done to draw a selection around the selected node more easily. This is omitted in the code generation step.

Initially, the selection border was done using solely CSS trickery such as :after and :before pseudo elements our using outline. However, this was interfering with Elm UI in certain circumstances, since Elm UI too uses such pseudo elements (check also the way it renders input elements). Also if we want to draw UI drag anchors we definitely need concrete DOM elements to attach events.

This setup works mostly fine, except for certain edge-cases like https://github.com/passiomatic/elm-designer/issues/59.

Paragraphs are monolithic

Paragraphs is Elm Designer are just plain text. That is:

type NodeType
    ...
    | ParagraphNode TextData

type alias TextData =
    { text : String
    }

Instead, in Elm UI, a paragraph can contain multiple elements with different alignments.

This would complicate the WYSIWYG editor a lot and currently user cannot format paragraph text at all. In the future we could allow markdown formatting or a simple Medium-style pop-up "formatting bar" with simple Bold, Italic, etc. styling.