From 8729cf25bf0b066491ca40ca1de494cafdbc13aa Mon Sep 17 00:00:00 2001
From: prql-bot <107324867+prql-bot@users.noreply.github.com>
Date: Fri, 4 Sep 2026 06:54:35 +0000
Subject: [PATCH] fix: hide playground sidebar subtrees when an ancestor folder
is collapsed
---
web/playground/src/sidebar/Sidebar.jsx | 55 +++++++++++++++-----------
1 file changed, 31 insertions(+), 24 deletions(-)
diff --git a/web/playground/src/sidebar/Sidebar.jsx b/web/playground/src/sidebar/Sidebar.jsx
index 1f86d1011c54..1ba227bf7fb9 100644
--- a/web/playground/src/sidebar/Sidebar.jsx
+++ b/web/playground/src/sidebar/Sidebar.jsx
@@ -1,5 +1,4 @@
import "./Sidebar.css";
-import React from "react";
import { useState } from "react";
function Sidebar({ library, onLoadFile }) {
@@ -8,8 +7,7 @@ function Sidebar({ library, onLoadFile }) {
}
function toggleFolder(id) {
- openFolders[id] = !Boolean(openFolders[id]);
- setOpenFolders(() => ({ ...openFolders }));
+ setOpenFolders((folders) => ({ ...folders, [id]: !folders[id] }));
}
function handleClick(section, file, id) {
@@ -29,28 +27,37 @@ function Sidebar({ library, onLoadFile }) {
for (const [section, files] of Object.entries(library)) {
const fileRows = [];
- for (const [index, filename] of Object.keys(files).entries()) {
- const array = files[filename];
- const depth = array[2];
- const parent = array[3];
- const id = array[4];
- const name = array[5];
+ // Whether each row's children should render: the row is itself visible
+ // *and* open. `generateBook.cjs` emits parents before their children, so
+ // an entry's ancestors are already recorded by the time it's read. Testing
+ // only the immediate parent would leave a subtree dangling at the top of
+ // the sidebar when a grandparent is collapsed while the parent stays open.
+ const childrenVisible = {};
+ for (const filename of Object.keys(files)) {
+ // The `book` section carries tree metadata past the editor and content;
+ // the flat sections (examples, tables, local storage) leave it undefined.
+ const [, , depth, parent, id, name] = files[filename];
+ const visible =
+ parent == null || depth === 0 || Boolean(childrenVisible[parent]);
+ childrenVisible[id] = visible && Boolean(openFolders[id]);
+
+ if (!visible) {
+ continue;
+ }
+
fileRows.push(
-