JSFiddle - React, Tailwind, and code Playground

HTML

<div id="dropzone">
Drop some directory here.
<pre id="_log"></pre>
</div>

CSS

#dropzone{
  border: 1px solid;
  width: 90vw;
  height: 90vh;
  margin: 2vmin;
  padding: 2vmin;
  overflow: auto;
  }
#dropzone.over{
  background-color: rgba(0,0,0,.2);
}

JavaScript

/* constructs a simple directory view from a filesystem */
async function makedir(entries) {

  const systems = entries.map(entry => traverse(entry, {}));
  return Promise.all(systems);

  async function traverse(entry, fs) {
    if (entry.isDirectory) {
      fs[entry.name] = {};
      let dirReader = entry.createReader();
      await new Promise((res, rej) => {
        dirReader.readEntries(async entries => {
          for(let e of entries) {
          	await traverse(e, fs[entry.name]);
          }
          res();
        }, rej);
      });
    } else if (entry.isFile) {
      await new Promise((res, rej) => {
        entry.file(file => {
          fs[entry.name] = file;
          res();
        }, rej);
      });
    }
  return fs;
  }
}

function readDropped(dT) {
  const entries = [...dT.items].map(item => {
      return item.webkitGetAsEntry ? item.webkitGetAsEntry() : null;
    })
    .filter(entry => entry);
  if (entries.length) {
    makedir(entries)
      .then(output)
      .catch(handleSecurityLimitation);
  }
  else notadir();

}

function notadir() {
  _log.textContent = "wasn't a directory, or webkitdirectory is not supported";
}

dropzone.ondragover = e => {
  e.preventDefault();
  dropzone.classList.add('over');
}
dropzone.ondragexit = dropzone.ondragend = e => dropzone.classList.remove('over');
dropzone.ondrop = e => {
  e.preventDefault();
  dropzone.classList.remove('over');
  readDropped(e.dataTransfer);
}

function output(system_trees) {
  console.log(system_trees);
  _log.textContent = JSON.stringify(system_trees, checkFile, 2);

  function checkFile(key, value) {
    if (value instanceof File) {
      return '{[File] ' + value.name + ', ' + value.size + 'b}';
    } else return value;
  }
}
function handleSecurityLimitation(error) {
  console.error(error);
  document.body.innerHTML = `
    <h2>Faced security limitations</h2>
    <a href="https://jsfiddle.net/x85vtnef/">Please go to this fiddle</a>`;
}