JSFiddle - React, Tailwind, and code Playground
by neonDog
HTML
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<div class="test"></div>
SCSS
body, html {
font-family: Helvetica;
background-color: #212830;
color: #9EA1B2;
}
* {
box-sizing:border-box;
}
$directory-color: #0568ae;
$file-color: inherit;
.neon-tree-item {
padding:2px 4px 2px 0;
border-radius:6px;
outline:0;
cursor:default;
&.file .neon-tree-icon {
color:$file-color;
}
&.directory .neon-tree-icon {
color:$directory-color;
}
&:focus {
color: #FFFFFF;
background-color: #31343F;
}
}
.neon-tree-row {
list-style:none;
padding-top:3px;
padding-bottom:3px;
}
.children {
padding-left:20px;
}
.root.children {
padding-left:0;
}
.neon-tree-toggle {
width:15px;
text-align:right;
}
.neon-tree-icon, .neon-tree-name, .neon-tree-toggle {
display:inline-block;
padding-left:4px;
}
.hide {
display:none;
}
JavaScript
class NeonTree {
constructor(element,settings={}) {
this.element = element;
this.defaults = {
directoryIcon:'fas fa-folder',
directoryOpenIcon:'far fa-folder',
fileIcon:'far fa-file',
toggleClosed:'fas fa-caret-right',
toggleOpen:'fas fa-caret-down',
data:[]
};
this.options = Object.assign({},this.defaults,settings);
this.click = this.click.bind(this);
this.element.addEventListener('click',this.click);
this.build();
}
build() {
this.element.innerHTML = this.buildTree(this.options.data);
}
buildItem(itemData) {
let {text,icon,children,type,state,a_attr} = itemData;
let html = '<a ';
for (let key in a_attr) {
if (key !== 'class') {
html += ' '+key+'="'+a_attr[key]+'"';
}
}
const isOpen = itemData.type === 'directory' && state && state.opened === true;
if (!icon) {
if (itemData.type === 'directory') {
icon = isOpen === true ? this.options.directoryOpenedIcon : this.options.directoryIcon;
} else {
icon = this.options.fileIcon;
}
}
html += `class="neon-tree-item ${type} ${ a_attr.class || '' }" tabindex="0">`;
if (children.length) {
html += `<span class="neon-tree-toggle${ isOpen === true ? ' open' : ''}">
<i class="${ isOpen === true ? this.options.toggleOpen : this.options.toggleClosed }"></i>
</span>`;
}
html += `<span class="neon-tree-icon"><i class="${ icon }"></i></span><span class="neon-tree-name">${ text || '' }</span></a>`;
return html;
}
buildTree(itemData,depth=0,opened=true) {
let html = `<ul class="children ${ depth === 0 ? 'root' : '' } ${ opened === true ? '' : 'hide' }">`;
++depth;
itemData.forEach((v) => {
const...