Solution 1 :

I managed to find a solution by only drawing one line at the last child and using offsetTop and getBoundingClientRect().height to calculate the position and height of the arrow-line. Working solution here: https://plnkr.co/edit/SFzgiZi1dckRa79C

Problem :

I have a reusable React list component that can have nested children and I want to draw an arrow from the parent div to all direct children divs like the picture below.

List Component Image

Here is an example of a nested list component:

import React from 'react';
import ListElement from './ListElement.js';

const List = () => (
  <>
    <ListElement>
      <ListElement>
        <ListElement>
          <ListElement />
          <ListElement>
            <ListElement />
          </ListElement>
        </ListElement>
        <ListElement />
      </ListElement>
      <ListElement />
    </ListElement>
    <ListElement />
  </>
);

export default List;

The ListElement component looks something like this:

    import React from 'react';

    const ListElement = props => {
      const indentationStyle = { paddingLeft: `${3 * props.indent}rem`,
      position: 'relative'};

      const lineStyle = {
        left: `${2 + 3 * (props.indent - 1.2)}rem`,
      };

      const tile = (
        <div style={indentationStyle}>
          {props.indent > 0 ? (
            <div className={'arrow-line-container'} style={lineStyle}>
              <div className={'arrow-line'}/>
              <div className={'curve-arrow-line'}/>
            </div>
          ) : null}
          <div
            style={{
              border: '1px solid black',
              padding: '1rem',
              marginBottom: '1rem',
            }}
          >
            I am a ListElement
          </div>
        </div>
      );

      const getChildren = () => {
        let elements = React.Children.toArray(props.children);

        // increase indent prop of each child and assign what number child it is in the list
        elements = elements.map((element, index) => {
          return React.cloneElement(element, {
            ...element.props,
            indent: props.indent + 1,
            childNumber: index,
          });
        });
        return elements;
      };

      const childTiles = <div className={'child-tile'}>{getChildren()}</div>;

      const arrowStyle = {
        backgroundPosition: `${1.3 + 3 * (props.indent - 1)}rem`,
      };

      return (
        <>
          <ul className={'no-bullet'}>
            <li
              className={props.indent === 0 ? 'no-arrow' : 'arrow'}
              style={arrowStyle}
            >
              {tile}
            </li>
            {props.children ? childTiles : null}
          </ul>
        </>
      );
    };

    ListElement.defaultProps = {
      childNumber: 0,
      indent: 0,
    };

    export default ListElement;

and the css looks like this:

ul.no-bullet {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

.arrow-line {
  border-left: 2px solid #6a6969;
  content: "";
  position: absolute;
  height: 65%;
}

li.arrow {
  background: url("./arrow.png") no-repeat;
}

li.no-arrow {
  display: block;
}

Currently, I am creating the list with <li> elements and changing the bullet to an image of the arrow. I want to draw the lines from the parent and attach them to the arrows at each child. I am struggling with calculating the correct height of the line and the position for the top of the line. Any suggestions are appreciated.

Here is a link to the Plunker: https://plnkr.co/edit/GFrriWfJyeur7MRh?open=Hello.js&deferRun=1&preview

By