Skip to content

File Tree Explorer

A recursive, collapsible file tree with real roving-tabindex arrow-key navigation.

Prominimalbrutalist
Category
Components
Added
2026-09-01
Deps
1
Updated
2026-09-01

This is a viberdy Pro component

The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.

Preview
app
page.tsx
layout.tsx
README.md
package.json

Props

Expand root on load
Requires lucide-react
"use client";

import { useEffect, useMemo, useRef, useState, type KeyboardEvent } from "react";
import { ChevronRight, File, Folder } from "lucide-react";

type Node = {
  id: string;
  name: string;
  type: "folder" | "file";
  children?: Node[];
};

const TREE: Node[] = [
  {
    id: "app", name: "app", type: "folder", children: [
      { id: "app-page", name: "page.tsx", type: "file" },
      { id: "app-layout", name: "layout.tsx", type: "file" },
      {

  // ---------------------------------------------------------------
  // Full source available with a viberdy Pro subscription.
  // https://viberdy.dev/pricing
  // ---------------------------------------------------------------
}
Notes

About this component

A nested set of <ul>/<li> elements with onClick toggles looks like a file tree but has none of the keyboard behavior people expect from one — a real tree view uses roving tabindex, where only one row is ever a Tab stop and arrow keys move a virtual cursor between rows, exactly like VS Code's sidebar or a native OS file picker. Implementing that means flattening the nested Node structure into a visible-rows array every render (skipping any subtree whose parent folder isn't in the expanded set), tracking a single activeIndex against that flattened array, and syncing DOM focus to it from an effect. The non-obvious detail is ArrowLeft on a file: it has to walk backward through the flattened rows looking for the nearest row at a shallower depth, since the parent isn't stored on the node itself — the flattened list is the only place that relationship is recoverable. Caveat: this hand-rolled version doesn't virtualize, so a tree with thousands of expanded rows will re-flatten and re-render the whole visible set on every toggle; for that scale, pair the same expanded-Set logic with a virtualizer.

Related

Pairs well with

Matched on shared tags and category — the entries most likely to be used alongside this one.

Pro

A Cmd+K menu with real submenu drilling, a breadcrumb trail, and scoped per-level search.

command menucmdknavigation
Pro

A keyboard-driven spreadsheet grid with roving-cell navigation and Excel-style Enter/Tab commits.

gridspreadsheeteditable
Featured
NewPro

A nav that measures itself and collapses what does not fit into a More menu — ghost-row measurement, no breakpoints, no flicker loop.

navigationresponsivemenu