Skip to content

fix: Auto-arrange follows cards that grow (#655) - #656

Merged
a-ratz merged 6 commits into
ui-reworkfrom
fix/655-relayout-on-resize
Oct 12, 2026
Merged

a-ratz merged 6 commits into
ui-reworkfrom
fix/655-relayout-on-resize

Conversation

@a-ratz

@a-ratz a-ratz commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Fixes #655 (into ui-rework, merged to main with #623).

What was wrong

With Auto-arrange on, the Flow lays itself out again when nodes or edges arrive, but not when an agent's card changes its size. A card that grows keeps its top and grows downwards: in Quick, Draw! the guesser card gains a row of thumbnails with every new guess and slides out of the bottom of the view; in a column of the hierarchical layout a growing card runs into the card below.

What changed

  • autoLayoutTrigger.ts: cardsResized(laidOut, cardSizes) says whether a card is 8 px or more (RESIZE_THRESHOLD_PX) off the size the last layout used; a card the last layout did not place is the topology trigger's. RESIZE_LAYOUT_DELAY_MS = 30.
  • GraphCanvas: keeps the card sizes each layout used (cards no layout placed take their first size as the baseline, also when Auto-arrange is switched on); when React Flow reports new node dimensions it checks 30 ms later whether a card is off them and lays the board out again (not after the 500 ms debounce); a layout already due for new nodes or edges comes forward instead. AgentNode keeps cardSizes up to date with a ResizeObserver too (a card resizing without rendering, fonts loading). The layout centres the board on the view and glides there (Dashboard: a new layout of the Flow jumps instead of gliding #650), so the growing card grows up and down. An unfolded agent keeps its card's size (cardSizes) and does not count, nor does folding it back; with Auto-arrange off nothing moves on its own.
  • AgentNode: with Auto-arrange on, a card that grows opens the part it grew by (clip-path from inset(0 0 <growth> 0), 200 ms, the glide's easing) while the board moves, so the new row does not pop in below; growing again continues from what it hides, shrinking cancels the opening. With reduced motion nothing animates.

Before and after

Before (the v0.5.8 video's take, Auto-arrange off as the recorder had it): the guesser has grown down to the dock.

before

After (--fake guesser, Auto-arrange on, 1.5x): a new row of thumbnails; the card opens it while the board glides up, in one movement.

after

check_motion.py on that take: three growths, each a glide over 7 to 8 frames, no move in a single frame (before this change, a card that grew showed as a 104 px step, followed 0.5 s later by the layout).

Tests

  • autoLayoutTrigger.test.ts: cardsResized is true for a card 8 px or more off in height or width; false for small changes, unchanged cards, new cards and no layout yet; RESIZE_LAYOUT_DELAY_MS is at most 50.
  • AgentNode.test.tsx: a card that grows by 60 px animates its clip from inset(0px 0px 60px 0px) to inset(0px 0px 0px 0px) in MOVE_MS; nothing opens with Auto-arrange off; shrinking again cancels the opening; the ResizeObserver keeps cardSizes up to date.

They failed before the change. npm test: 756 passed; npm run type-check clean. The images under docs/internal/design-system/screenshots/655/ are removed before the merge.

🤖 Generated with Claude Code

a-ratz and others added 2 commits October 13, 2026 00:51
With Auto-arrange on, the Flow laid itself out again only when nodes or
edges arrived. A card that grew (the guesser's new row of thumbnails)
grew downwards, out of the view or into the card below. GraphCanvas now
keeps the card sizes the last layout used; a card 8 px or more off them
(cardsResized) lays the board out again 30 ms later instead of after the
500 ms debounce, centred and gliding (#650), and AgentNode opens the part
its card grew by (clip-path) at the pace of that glide, so the card grows
up and down in one movement. An unfolded agent keeps its card size and
does not count; Auto-arrange off moves nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@a-ratz

a-ratz commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Local Codex review, round 1 (codex review of the branch against its base, at dcfe2bb).

Findings as reported

Target: branch diff against origin/ui-rework

The resize trigger misses DOM-driven size changes, and the reveal animation also affects boards with Auto-arrange disabled. Type checking and the frontend suite pass: 753 tests passed, 3 skipped.

Full review comments:

  • [P2] Compare fresh card dimensions when handling a resize — src/flock/frontend/src/components/graph/GraphCanvas.tsx:140-142
    If a card changes size outside a React render—for example, when the imported Geist fonts finish loading—cardSizes still contains its previous dimensions when this callback runs. The comparison returns false; the resulting render updates the cache afterward, but no further dimensions event occurs, so Auto-arrange misses the resize and can leave overlapping cards. Read fresh folded-card dimensions before comparing and laying out, or perform the check after the measurement cache updates.

  • [P3] Skip the growth reveal when Auto-arrange is disabled — src/flock/frontend/src/components/graph/AgentNode.tsx:275-277
    With Auto-arrange off, a card growing by at least 8 px still runs this animation, hiding and gradually revealing its bottom content for 200 ms even though the board does not make room. This changes manually arranged boards despite the changelog explicitly promising they remain unaffected. Gate the growth animation on Auto-arrange being enabled.

…655)

Review round 1:
- AgentNode keeps its card size up to date with a ResizeObserver too, so a
  card that resizes without rendering (fonts loading) is noticed, and
  GraphCanvas compares the sizes 30 ms after React Flow reports new
  dimensions, when they are measured. A layout already due is not
  replaced by the check.
- A card opens the part it grew by only with Auto-arrange on; a board
  arranged by hand keeps still.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@a-ratz

a-ratz commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Local Codex review, round 2 (codex review of the branch against its base, at 0729554).

Findings as reported

Target: branch diff against origin/ui-rework

Resize handling can remain inactive after enabling Auto-arrange, and interrupted growth animations can hide existing card content. Type checking passed; Vitest execution was blocked by the read-only temporary filesystem.

Full review comments:

  • [P2] Establish a resize baseline when Auto-arrange is enabled — src/flock/frontend/src/components/graph/GraphCanvas.tsx:143-144
    If Auto-arrange is disabled during initial load and later enabled without new node or edge IDs, applyLayout has never run and laidOutRef remains null. Since cardsResized(null, ...) always returns false, every subsequent resize is discarded, allowing growing cards to overlap or leave the view despite Auto-arrange being enabled. Initialize the baseline from measured cards when enabling Auto-arrange rather than requiring a topology change or manual layout first.

  • [P2] Cancel the growth reveal when the card shrinks — src/flock/frontend/src/components/graph/AgentNode.tsx:287-288
    When a card grows and shrinks again within MOVE_MS, such as a streaming ticker appearing and disappearing during a fast run, this early return leaves the previous clipPath animation running. Its bottom inset now clips existing content on the smaller card until the animation finishes. Retain the running animation and cancel or rebase it when the card shrinks.

Review round 2:
- Cards no layout placed yet (Auto-arrange switched on, a board from saved
  positions) take their sizes then as the baseline a resize compares
  with, also when Auto-arrange is switched on.
- A card that shrinks again while it opens cancels the opening, which
  would clip what is left; one that grows again opens from what it hides
  now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@a-ratz

a-ratz commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Local Codex review, round 3 (codex review of the branch against its base, at d31e838).

Findings as reported

Target: branch diff against origin/ui-rework

The shared debounce timer can delay making room until after the card's growth animation finishes. Type checking passed; Vitest could not start because the read-only sandbox blocks its temporary-directory creation.

Review comment:

  • [P2] Let resize layouts preempt the topology debounce — src/flock/frontend/src/components/graph/GraphCanvas.tsx:138-138
    If a new node or edge has already queued the 500 ms topology layout, this guard suppresses the subsequent 30 ms resize layout. AgentNode still reveals its added height over 200 ms, so the enlarged card becomes fully visible before surrounding nodes make room, recreating the overlap or offscreen growth this change addresses. Bring the pending layout forward when a card resizes, while preserving the topology-triggered layout.

Review round 3: a layout due for new nodes or edges (500 ms) suppressed
the resize check, so the board made room only after the card had opened.
A card that resizes now brings that layout forward to 30 ms, whole (it
stays the topology layout); without one due it schedules the resize
check as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@a-ratz

a-ratz commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Round 3 is addressed in 1f8454e. The local review stops here after three rounds; a fake Quick, Draw! take on the final build shows each growth of the guesser as one glide over 8 frames and no move in a single frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@a-ratz
a-ratz merged commit 0b98f6b into ui-rework Oct 12, 2026
3 checks passed
@a-ratz
a-ratz deleted the fix/655-relayout-on-resize branch October 12, 2026 23:14
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.

1 participant