Repeater: collapse empty field wrappers via padding, not display:none (fixes Safari zero-height rows) - #92
Open
juliacanzani wants to merge 1 commit into
Open
Conversation
…:none — unbreaks Safari WebKit evaluates `:has(> [data-overlay-container]:empty)` for a freshly inserted subtree BEFORE the subtree's children are attached, so on insertion the selector matches EVERY field wrapper — and WebKit then fails to re-evaluate once children exist. The stale `display: none` persists in the used style (getComputedStyle reports the corrected value, which makes this miserable to debug) until any later stylesheet mutation forces a global recalculation. Observable result: opening a repeater-advanced row in Safari expanded to an empty zero-height strip, with all fields present in the DOM but boxless, for many seconds — until some unrelated style invalidation happened to occur. `padding: 0` keeps the intent (an empty wrapper's only footprint is its padding) with a graceful stale-case: visible fields briefly render without wrapper padding instead of being invisible, self-correcting on the next recalculation. Applied to both repeater layouts using the pattern (advanced, block). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
juliacanzani
marked this pull request as ready for review
August 25, 2026 01:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(not needed if #93 is approved)
Symptom
Opening a row in a
layout: advancedrepeater in Safari expands to an empty zero-height strip — the row's fields are in the DOM but have no layout boxes — and stays that way for many seconds (sometimes indefinitely), until some unrelated global style invalidation happens to occur. Reported from Tangible SearchSync's index-settings screen ("the repeater takes several seconds to expand"), reproduced deterministically in Playwright WebKit; Chromium is unaffected.Root cause
WebKit evaluates
:has(> :empty)for a freshly inserted subtree before the subtree's children are attached, so at insertion the selector matches every field wrapper in the new row — and WebKit then fails to re-evaluate once the children exist. The staledisplay: nonepersists in the used style. Debugging note for posterity:getComputedStyle()re-resolves fresh and reportsdisplay: blockwhile the render box simply doesn't exist, andelement.matches(...)returns the correct (non-matching) result — everything reads healthy while nothing paints.Evidence chain (all Playwright WebKit against a live WP admin page):
offsetHeight/offsetWidthof 0 at every level down to bare<input>s, despite computeddisplay: block/flexandmin-height: 32px.scrollHeight0.Fix
padding: 0instead ofdisplay: none, in both repeater layouts using the pattern (advanced,block). The rule's intent survives — an empty wrapper's only footprint is its padding, so zeroing it collapses the wrapper to 0×0. And the WebKit stale-match now degrades gracefully: visible fields briefly render without wrapper padding (self-corrects on the next recalculation) instead of being invisible for seconds.Verified in both engines on the reporting screen (8-row and 120-row repeaters):
Not changed, worth a look
assets/src/components/base/tab/index.scsshas the same pattern (&:has(> .tf-tab-row-field > div[class*='tf-context-']:empty) { display: none }). A padding swap is not equivalent there — the rule hides a whole labelled row, so zero padding would still leave the label visible. It carries the same WebKit stale-match risk for tab rows mounted after initial render; flagging rather than changing speculatively.Source-only change — needs a build before release.
🤖 Generated with Claude Code