Skip to content

fix(dashboard): auto-expand small containers on layer navigation#492

Open
Muammer06 wants to merge 5 commits into
Egonex-AI:mainfrom
Muammer06:fix/dashboard-auto-expand-collapsed-containers
Open

fix(dashboard): auto-expand small containers on layer navigation#492
Muammer06 wants to merge 5 commits into
Egonex-AI:mainfrom
Muammer06:fix/dashboard-auto-expand-collapsed-containers

Conversation

@Muammer06

@Muammer06 Muammer06 commented Jun 21, 2026

Copy link
Copy Markdown

Problem

When navigating into a layer, all file nodes were hidden inside collapsed ContainerNode groups. At the typical fitted zoom level (0.10–0.20×), collapsed containers appeared as nearly-invisible dark boxes with faint 1px borders — users had to either click every container manually or zoom in to 1.0× before any file nodes became readable.

Before

Before: all containers collapsed, file nodes invisible

After

After: small containers auto-expanded on layer open


Solution

Two-part fix across GraphView.tsx and ContainerNode.tsx.

1. Auto-expand small containers on first layer visit (GraphView.tsx)

  • When drillIntoLayer fires, an effect expands all containers whose child count ≤ AUTO_EXPAND_MAX_CHILDREN (10)
  • Containers with > 10 files stay collapsed — expanding them all would cascade into many parallel ELK Stage 1 re-layouts, potentially freezing the UI on large layers
  • A per-layer Set (autoExpandedLayersRef) ensures re-visiting a layer respects whatever the user collapsed/expanded manually — no second auto-expand
  • After expansion triggers a bumpStage1Tick re-layout, a second effect calls fitView() once layoutStatus returns to "ready", keeping all expanded nodes in the viewport

New newLayoutRef guard (premature fitView fix):
A ref set synchronously in the ELK Stage 1 effect prevents the nodes-watch fitView effect from firing on the previous layer's stale nodes before the new layout arrives.

2. Collapsed container visibility (ContainerNode.tsx)

Property Before After
Border (collapsed) rgba(212,165,116,0.25) 1px rgba(212,165,116,0.55) 1.5px
Border (expanded) rgba(212,165,116,0.60) 1.5px rgba(212,165,116,0.85) 1.5px
Background (collapsed) rgba(255,255,255,0.02) rgba(212,165,116,0.06) (gold tint)
Background (expanded) rgba(255,255,255,0.02) rgba(255,255,255,0.04)

Flow diagram

Auto-expand flow through GraphViewInner


Why not expand ALL containers?

Expanding every container on a large layer (e.g. 30 folders × 40 files each) triggers 30 parallel ELK layouts, then a bumpStage1Tick per container whose estimated size deviates > 20% from Stage 1, leading to cascading re-layouts. The ≤ 10 threshold bounds ELK work: a layer with 20 folders where 15 are large still expands the 5 small ones instantly, and the remaining 15 stay readable as labeled collapsed boxes.

The threshold is a constant (AUTO_EXPAND_MAX_CHILDREN) — easy to tune or make configurable later.


Testing

  1. Open a knowledge graph with a layer that has both small (≤ 10 files) and large (> 10 files) folders
  2. Click a layer cluster to drill in
  3. Expected: small containers expand automatically, large containers stay collapsed
  4. Navigate away and back to the same layer — expected: no second auto-expand, manual changes preserved
  5. Manually collapse an auto-expanded container, navigate away, return — expected: stays collapsed

Muammer06 and others added 4 commits June 21, 2026 12:55
Collapsed ContainerNode groups were nearly invisible at typical fitted
zoom levels (0.10–0.20×), forcing users to click each container manually
or zoom to 1.0× before any file nodes became visible.

Two-part fix:

1. Auto-expand on first layer visit (GraphView.tsx)
   - On `drillIntoLayer`, expand all containers whose child count is
     ≤ AUTO_EXPAND_MAX_CHILDREN (10). Large containers stay collapsed to
     avoid cascading ELK Stage 1 re-layouts that can freeze the UI.
   - Per-layer Set (autoExpandedLayersRef) prevents re-expansion on
     return visits, preserving manual collapse/expand decisions.
   - After expansion triggers a bumpStage1Tick re-layout, a second
     effect fires fitView() once layoutStatus returns to "ready",
     keeping all expanded nodes in the viewport.
   - `newLayoutRef` (new ref) blocks a premature fitView on the previous
     layer's stale nodes while the new ELK layout is in flight.

2. Collapsed container visibility (ContainerNode.tsx)
   - Raised border opacity: 0.25 → 0.55 (collapsed), 0.6 → 0.85 (expanded)
   - Border always 1.5 px (was 1 px when collapsed)
   - Background: slight gold tint (rgba 212,165,116,0.06) when collapsed,
     near-transparent white when expanded

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Lum1104

Lum1104 commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator

@codex review this

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 935b6ecda8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (navigationLevel !== "layer-detail" || !activeLayerId) return;
if (!containerIds || containerIds.length === 0 || !containers) return;
if (autoExpandedLayersRef.current.has(activeLayerId)) return;
autoExpandedLayersRef.current.add(activeLayerId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wait for fresh topology before marking the layer expanded

When navigating directly from one detail layer to another (for example via a portal or tour step), topo.containers still holds the previous layer until the async Stage 1 layout calls setTopology. This effect runs immediately on the activeLayerId change, records the new layer as already auto-expanded, and then filters/expands stale container ids; once the real topology arrives the guard skips the layer, so small containers are not auto-expanded, and colliding ids can even expand a large container based on the previous layer’s child count. Gate this on fresh topology/layout for the current layer before adding it to autoExpandedLayersRef.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in 33b42d8.

Root cause: containers / containerIds / nodes all derive from the same topo topology state, so on a direct layer→layer jump (portal/tour, where navigationLevel stays "layer-detail") they hold the previous layer for one flush until the async Stage 1 ELK calls setTopology. The effect ran in that window, added the new activeLayerId to autoExpandedLayersRef, and expanded stale ids — so once fresh topology arrived the has(activeLayerId) guard skipped the layer and its small containers never expanded.

This staleness window was already known: the sibling fitView effect bails on it via newLayoutRef. The fix applies the same guard before mutating the ref:

if (navigationLevel !== "layer-detail" || !activeLayerId) return;
if (!containerIds || containerIds.length === 0 || !containers) return;
if (newLayoutRef?.current) return;        // stale topology — wait for fresh layout
if (autoExpandedLayersRef.current.has(activeLayerId)) return;
autoExpandedLayersRef.current.add(activeLayerId);

When ELK completes, newLayoutRef clears and setTopology re-renders → the effect re-runs with fresh containers and marks/expands the layer correctly.

On a direct layer→layer navigation (portal/tour, navigationLevel stays
"layer-detail"), containers/containerIds still hold the previous layer's
topology until the async Stage 1 ELK setTopology lands. The initial
auto-expand effect ran in that window, marked the new layer in
autoExpandedLayersRef and expanded stale container ids; once fresh
topology arrived the guard skipped the layer, so the new layer's small
containers never auto-expanded.

Bail while a new-layer layout is in flight using the existing newLayoutRef
(same guard the fitView effect already uses) before mutating the ref.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Muammer06

Copy link
Copy Markdown
Author

@Lum1104 I solved the probably bug, you can check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants