JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.4.2.js"></script>
<div class='tree'  data-bind='with: tree'>
  <ul data-bind='template: {name:"treeNode", foreach: children}'>
  </ul>    
</div>  

<script id='treeNode' type='text/html'>
  <li data-bind='css:{closed:isClosed,open:isOpen, leaf: isLeaf, last: isLast}, click: toggleOpen, clickBubble: false'> 
    <ins></ins>
    <span data-bind='text:caption'></span>
    <ul data-bind='template: {name:"treeNode", foreach: children}'>
    </ul> 
  </li>  
 </script>

CSS

.tree li, 
.tree ins{ background-image:url("http://habrastorage.org/storage2/0eb/507/98d/0eb50798dca00f5cc8e153e6da9a87f9.png"); background-repeat:no-repeat; background-color:transparent; }
.tree li { background-position:-90px 0; background-repeat:repeat-y; }

.tree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; min-width:18px; }

.tree ul, .tree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; }
.tree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; min-width:18px; } 
.tree > ul > li { margin-left:0px; }

.tree li.last { background:transparent; }
.tree .open > ins { background-position:-72px 0;}
.tree .closed > ins { background-position:-54px 0;}
.tree .leaf > ins { background-position:-36px 0;}


.tree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; }
li.open > ul { display:block; }
li.closed > ul { display:none; }

JavaScript

function setIsLast(children){
  for(var i=0,l=children.length;i<l;i++){
     children[i].isLast = (i==(l-1));   
  }
}

function TreeViewNode(caption,children){
  var self = this;
  this.caption = caption;
  this.children = children||[];
  
  this.isOpen = ko.observable();
  this.isClosed = ko.computed(function(){
       return !this.isOpen();
  },this);
  
  this.isLeaf = !this.children.length;
  this.isLast = false;
  setIsLast(this.children);
  
  this.toggleOpen = function(){
    self.isOpen(!self.isOpen());
  };
}

function TreeView(children){
  this.children = children;
  setIsLast(this.children);
}

var vm = {
  tree: new TreeView([
     new TreeViewNode('Node 1',[
        new TreeViewNode('Node 3')
     ]),
     new TreeViewNode('Node 2')
  ])
};

ko.applyBindings(vm);