<div class="vue-app">
        <root v-bind:folder="root"></root>
    </div>

<script type="text/x-template" id="folders-component">
  <template>
  <ul class="folders">
    <li>Folders</li>
    <folder v-bind:folder="folder"></folder>
  </ul>
</template>
</script>
                                  
<script type="text/x-template" id="folder-component">
<template>
  <li class="folder" v-bind:class="[folder.leaf ? 'is-leaf' : 'is-folder']">
    <span v-on:click="expand()">{{ folder.text }}</span>

    <ul class="sub-folders" v-if="folder.children && folder.children.length > 0" v-show="folder.expanded">
      <folder v-for="child in folder.children" v-bind:folder="child"></folder>
    </ul>
    <div class="folder-empty" v-else v-show="!folder.leaf && folder.expanded">No Data</div>
  </li>
</template>
</script>
.vue-app {
  margin: 0 auto;
  width: 300px
}

ul.folders {
  padding: 1rem;
  margin: 0;
  box-sizing: border-box;
  width: 100%;
  list-style: none
}
ul.folders > li:first-child {
  padding: 1rem 1rem 1rem 0
}

li.is-folder {
  padding: 1rem;
  border-left: 1px solid #d3d3d3;
  margin-bottom: 0.5rem
}
li.is-folder > span {
  padding: 0.5rem;
  border: 1px solid #d3d3d3;
  cursor: pointer;
  display:inline-block
}
li.is-leaf {
  padding: 0 0 0 1rem;
  color: #000;
}
ul.sub-folders {
  padding: 1rem 1rem 0 0;
  margin: 0;
  box-sizing: border-box;
  width: 100%;
  list-style: none
}
div.folder-empty {
  padding: 1rem 1rem 0 1rem;
  color: #000;
  opacity: 0.5
}
const root = {
    text: 'Root Folder',
    leaf: false,
    expanded: true,
    children: [{
      text: 'Sub Folder 1',
      leaf: false,
      expanded: false,
      children: [{
        text: 'Sub Sub Folder 1',
        leaf: false,
        expanded: false,
        children: [{
          text: 'SomeFile1.js',
          leaf: true
        }]
      }, {
        text: 'Sub Sub Folder 2',
        leaf: false,
        expanded: false,
        children: []
      }, {
        text: 'SomeFile.txt',
        leaf: true
      }]
    }]
};

const folder = {
  name: "folder",
  template: '#folder-component',
  props: {
    folder: Object
  },
  methods: {
    expand() {
      if (this.folder.leaf) {
        return;
      }

      this.folder.expanded = !this.folder.expanded;
    }
  }
}

const folders = {
  name: 'root',
  template: '#folders-component',
  props: {
    folder: Object
  },
  components: {
    'folder': folder
  }
}

new Vue({
  el: '.vue-app',
  data: () => {
    return root;
  },
  components: {
    'root': folders
  }
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js