Tree Node

Individual tree item.

src/
index.js

html

<details class="tree-node tree-node--folder" style="--accent:#E8A020;" open>
  <summary class="tree-node__summary">src/</summary>
  <div class="tree-node__children" style="padding-left:20px;">
    <div class="tree-node__leaf">
      <span class="tree-node__leaf-icon" aria-hidden="true"></span>
      <span class="tree-node__leaf-label">index.js</span>
    </div>
  </div>
</details>
<style>
.tree-node { font: 15px/1.5 system-ui, sans-serif; color: #241430; background: #FAF7F2; border-radius: 8px; padding: 4px 8px; }
.tree-node__summary { list-style: none; cursor: pointer; padding: 6px 4px; border-radius: 6px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.tree-node__summary::-webkit-details-marker { display: none; }
.tree-node__summary::before { content: "📁"; font-size: 13px; }
.tree-node--file .tree-node__summary::before { content: "📄"; }
.tree-node__summary::after { content: "▸"; margin-left: auto; color: var(--accent); }
.tree-node[open] > .tree-node__summary::after { transform: rotate(90deg); display: inline-block; }
.tree-node__summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.tree-node__children { border-left: 1.5px solid #24143022; margin-left: 10px; }
.tree-node__leaf { display: flex; align-items: center; gap: 6px; padding: 5px 4px; font-size: 14px; }
.tree-node__leaf-icon::before { content: "📄"; font-size: 12px; }
</style>

tailwind

<details open class="tree-node-tw tree-node-tw--folder font-sans text-[15px] text-[#241430] bg-[#FAF7F2] rounded-lg px-2 py-1" style="--accent:#E8A020;">
  <summary class="tree-node-tw__summary list-none cursor-pointer rounded-md px-1 py-1.5 font-semibold flex items-center gap-1.5 marker:hidden">
    <span aria-hidden="true" class="tree-node-tw__icon"></span>
    src/
    <span aria-hidden="true" class="ml-auto" style="color:#E8A020">▸</span>
  </summary>
  <div class="border-l-[1.5px] border-[#24143022] ml-2.5" style="padding-left:20px;">
    <div class="flex items-center gap-1.5 py-1 px-1 text-sm">
      <span aria-hidden="true" class="tree-node-tw__leaf-icon"></span>
      <span>index.js</span>
    </div>
  </div>
</details>
<style>
.tree-node-tw__icon::before { content: "📁"; font-size: 13px; }
.tree-node-tw--file .tree-node-tw__icon::before { content: "📄"; }
.tree-node-tw__leaf-icon::before { content: "📄"; font-size: 12px; }
</style>

react

export function TreeNode({
  label = "src/",
  childLabel = "index.js",
  open = true,
  accent = "#E8A020",
  kind = "folder",
  indent = 20,
}) {
  const isFolder = kind === "folder";
  return (
    <details open={open} style={{ fontFamily: "system-ui, sans-serif", fontSize: 15, lineHeight: 1.5, color: "#241430",
      background: "#FAF7F2", borderRadius: 8, padding: "4px 8px" }}>
      <summary style={{ listStyle: "none", cursor: "pointer", padding: "6px 4px", borderRadius: 6, fontWeight: 600,
        display: "flex", alignItems: "center", gap: 6 }}>
        <span aria-hidden="true" style={{ fontSize: 13 }}>{isFolder ? "📁" : "📄"}</span>
        {label}
        <span aria-hidden="true" style={{ marginLeft: "auto", color: accent }}>▸</span>
      </summary>
      <div style={{ borderLeft: "1.5px solid #24143022", marginLeft: 10, paddingLeft: indent }}>
        <div style={{ display: "flex", alignItems: "center", gap: 6, padding: "5px 4px", fontSize: 14 }}>
          <span aria-hidden="true" style={{ fontSize: 12 }}>📄</span>
          <span>{childLabel}</span>
        </div>
      </div>
    </details>
  );
}