Skip to content

fix(NotchGrid): guarantee distinct panels never overlap at gap=0#323

Closed
I-am-nothing wants to merge 5 commits into
mainfrom
fix/notch-grid-adjacent-group-overlap
Closed

fix(NotchGrid): guarantee distinct panels never overlap at gap=0#323
I-am-nothing wants to merge 5 commits into
mainfrom
fix/notch-grid-adjacent-group-overlap

Conversation

@I-am-nothing

Copy link
Copy Markdown
Contributor

Problem

In an app-overview NotchGrid (web-applications), two UNRELATED right-column panels — Summary (filled/secondary) and Manage (filled/tertiary), different keys, no shared `groupKey` — rendered with their outlines stuck together: Manage's top cutting up into Summary's bottom.

Root cause (verified by reproduction, not assumption)

Two distinct panels placed on touching cells with `gap={0}` + `panelBleed={4}` render outlines that overlap by `2·panelBleed` = 8px. `grid-outline.ts` computes `erosion = gap/2 − bleed`; at `gap=0` that is `−panelBleed` (net outward dilation), and nothing in the kit guarantees separation between distinct components. Manage paints after Summary → its dilated top overlaps Summary's dilated bottom.

Ruled out — the 8-connected grouping merge. `findConnectedComponents` does merge touching placements, but `groupComponents` buckets by `groupKey` first, and a panel with `subItems` gets its own key as `groupKey` (NotchGrid.tsx:749). Verified via the real render path: distinct-keyed touching panels stay two separate chromes (2 ``), so the "joined shape" was overlapping-but-separate outlines, not a real mask merge.

Fix

`NotchGrid` now derives per-component outline geometry (`computeComponentOutlines`): each component's outward `panelBleed` is capped at half the empty pixel space to its nearest distinct neighbour, and a flush neighbour forces a small inward seam (`MIN_COMPONENT_SEP`). Distinct components stay visually separated regardless of the `gap` prop; well-separated layouts keep the full `panelBleed` unchanged (only kicks in for default `panelBleed=0` never).

Tests

  • New regression test: two distinct-key, distinct-theme, ungrouped panels stacked flush with `gap=0`+`panelBleed=4` → asserts two separate chromes AND no outline overlap. Fails before the fix (`44 < 52`, the 8px overlap), passes after.
  • Full suite: 786 passing; typecheck + lint clean.

Bumps to 0.5.17 (patch, pre-1.0) paired with the `release` label.

🤖 Generated with Claude Code

Two unrelated components (different keys, no shared groupKey, different
themes) placed on touching cells rendered with their outlines overlapping
by 2*panelBleed px — the later-painted panel cutting up into the one above
— because panelBleed dilates every outline outward and gap=0 applies no
counter-erosion. Grouping was correct (they stayed two separate chromes);
the defect was purely in outline geometry (grid-outline erosion = gap/2 -
bleed going negative with no inter-component protection).

NotchGrid now caps each component's outward bleed at half the empty space
to its nearest distinct neighbour and forces a small seam when a neighbour
is flush, so distinct components always stay visually separated regardless
of the gap prop. Well-separated layouts keep the full panelBleed unchanged.

Bump 0.5.17; add regression test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@I-am-nothing I-am-nothing added the release Trigger a version bump on merge label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Storybook Preview: https://mirrorstack-ai.github.io/web-ui-kit/pr/323/

github-actions Bot added a commit that referenced this pull request Jul 1, 2026
…t a fixed px

MIN_COMPONENT_SEP was a flat 2px, imperceptible at typical block sizes and not
what "leave a gap between distinct panels" actually needs. Replaced with
MIN_COMPONENT_SEP_FRACTION (0.25 of one cell), so the guaranteed seam scales
with the grid's live block size the same way callers already reason about
spacing in cell/tile units.
github-actions Bot added a commit that referenced this pull request Jul 1, 2026
Replace the per-component bleed-capping/eroding approach (computeComponentOutlines)
with a position nudge (computeComponentNudges): distinct touching components get
pushed apart by enough to cancel their bleed's outward dilation plus the desired
MIN_COMPONENT_SEP_FRACTION seam, applied to where each component renders (its
wrapper's left/top, the same mechanism already used for drag offsets) rather than
varying its gap/panelBleed. Every component's own outline shape is now identical
regardless of its neighbors — only its position shifts.

Strengthened the regression test to also assert each panel's own outline
dimensions are unchanged (proving the fix is position-only), and fixed the nudge
magnitude to account for panelBleed's full outward reach (previously only offset
by half the target seam, which undershot when panelBleed was nonzero).
github-actions Bot added a commit that referenced this pull request Jul 1, 2026
…ound race

agentBodyH started at 0 and was only ever set by ResizeObserver's own
callback, which the spec requires to fire asynchronously — even for the
very first observation. That left a real (if usually brief) window on every
sidebar open where windowBodyHeight was omitted from AgentSidebarHeader,
so the transparent body (which depends entirely on the header's single-shape
fill reaching down over it) rendered with no background at all until the
async callback landed.

Switch the effect to useLayoutEffect and seed agentBodyH synchronously via
getBoundingClientRect() before attaching the observer, so the very first
paint already has a real height. The observer still owns every subsequent
resize (drag, viewport changes, content growth) — this only closes the
initial gap.
github-actions Bot added a commit that referenced this pull request Jul 1, 2026
Reflects the NotchGrid position-nudge fix (gap=0 + panelBleed distinct-panel
overlap) as a minor rather than patch — the fix changed the resolved geometry
of any component that touches a distinct neighbor, not just an edge case.
@I-am-nothing

Copy link
Copy Markdown
Contributor Author

Superseded by #325 — this branch picked up an unrelated commit from a concurrent session that now conflicts with main (main merged a different version of the same AppShell fix via #324). #325 is a clean cherry-pick of just the NotchGrid + version-bump commits off current main. Branch kept on origin, not deleted.

@github-project-automation github-project-automation Bot moved this from Backlog to Done in MirrorStack Platform Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release Trigger a version bump on merge

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant