Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

RFC: Layout and ItemLayout render a big amount of nested DOM nodes #241

@bmdalex

Description

@bmdalex

Layout and ItemLayout render a big amount of nested DOM nodes

Steps

I was trying to reuse and ItemLayout (and Layout) Stardust components to re-write the Chat.Message component since it looked that I can leverage the logic provided by ItemLayout props (media, endMedia, header, headerMedia, etc) to add author and date props to Chat.Message.

However, I realized these layout components render a big amount of redundant DOM nodes; here is an example for a very simple Chat.Message implemented with ItemLayout:

Example code:

const messages = [
  {
    key: 1,
    author: 'John Doe',
    date: 'Mon Sep 17 2018 13:54:05',
    content: 'Hello',
    mine: true,
    avatar: { src: 'public/images/avatar/small/matt.jpg', status: availableStatus },
  },
]

const ChatExampleAvatar = () => <Chat messages={messages} />

export default ChatExampleAvatar

Screenshot:

screen shot 2018-09-17 at 14 01 14

Rendered DOM:

<li date="Mon Sep 17 2018 13:54:05" class="ui-layout ui-itemlayout ui-chat__message">
  <div class="ui-layout__main">
    <div class="ui-item-layout__main" style="grid-template-rows:1fr 1fr">
      <div class="ui-layout ui-item-layout__header">
        <div class="ui-layout__main">John Doe</div>
        <span class="ui-layout__gap"></span>
        <div class="ui-layout__end">
          <span class="ui-item-layout__headerMedia">Mon Sep 17 2018 13:54:05</span>
        </div>
      </div>
      <div class="ui-layout ui-item-layout__content">
        <div class="ui-layout__main">Hello</div>
      </div>
    </div>
  </div>
  <span class="ui-layout__gap"></span>
  <div class="ui-layout__end">
    <span class="ui-item-layout__endMedia">
      <div class="ui-avatar">
        <img aria-hidden="true" src="public/images/avatar/small/matt.jpg" class="ui-image"/>
        <span title="Available" class="ui-status">
          <span class="ui-icon" aria-hidden="true"></span>
        </span>
      </div>
    </span>
  </div>
</li>

Implementation:

<ItemLayout
  as={as}
  {...rest}
  className={cx(classes.root, classes.content)}
  media={!mine && this.renderAvatar(avatar, styles, variables)}
  endMedia={mine && this.renderAvatar(avatar, styles, variables)}
  header={author}
  headerMedia={date}
  content={content}
  truncateHeader={true}
/>

Issue:

Expected Result

The DOM tree has a reasonable depths (let's say a max of 4 nodes).

Actual Result

The DOM tree has a depth of 6 just for this basic example!

Proposed solution

Add better conditions to Layout and ItemLayout components in order to prevent additional DOM elements in the tree when a certain rendered area (start, main, end, header, media, etc) is represented by:

  • another ItemLayout / Layout component
  • single DOM node
    What we do now is to add a wrapper DOM element (div usually) to wrap content for a layout slot. We can use the single node itself for that and apply the layouting styles directly.

Version

0.5.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions