Tree view

트리뷰

A collapsible, nested list — like a folder tree — where expanding a branch reveals indented items inside it.

Also known as: File treeNested listOutline view
···
html
<ul class="tv" role="tree" aria-label="프로젝트">
  <li role="treeitem" aria-expanded="true" id="tv1"><span class="tv-row"><i class="tv-caret">▸</i>📁 project</span>
    <ul role="group">
      <li role="treeitem" aria-expanded="false" id="tv2"><span class="tv-row"><i class="tv-caret">▸</i>📁 src</span>
        <ul role="group" hidden>
          <li role="treeitem"><span class="tv-row leaf">📄 index.ts</span></li>
          <li role="treeitem"><span class="tv-row leaf">📄 demo.ts</span></li>
        </ul></li>
      <li role="treeitem"><span class="tv-row leaf">📄 package.json</span></li>
    </ul></li>
</ul>
css
.tv{list-style:none;margin:0;padding:0;width:min(220px,92%);font-size:12px;color:var(--fg)}
.tv ul{list-style:none;margin:0;padding-left:16px}
.tv-row{display:flex;align-items:center;gap:5px;padding:4px 6px;border-radius:6px;cursor:pointer}
.leaf{color:var(--muted);cursor:default}
.tv-caret{display:inline-block;transition:transform .2s;color:var(--muted);width:10px}
[aria-expanded=true] > .tv-row .tv-caret{transform:rotate(90deg)}
js
function toggle(li) {
  const open = li.getAttribute('aria-expanded') === 'true';
  li.setAttribute('aria-expanded', String(!open));
  const group = li.querySelector(':scope > ul');
  if (group) group.hidden = open;
}
document.querySelectorAll('[role=treeitem][aria-expanded]').forEach((li) => {
  li.querySelector(':scope > .tv-row').addEventListener('click', (e) => { e.stopPropagation(); auto = false; toggle(li); });
});
let auto = true;
// 루트(project)는 항상 열어 두고, 그 안의 src 폴더만 자동으로 여닫아 카드가 절대 텅 비어 보이지 않게 한다.
const inner = document.getElementById('tv2');
setInterval(() => { if (!auto) return; toggle(inner); }, 1700);

role="treeitem" nodes nest inside role="tree", and any node with children groups them under role="group". Each node carries aria-expanded (open or not) and aria-level (indentation depth). Right arrow conventionally expands or moves into children; left arrow collapses or moves to the parent.

It differs from an accordion in nesting depth — an accordion usually toggles single-level sections, while a tree view is recursive, like a file explorer where folders can sit inside folders to any depth.

A tree with checkboxes (a permissions editor, say) reuses the indeterminate pattern from the checkbox entry — a parent node shows a dash when only some of its children are checked.