Skip to content

Review 5547

Cindy Zhang edited this page Aug 27, 2026 · 5 revisions

Review #5547 — Toast shadow clipping

freddymeta · collaborator · OPEN · view on GitHub

PR

#5547fix(Toast): the card's shadow is no longer clipped away

HEAD REVIEWED

b962d810bdebad86f382853ced4bb2db7a820e08

VERSIONS

LOOP VERSION: 1.4.1 AUDIT RUBRIC: 1.12

Gate 1 read 1.4.1 from the Mac source of truth. The task named 1.4.0, but 1.4.1 had become current before this review began; the patch only makes the same loop self-contained and does not change judgement.

LANE

LANE: full WHY: this intentionally changes pixels and the clipping primitive, so browser paint, exit clipping, pointer hit testing, stacking, and scroll-container semantics all require direct evidence.

STEP 0

Clear. The head is in facebook/astryx, freddymeta has write permission, and the exact two changed paths are one component source file plus one changeset. No dependency, lockfile, workflow, install hook, executable script, credential, environment, or build-network path changed.

PROBLEM

The Toast card already declares its elevation shadow, but the inner grid-collapse wrapper clips exactly at the card border box. A person therefore sees a flat Toast, and a theme-authored shadow cannot paint outside the card.

The exact parent reproduced the defect: all 15 sampled pixel rows below the card were 255,255,255 even though the computed box-shadow was present.

VERDICT: clear

SOLUTION

The inner grid item remains the collapse clip, but changes from overflow: hidden to overflow: clip and extends its clip edge by 32px. Because clip does not zero a grid item's automatic minimum size, min-height: 0 keeps the row able to collapse. The chosen primitive restores the shadow in Chromium, but it also depends on engine support and extends descendant hit testing during exit.

SOLUTION (2 decisions · 3 declarations in 16 added runtime lines of 42 changed lines)

  1. Change the clip primitive and extend its edge by 32px so the existing Toast shadow can paint.
  2. Explicitly zero the grid item's minimum block size so the exit row still reaches zero.

VERDICT: BLOCKS — the selected primitive does not restore the shadow in WebKit and broadens Chromium's exit hit boundary.

ARCHITECTURE

OWNER: ToastViewport owns the stack, the collapse row, and its clipping boundary; Toast remains the painted and themed surface. TIER 1: browser-native grid transitions, overflow: clip, and overflow-clip-margin. TIER 2: none. SEAMS: top-layer popover viewport, nested dialog viewport, stacked sibling order, endContent actions, all four positions. BEHAVIOR UNIT: inline CSS declarations — the behavior is a browser layout/paint contract, so the focused boundary probes are the testable unit.

seam driven result
top-layer portal exact head remained :popover-open; the outer viewport stayed overflow: visible and the Toast remained at the same 400×52 geometry
stack paint/order a middle Toast overlapped the later sibling during collapse, but the later sibling's dismiss target still won hit testing in both parent and head
action during exit Chromium exact head kept an out-of-clip Undo action hit-testable and a real pointer click fired it; exact parent did not
scroll-container semantics hiddenclip removes the inner scroll container; this private grid item has no scroll API, sticky descendant, or scroll-linked behavior, so no reachable scroll regression was found
candidate boundary resetting only the exit-state clip margin to 0 restored the old action hit boundary while leaving the resting shadow frame pixel-identical

The owner remains correct and no portal/z-index owner moves. The cross-engine and pointer behavior of the chosen clip primitive is not safe yet.

VERDICT: BLOCKS — the clipping boundary changes beyond shadow paint.

IMPACT

In Chromium, every stock and themed Toast gets the intended elevation; the exact-head centerline changes from white to a 14px shadow falloff. In WebKit 26.5, overflow-clip-margin is unsupported and every sampled row remains white, so WebKit 26.5 users keep the original defect.

During Chromium dismissal, content admitted by the 32px clip margin remains hit-testable outside the collapsed row. A Toast action can therefore fire after dismissal has begun while the surface is mostly transparent.

Two open Toast layout PRs — #5353 and #5541 — also touch this wrapper. They will need to rebase around whichever cross-browser clipping shape lands, but they do not prevent this author from correcting the exact head.

VERDICT: BLOCKS — WebKit 26.5 users do not receive the fix, and Chromium users gain an unintended exit action window.

API

No public prop, type, export, default, callback, role, DOM attribute, or call shape changes.

change public? class doc'd? verdict
no API change clear

OSSIFICATION: the 32px clip allowance is private layout implementation, not a new theme target or public promise. Its engine dependence still has to be corrected before landing.

VERDICT: clear

THEMING

No theme target, token, variable, selector, or state reflection changes. The existing astryx-toast target remains on the element that paints the shadow, and --shadow-med remains the source of the default value. The 32px clip allowance is component-owned clipping, not theme surface.

The intended result reaches existing shadows only in engines that implement overflow-clip-margin; WebKit leaves the same theme paint clipped.

VERDICT: BLOCKS — existing theme shadow output remains unreachable in WebKit.

BREAKING

BEHAVIOR: yes — Chromium pointer hit testing expands outside the collapsing inner box; an exiting Undo action can now fire where the parent rejected the same click. API: no — signatures and semantics exposed to TypeScript are unchanged. VISUAL: yes — the resting shadow is intentionally restored in Chromium; the card also paints farther outside the shrinking row during exit. WebKit remains visually unchanged and therefore unfixed. THEME: no surface break — no target/token changes, but existing shadow overrides remain clipped on WebKit.

VERDICT: BLOCKS — the behavior delta is unintended and the stated visual goal is engine-incomplete.

PERFORMANCE & RESOURCES

EFFECTS: zero added or moved. RENDER: no React render-path change. LISTENERS/OBSERVERS: zero added. LAYOUT: no JavaScript reads/writes or forced reflow; CSS paint may extend up to 32px around at most five visible Toasts. BUNDLE: no dependency and only three runtime CSS declarations in the reviewed source change.

No performance or resource regression was found. The paint-area cost was not separately timed because there is no hot O(N) JavaScript path and wall-clock paint timing would not be an actionable invariant.

VERDICT: clear

VISUAL EVIDENCE

VISUAL CHECK: manual frames required WHY: the PR intentionally changes visible shadow pixels, and the exact-head visual job reported no compared Toast change because 16 shots had no baseline.

The decisive pair was opened and inspected. The before image has a hard white edge directly under the card; the after image has a soft gray falloff through row +14, with no card geometry change.

Sensor Before After
Build parent 58f95421362527e586c078b9377b1fcab2274910 head b962d810bdebad86f382853ced4bb2db7a820e08
Receipt JSON JSON
Story core-toast--default same
Theme / mode / direction neutral / light / LTR same
Viewport / media 900×520 @1; forced colors off; reduced motion off; fine pointer; hover same
Semantic state one 400×52 info Toast; role=status; aria-live=polite; one dismiss control same
Geometry x484, y452, 400×52, visible in viewport same
Settled / errors fonts loaded; 0 animations; no page/Storybook error same
Pair check all sensors match except Build same
Exact parent — shadow clipped Exact head — shadow visible
Toast before: the card ends at a hard white edge with no visible shadow Toast after: a soft shadow is visible below and around the card

Pixel receipt: at the card centerline, row +1 changes 255 → 229, +6 255 → 245, +10 255 → 251, +14 255 → 254, and rows +15/+16 return to white. The exact PR delta is banked as exact-pr.diff.

Cross-engine control: WebKit 26.5 exact head reports CSS.supports(...) = false, no computed clip margin, and 15/15 white rows below the card. The exact parent is identically clipped.

VERDICT: BLOCKS — Chromium proves the intended pixels, while WebKit proves the stated cross-browser outcome is not achieved.

A11Y & I18N

No role, accessible name, live-region policy, focus handoff, string, locale, or logical-direction declaration changes. Exact-head pr-a11y and pr-rtl passed. The new pointer reach is a behavior regression rather than a change to the accessibility tree; it is carried in ARCHITECTURE, IMPACT, and BREAKING instead of double-counted here.

VERDICT: clear

JUDGEMENT

slot verdict
PROBLEM clear
SOLUTION BLOCKS — engine support and hit testing
ARCHITECTURE BLOCKS — clipping boundary widens beyond paint
IMPACT BLOCKS — WebKit remains broken; Chromium exit action stays live
API clear
THEMING BLOCKS — shadow remains clipped in WebKit
BREAKING BLOCKS — unintended pointer behavior
PERFORMANCE clear
VISUAL BLOCKS — stated result does not reach WebKit
A11Y & I18N clear

GOAL: partly met — Chromium restores the 14px shadow falloff with unchanged 400×52 geometry; WebKit 26.5 leaves all sampled rows white. DISPOSITION: both negative findings block this head. A cross-browser clipping shape must restore the resting shadow, and exiting content must not remain pointer-active outside the collapsing box. ADVICE: proven bounded direction — an inspected candidate that resets the clip margin only while exiting makes the out-of-box Undo click stop firing and preserves the resting Chromium frame pixel-for-pixel; it does not solve WebKit, so the final mechanism still needs a cross-browser paint path. candidate-exit-clip.diff · candidate action receipt · pixel control. AUTHOR CAN PROCEED: yes — acceptance is concrete: the stock resting shadow paints in Chromium and WebKit, the collapse reaches zero, and an action outside the shrinking clip cannot receive a real pointer click during exit. WORST OUTCOME: “WebKit 26.5 users still get no Toast shadow, while Chromium users can activate an almost-gone Toast action after dismissal starts.” → request changes

JUDGEMENT NEEDED: none

request changes

  1. [BLOCKS] WebKit 26.5 ignores overflow-clip-margin, so the shadow remains fully clipped. → WebKit 26.5 users receive no visible fix · packages/core/src/Toast/ToastViewport.tsx:101
  2. [BLOCKS] Chromium applies the 32px margin to hit testing during exit. → a real click can fire an action outside a 2.73px collapse box while the Toast is 23% opaque · packages/core/src/Toast/ToastViewport.tsx:101

Independent confirmation: the exact parent rejects the same action click, and the exact candidate exit-only 0px margin rejects it while leaving the resting frame byte-identical.

REVIEW

Thanks — the Chromium shadow and collapse both work.

ToastViewport.tsx:101 still needs a cross-engine fix. WebKit 26.5 does not support overflow-clip-margin; all 15 sampled rows below the card stayed white, so the shadow remains clipped. In Chromium, the 32px margin also expands hit testing during exit: with the clip box 2.73px tall and the toast 23% opaque, a real click on the out-of-bounds Undo action fired; the parent did not.

Could we preserve the old exit hit boundary and make the resting shadow visible in WebKit too?

[Reviewed by Robohands]

Public review length: 90 words (request-changes cap: 150).

INLINE

None. Both failures come from the same declaration and are clearer together in the summary.

EVIDENCE I DID NOT SPEND

  • The head is 20 commits behind current main but GitHub reports it mergeable; age is under one day, so this is not a staleness finding.
  • #5353 and #5541 overlap the Toast wrapper, but neither makes this exact-head cross-engine/pointer result disappear.
  • The 13-line inline comment largely repeats the PR body; omitted as polish because the two behavior defects decide the verdict.

EVIDENCE AND TESTS

  • Focused Vitest: ToastViewport.test.tsx — 13/13 passed.
  • Strict ESLint on ToastViewport.tsx — passed.
  • Core TypeScript --noEmit — passed.
  • Changeset gate — 28 changesets valid; this [fix] / patch entry passed.
  • Exact-head CI: build, test, lint, Storybook, a11y, RTL, theme layers, sandbox, and Vercel green; review-required remains pending as expected.
  • Chromium manual pair: passing captureWithSensors() receipts; pair equality checked with only Build differing.
  • Chromium action probe: parent hit=false/fired=false; head hit=true/fired=true; candidate hit=false/fired=false.
  • WebKit 26.5 paint probe: overflow: clip, overflow-clip-margin unsupported, 0/15 non-white rows on both parent and head.
  • Full reproducibility bundle: assets/pr-5547.

TIME

TIME total 42m setup 6m — exact-head worktree, fresh fork/public wiki clones, fast install, Storybook reading 9m — body/test plan, current kit, audit 1.12, rulings, design/API guidance, source/history/overlapping work measuring 18m — Chromium frames, pointer action A/B, candidate arm, WebKit control, focused checks writing 6m — R16 presentation, public text, evidence receipts waste 3m — corrected one generic readiness selector and one transparent-surface sensor expectation before banking evidence

WHAT I COULD NOT VERIFY

  • Firefox was not run after WebKit independently falsified the cross-engine claim; another passing engine would not change either blocker.

CRITIC

One artifact-only critic pass found four presentation defects and they were corrected: the page title now links the PR, the WebKit result no longer overclaims every Safari build, the unsupported bundle-report claim was removed, and the time ledger now sums. The critic also rechecked both blocks against independent controls, the 90-word cap, the signature, every slot verdict, AUTHOR CAN PROCEED, and the exact-head anchor. No verdict changed.

WHAT CHANGED BEFORE POSTING

Nothing was posted to the PR. This run made no GitHub review, comment, merge, auto-merge, or contributor-branch push. Only this fork-wiki review record and its evidence assets will be published.


Round 2 — current-head re-review

Head reviewed: 5df116926a18b8f399f8c0caa854756334a5becc Previously reviewed head: b962d810bdebad86f382853ced4bb2db7a820e08 PR merge-base / head's main parent: 5b5f1903a8eeccde0e404062a44a168e81677279

Verdict: request changes (drafted; no public PR action)

Versions

LOOP VERSION: 1.5.0
AUDIT RUBRIC: 1.13

The original Round 1 record remains unchanged above. This is a fresh re-review under the versions current when this gate began.

Lane and safety

LANE: full. This round must re-drive two prior cross-engine/interaction blocks, inspect a merged-main conflict resolution, and validate intentional paint plus exit hit testing.

Step 0 passed. The current PR patch is three safe paths: one Toast source file, its test, and a changeset. No dependency, lockfile, workflow, package script, executable tool, credential, environment read, or build-network path changed.

Prior review and delta

Our Round 1 request at b962d810 asked for two outcomes at ToastViewport.tsx:101: restore the resting shadow in WebKit 26.5, and prevent an out-of-bounds Undo action from firing during Chromium exit. Rubyycheung's design approval said the intended elevation and dismissal motion were correct.

The new head merges #5353 from main and resolves the Toast conflict. Relative to exact base 5b5f1903, the PR is three files, +102/−13:

  1. keep overflow: hidden through entry and exit, then switch to visible after the opening grid transition;
  2. track settled Toast ids in viewport state;
  3. set the exiting wrapper to pointer-events: none;
  4. add a lifecycle test and rewrite the changeset around the new mechanism.

Current origin/main is three unrelated commits ahead at a7ad8f98; its Toast source and story blobs are byte-identical to the exact PR base, so main has not invalidated this patch.

Problem

WHY 1: The collapse wrapper clips at the Toast card's border box, hiding the shadow the card already declares. WHY 2: A person sees a flat transient message instead of the intended separation from the page beneath it. WHY 3: Toast is a temporal overlay; losing elevation weakens the visual cue that it sits above the task in progress.

USER-FACING PROBLEM: A person receiving a Toast sees its elevation disappear even though the theme supplies it.

PROBLEM SEVERITY: polish. The message and actions remain usable; the defect is the intended elevation treatment.

VERDICT: clear

Solution — 2 decisions

The stack keeps the existing clipping boundary while a row opens or closes, then releases only the paint boundary after entry finishes. Dismissal restores clipping before collapse. The viewport owns that lifecycle because it already owns the row transition and removal.

  1. Track settled Toasts and switch the inner wrapper from hidden to visible after the real grid transition — the cross-engine shadow fix.
  2. Remove pointer hit testing from the entire wrapper as soon as dismissal starts — additional behavior intended to prevent the old out-of-clip action.

BURDEN: medium. One private Set, one transition handler, and one post-entry state update are added; no Effect, listener, observer, timer, public surface, or extra layout read appears.

BURDEN MATCH: proportionate after one deletion. The lifecycle state is the bounded cost of retaining entry/exit clipping while showing the resting shadow. Whole-wrapper pointer-events: none is broader than the failing state and is unnecessary once overflow: hidden returns for exit.

VERDICT: BLOCKS — the pointer guard lets a second click activate obscured app UI while the Toast remains fully visible

Architecture

OWNER: ToastViewport owns stack-row transition, clipping, and removal; Toast owns the painted surface
TIER 1: CSS @starting-style + grid transition; React event/state lifecycle
TIER 2: none
SEAMS: top-layer viewport, stacked rows, action Toast, all placements, nested dialog viewport
BEHAVIOR UNIT: inline — one transition boundary and one private id set; focused browser probes are the behavioral test
Seam Driven result
Entry → settled, Chromium 149 starts hidden; real grid transitionend observed; settles visible; 10/15 sampled rows below card contain shadow
Entry → settled, WebKit 26.5 starts hidden; real grid transitionend observed; settles visible; 10/15 rows contain shadow
Late exit, Chromium current head restores hidden; Undo center is outside the 2–3px inner box; Undo hit/fire are both false
Immediate exit, Chromium current head is still 52px high and opacity 1, but pointer-events: none sends the second dismiss click to the control underneath
One-line candidate deleting only pointerEvents: 'none' restores main's immediate interception and keeps the late Undo hit/fire false

The lifecycle owner is correct. The new pointer rule broadens the boundary beyond the defect.

VERDICT: BLOCKS — the interaction boundary regresses until the proven one-line correction is applied

Impact

The fix now reaches both tested engines: Chromium 149 and WebKit 26.5 show the existing stock shadow after settling, while entry and exit remain clipped. The two exact Round 1 failures are resolved.

At current head, a person who clicks Dismiss twice can activate a control obscured beneath the Toast on the second click while the Toast is still fully visible. Main and the one-line candidate instead let the still-visible dismiss control intercept that click.

VERDICT: BLOCKS — a person can activate unavailable UI underneath a still-visible Toast

API

No prop, type, export, default, callback, role, DOM attribute, theme target, or call shape changes. The settled-id set is private implementation and adds no ossified surface.

VERDICT: clear

Theming

No token, target, variable, or selector contract changes. The existing astryx-toast painting surface and --shadow-med value are unchanged; this patch makes their output visible after entry in both tested engines.

VERDICT: clear

Breaking

  • Behavior: yes, unintentionally at exact head — the whole exiting Toast stops intercepting pointers immediately, so a second click can reach obscured app UI. The previous out-of-clip Undo behavior is fixed.
  • API: no.
  • Visual: yes, intentionally — the existing shadow becomes visible at rest. Entry and exit remain clipped; card geometry stays 400×52 in the measured default.
  • Theme: no — existing targets, tokens, and overrides retain their meaning.
  • Empty/loading/error/disabled/controlled/boundary: not newly reachable; this diff changes Toast entry/settled/exit only.

VERDICT: BLOCKS — concrete interaction regressions cannot be downgraded when they activate obscured UI

Performance & resources

EFFECTS: zero added or changed. RENDER: one post-entry setSettledIds state update per settling Toast; dismissal's settled/exiting updates occur in the same event. LISTENERS/OBSERVERS: none added. LAYOUT: no JavaScript layout read/write in production; CSS still owns the transition. BUNDLE: no dependency; 51 runtime additions and 13 removals relative to the exact base.

The added render is the mechanism that releases the clip after the browser transition; no hot or user-sized loop is introduced.

VERDICT: clear

Visual evidence

VISUAL CHECK: manual frames required
WHY: the patch intentionally restores shadow pixels, and Toast lacked a compared visual baseline in the PR report.
Case Main control Current head Result
Chromium 149, settled default Toast Main: clipped shadow Current: visible shadow sampled rows below card: 0/15 → 10/15 non-white
WebKit 26.5, settled default Toast Round 1 exact-head evidence: 0/15 rows Current WebKit: visible shadow 10/15 rows now contain the shadow

Canonical receipts sit beside every PNG. Pair check confirms story, theme, mode, direction, viewport/media, semantic state, geometry readiness, animation state, and errors match across the compared arms; only Build differs for main/current. Chromium and WebKit both observed the real grid transition before settled overflow: visible.

The frames were recropped after the first capture used the pre-#5353 right-edge position and contained white space; the final files above contain the Toast and shadow pixels.

VERDICT: clear — the requested cross-engine paint outcome is now measured

A11y & i18n

Exact-head pr-a11y and pr-rtl are green. No role, name, live-region policy, focus handoff, string, locale, or direction declaration changes. Keyboard activation remains on the exiting control; the new defect is pointer click-through and is owned by IMPACT/BREAKING rather than duplicated here.

VERDICT: clear

Tests and checks

  • Exact head and current base confirmed before execution; git diff --check clean.
  • ToastViewport.test.tsx: 31/31 passed.
  • Targeted ESLint on source and test: passed with zero warnings/errors (Node's pre-existing module-type warning only).
  • Exact-head CI: build, test, lint, Storybook, a11y, RTL, theme layers, sandbox, dependency, scope, and Vercel checks green; review gate remains pending because our prior request-changes is still open.
  • Chromium 149 and WebKit 26.5 paint probes passed with canonical receipts and zero page errors.
  • Chromium main/head/candidate exit probes passed with real pointer clicks and zero page errors.
  • Reproduction bundle.

Judgement

Slot Verdict
Problem clear
Solution BLOCKS — whole-wrapper pointer guard activates obscured UI
Architecture BLOCKS — interaction boundary regresses
Impact BLOCKS — second dismiss click activates unavailable UI
API clear
Theming clear
Breaking BLOCKS — user-facing interaction regression
Performance clear
Visual clear — Chromium + WebKit
A11y & i18n clear

GOAL: met. WebKit 26.5 and Chromium 149 both transition hidden → visible and paint 10/15 sampled shadow rows at rest; Chromium exit returns to hidden, and the formerly out-of-bounds Undo action neither hits nor fires.

DISPOSITION: both Round 1 blockers are satisfied. The click-through regression blocks this head now; deleting pointerEvents: 'none' is the independently verified correction.

ADVICE: proven remedy. Delete pointerEvents: 'none' at ToastViewport.tsx:128. The banked one-line candidate restores main's immediate interception while preserving current head's WebKit shadow and late exit boundary.

AUTHOR CAN PROCEED: yes. No human decision is withheld; the concrete acceptance criterion is that a second click within the still-visible Toast remains intercepted while the late out-of-clip Undo remains unreachable.

WORST OUTCOME: “A person who clicks Dismiss twice can activate a control obscured beneath the still-visible Toast.” → request changes.

JUDGEMENT NEEDED: none — the design owner already approved the intended elevation; the remaining correction restores main's interaction boundary.

Critic

Gate 1 found the code issue but failed the screenshot-receipt rules: it included changed CSS in semantic-state equality and captured the old right-edge coordinates after #5353 moved the Toast left. Gate 2 regenerated matching receipts and preserved both independent confirmations, but incorrectly let the re-review rule downgrade concrete user harm. Gate 3 applies the standing impact floor: activating obscured UI is a user-facing interaction regression and blocks. PASS — request changes.

Verdict — request changes

One confirmed blocker remains at the current head. No public action was taken.

Exact public review text

Thanks — both requested fixes now pass in Chromium and WebKit.

A person who clicks Dismiss twice can activate an obscured control underneath while the Toast is still fully visible. pointerEvents: 'none' at ToastViewport.tsx:128 removes the whole exiting Toast from hit testing immediately. Main intercepts that second click, and deleting this declaration preserves the WebKit shadow and late-exit Undo fix.

Could we drop it before this lands?

[Reviewed by Robohands]

Inline

None. The single blocking finding is clearer in the request-changes body and already carries its exact line.

Evidence not spent

  • Current origin/main is three unrelated commits ahead of the merge base; Toast source and story blobs are identical, so no rebase-only finding exists.
  • The merged #5353 changes explain the large history delta but are already main; the current PR patch remains three files.
  • Closed #5541 is superseded by #5353 and no longer competes with this fix.

What changed before posting

Nothing was posted. This corrected re-review made no GitHub review, comment, merge, auto-merge, label, issue, or contributor-branch push. Only the fork-wiki record and its evidence are published.

Time

TIME  total 26m
  setup       4m   exact-head worktree, fresh wiki clones, safe fast install, warm main
  reading     7m   full history, prior review, current kit/rubric, merged-main delta, repo rules
  measuring   9m   Chromium/WebKit paint, main/head/candidate pointer A/B, focused checks
  writing     6m   presentation, three critic gates, verdict correction, wiki record
  waste       3m   cancelled a stray Safari process and recaptured a stale-position white crop
  warm main reused: yes — a7ad8f98; Toast source/story match exact base
  re-measures: 2 — corrected semantic-state receipts and the post-#5353 crop

What I could not verify

  • Firefox was not run; the prior engine-specific failure was WebKit, and WebKit 26.5 is verified directly at this head.

Round 3 — exact-head delta re-review

Head reviewed: 5eaa259f0d11e557d116e883dbcfdb7d0765c18a
Previously reviewed wiki head: b962d810bdebad86f382853ced4bb2db7a820e08
Prior posted request-changes head: 5df116926a18b8f399f8c0caa854756334a5becc
Prior approved head with notes: a022b53ea1a345b71ec060781111abc8cc42ab8b

Verdict: approve (drafted; no public PR action)

Versions

LOOP VERSION: 1.6.0
AUDIT RUBRIC: 1.13

Lane and safety

LANE: full. This is a visual and interaction delta re-review after request-changes: every prior finding, the stale settled-id note, the corrected changeset claim, and the affected Toast interaction radius were rechecked.

Step 0 passed before install/build. The effective PR file list is one Toast source file, its test, and one changeset; no dependency, lockfile, workflow, package script, executable tool, credential, environment-read, or build-network path changed.

Prior review and delta

Round 1 at b962d810 blocked on overflow-clip-margin: WebKit 26.5 ignored it, and Chromium kept out-of-row Undo hit-testable during exit. Round 2 at 5df11692 verified the hidden/visible mechanism fixed those, then blocked pointer-events: none because a second Dismiss click could activate obscured UI underneath. The approved note at a022b53e asked for stale settled ids to be pruned on overwrite and the changeset's hit-testing claim corrected.

The a022b53e5eaa259f delta is three PR files, +91/−18: add withoutId, prune a replaced toast's settled id when uniqueID overwrites, reuse the helper for dismissal/exit cleanup, add the overwrite lifecycle test, and rewrite the changeset sentence. The overflow mechanism and wrapper pointer-events: auto boundary are unchanged from the prior approved head.

Problem

WHY 1: Toast's collapse wrapper clips at the card border box, hiding the shadow the card already declares.
WHY 2: A person sees a flat transient message instead of the intended separation from the page beneath it.
WHY 3: Toast is a temporal overlay; losing elevation weakens the cue that it sits above the task in progress.

USER-FACING PROBLEM: A person receiving a Toast sees its elevation disappear even though the theme supplies it.
PROBLEM SEVERITY: polish — the message and actions remain usable; the defect is the intended elevation treatment.

VERDICT: clear

Solution

The stack clips each Toast while the row opens or closes, then releases only the paint boundary after entry finishes. Dismissal restores clipping before collapse. The viewport owns that lifecycle because it already owns the row transition and removal.

SOLUTION (2 decisions · private implementation only)

  1. Track settled Toast ids and switch the inner wrapper from hidden to visible after the real grid transition.
  2. Prune a replaced Toast's settled id when a uniqueID overwrite swaps in a new row.

BURDEN: medium — one private Set, one transition handler, and one post-entry state update per settling Toast; no new Effect, listener, observer, timer, public surface, or layout read.
BURDEN MATCH: proportionate — the state is scoped to the private row lifecycle needed to keep entry/exit clipped while the settled shadow paints.

VERDICT: clear

Architecture

OWNER: ToastViewport owns stack-row transition, clipping, and removal; Toast owns the painted surface
TIER 1: CSS grid transition, React event/state lifecycle
TIER 2: none
SEAMS: top-layer viewport, stacked rows, action Toast, uniqueID overwrite, all placements, nested viewport
BEHAVIOR UNIT: inline — one transition boundary and one private id set; focused browser probes and unit tests cover it
Seam Driven result
Settled shadow, Chromium main remains hidden; head settles visible; 0/15 → 13/15 sampled rows below the card contain shadow
WebKit prior finding mechanism unchanged from the prior approved head, whose WebKit 26.5 measurement showed the settled shadow visible
Second Dismiss click wrapper remains pointer-events: auto; an underlying control placed directly behind the dismiss point received 0 clicks
uniqueID overwrite toast id changes astryx-toast-1astryx-toast-2; replacement starts hidden, then settles visible

The lifecycle owner remains correct and the stale-id cleanup lives at the overwrite seam that creates the dead id.

VERDICT: clear

Impact

The two blocking interaction/browser findings are resolved: Chromium paints the resting shadow and the still-visible exiting Toast keeps intercepting pointer clicks. The WebKit-affecting mechanism did not change after the prior WebKit pass; this round's WebKit runner launched 26.5 but closed before opening a page, so the exact-head WebKit recheck was not repeatable in this run.

The overwrite fix has no visible end-user change unless a toast is replaced after it settled; in that state the replacement now starts clipped and releases the clip on its own transition instead of inheriting stale settled state.

VERDICT: clear

API

No prop, type, export, default, callback, role, DOM attribute, theme target, or call shape changes. The settled-id set and withoutId helper are private implementation.

VERDICT: clear

Theming

No token, target, variable, or selector contract changes. The existing astryx-toast painting surface and --shadow-med value are unchanged; the patch makes that already-declared output visible after entry.

VERDICT: clear

Breaking

  • Behavior: intended — settled Toast shadows paint; exit clipping and wrapper pointer interception are preserved.
  • API: no.
  • Visual: intended — the existing shadow becomes visible at rest. Chromium 149 shows 0/15 → 13/15 sampled non-white rows below the card.
  • Theme: no — existing targets, tokens, and overrides retain their meaning.
  • Empty/loading/error/disabled/controlled/boundary: not newly reachable; this diff changes Toast entry/settled/exit and overwrite cleanup only.

VERDICT: clear

Performance & resources

EFFECTS: zero added or changed.
RENDER: one post-entry setSettledIds update per settling Toast; overwrites and dismissals prune one id.
LISTENERS/OBSERVERS: none added.
LAYOUT: no JavaScript layout read/write in production; CSS owns the transition.
BUNDLE: no dependency.

The private Set is bounded by visible/to-be-exited Toast rows, and this round specifically removes the overwrite leak.

VERDICT: clear

Visual evidence

VISUAL CHECK: manual frames required
WHY: the patch intentionally restores shadow pixels, and the exact-head visual gate awaits human visual acceptance.
Sensor Main control Exact head
Build e6507a95fb13cae83f94e2d4b58009eaf584f1c6 5eaa259f0d11e557d116e883dbcfdb7d0765c18a
Story core-toast--deduplication same
Theme / mode / direction neutral / light / LTR same
Viewport/media 900×520 @1; forced colors off; reduced motion off; fine pointer; hover same
Semantic state one settled Toast, 400×52, no page/Storybook errors same
Clip state hidden visible
Main — shadow clipped Exact head — shadow visible
Main cropped Toast with no visible shadow below the card Exact-head cropped Toast with a visible shadow falloff below the card

Pixel receipt: main has 0/15 non-white rows below the card; exact head has 13/15, falling from 232 at row +1 through 254 at row +13.

VERDICT: clear

Remedy search

REMEDY SEARCH: not triggered — no proven visual defect

A11y & i18n

Exact-head pr-a11y and pr-rtl are green. No role, name, live-region policy, focus handoff, string, locale, or direction declaration changes. Pointer click-through was rechecked as behavior and no longer reproduces.

VERDICT: clear

Tests and checks

  • Focused test: ToastViewport.test.tsx — 32/32 passed.
  • Targeted ESLint on ToastViewport.tsx and ToastViewport.test.tsx — passed with zero warnings/errors, aside from Node's module-type runtime warning.
  • git diff --check on the PR files — passed.
  • Exact-head CI: build, test, lint, Storybook, a11y, RTL, theme layers, sandbox, dependency, scope, Vercel, and review-required passed.
  • CI still pending on visual-acceptance: stable visual changes await /accept-visual.

Judgement

Slot Verdict
Problem clear
Solution clear
Architecture clear
Impact clear
API clear
Theming clear
Breaking clear
Performance clear
Visual clear
A11y & i18n clear

GOAL: met. Chromium exact head restores the 13-row shadow falloff; the WebKit mechanism is unchanged from the prior approved WebKit-measured head; the second Dismiss click no longer reaches an underlying control; overwrite starts a fresh clipped row and then settles it independently.

DISPOSITION: Round 1 findings fixed; Round 2 click-through fixed; approved-head notes fixed. No negative finding remains.

ADVICE: omitted — no author-facing correction remains.

AUTHOR CAN PROCEED: yes — remaining external gate is visual acceptance, not an author code change.

WORST OUTCOME: none found.

JUDGEMENT NEEDED: none — the design owner already approved the intended elevation, and this round only validates the requested mechanics.

Critic

Gate 1 failed the visual slot because WebKit could not open a page in this run and the first image receipt did not display to the model. The corrected presentation limits the current-run engine claim to Chromium, carries prior WebKit evidence only for unchanged code, and states the exact verification gap. R1e passes: every prior finding and later note is named and disposed. R16g passes for the former blockers via source diff + browser interaction + focused tests. PASS — approve.

Verdict — approve

No code-review blocker remains. No public action was taken.

Exact public review text

Thanks — this addresses my remaining notes. The overwrite path starts clipped, settles independently, and the changeset now matches the current hit boundary. Good to approve once visual acceptance clears.

[Reviewed by Robohands]

Inline

None.

Evidence not spent

  • The last commit is a merge from main; the effective PR delta still only touches the Toast source/test and changeset.
  • The visual-acceptance workflow is pending because stable visual changes await /accept-visual; that is not a code-review finding.
  • WebKit 26.5 could not be rerun in this round because it closed before page creation twice; the code that mattered for the prior WebKit finding is unchanged since the approved WebKit-measured head.

What changed before posting

Nothing was posted. This re-review made no GitHub review, comment, merge, auto-merge, label, issue, or contributor-branch push. Only this fork-wiki record and its public-safe evidence assets are published.

Time

TIME  total 17m
  setup/rules       3m   memory, loop 1.6.0, rubric 1.13, fresh wiki clones, safety scan
  build/server      4m   fast install, one @astryxdesign/build build, exact-head Storybook, warm main reused
  browser/a11y      6m   Chromium visual/interaction probes; CI a11y/RTL read; WebKit retry failed before page creation
  focused tests     1m   ToastViewport test, ESLint, diff check
  code/history      2m   old→new delta, prior reviews, source/tests/changeset
  critique/wiki     1m   self-critic, wiki append, index update
  CI wait           0m   exact-head checks already complete except visual-acceptance pending
  waste             2m   one wrong Vitest cwd and two WebKit launch retries
  re-measures       2    main/head sensor correction; focused click-through probe with target placed under the click point

What I could not verify

  • Exact-head WebKit 26.5 browser evidence could not be recaptured: WebKit launched and then closed before opening a page in both headless and headed runs. The WebKit-affecting overflow code is unchanged from the prior approved head that was measured in WebKit.

Clone this wiki locally