Skip to content

fix: Reveal, Counter, Blur Text and Text Split play their entrance when a panel opens - #60

Open
catgarret wants to merge 3 commits into
agent/claude/ci-annotate-flakesfrom
agent/claude/reveal-panel-reopen
Open

catgarret wants to merge 3 commits into
agent/claude/ci-annotate-flakesfrom
agent/claude/reveal-panel-reopen

Conversation

@catgarret

Copy link
Copy Markdown
Owner

Stacked on #59. See CHANGELOG [Unreleased] and docs/QA_REPORT.md 2026-09-30.

…dialogs)

An element in a closed panel (display:none on it or an ancestor) has no
layout box. ScrollTrigger measured it as a 0x0 box at the top of the
viewport (start -765 / end 0 in the Bootstrap example), and the native
boundary observer read the 0x0 rect as "above the viewport". So with GSAP
a default once:true entrance ran while nobody could see it and the
content simply appeared when the panel opened, and a once:false entrance
replayed only its tail on reopen (GSAP 80%, native 58-67% already in) or
not at all: the Bootstrap example's FAQ answer and offer dialog showed
their content with no entrance the second time they opened.

Every Reveal path (GSAP tween, the mask/wipe/clock clock, class-only,
native) now follows three rules, documented in reveal.js "PANELS THAT
OPEN AND CLOSE" and docs/modules/reveal.md:
- nothing plays while the element has no box (ScrollTrigger callbacks
  check hasBox(); a tween whose toggle action already ran is reset);
- losing the box puts a repeatable (or not yet seen) entrance back to
  its start at once, with no onLeave;
- getting it back re-measures the trigger and plays the entrance once
  the element is on screen; once:true plays only the first time.
observeBoundaries() takes an options object instead of seven positional
arguments and reports onBox(hasBox). Without a layout engine (jsdom:
not even the root has a box) everything counts as boxed, as before.

Gates: tests/browser/reveal-panel-reopen.mjs (both browser lanes, with
and without GSAP; the old code fails five checks in all three engines)
and a reopen check in tests/integrations/bootstrap-qa.mjs (old code:
lowest opacity 1). Cost: reveal.js gzip 5,369 -> 5,880 B; product
ceilings move by the budget rule to 177 full/all, 181 React, 182 Vue
(Vite 176.1/179.9/181.1, Rolldown 176.4/180.1/181.7).

Docs: CHANGELOG [Unreleased] EN/KO, QA_REPORT 2026-09-30,
docs/consumer-bundle-size.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FauCMhuVzQvUy2RZAXchUa
… 1.2 s

PR #59 CI (a3e652b) retried WebKit 1/3 flip-fold: all 12 pinned copies
were still there 1.2 s after a 0.6 s change (their animations had not
finished), and the retry passed. The check now polls until they are
gone (at most 5 s) and reports how long that took; a copy that is never
removed still fails. CHANGELOG [Unreleased] Tests bullet and
QA_REPORT 2026-09-30 note the CI run (attw annotation gone, no Slider
retry). Verified in Chromium, WebKit and Firefox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FauCMhuVzQvUy2RZAXchUa
… opens

After the Reveal fix, the same probe (closed panel -> open -> close ->
reopen, a fingerprint of text/opacity/filter/transform every frame) over
the other modules with a `once` option found the same class on the GSAP
path: a Counter in a closed tab counted while nobody could see it (3454
of 5000 when the tab opened), a once:false Text Split did not replay on
reopen, and a once:false Blur Text replayed only in part.

The panel rules move to src/utils.js: hasBox(), watchBox(), and
panelGate(el, { once, enter, reset }) for an entrance a ScrollTrigger
starts (trigger(config) wraps the four boundary callbacks, watch(trigger)
follows the element's box). Counter (the trigger-driven animation of
plain/digit/pop/slot), Blur Text and Text Split use it; Reveal imports
hasBox/watchBox from there. watchBox() also observes the nearest
non-inline ancestor: ResizeObserver reports an inline element (a <span>
headline) as 0x0 whether shown or not, so a panel opening around a Blur
Text or Text Split went unnoticed.

Gate: tests/browser/panel-entrances.mjs (both browser lanes): Blur Text,
Text Split, Counter plain and slot and an inline Reveal play on the first
open, replay on every reopen with once:false, stay put with once:true,
and a closed counter waits at 0. The previous code fails splitRepeat and
counterOnce. Module docs (counter, blur-text, text-split) describe it.

Size ceilings by the budget rule: kineto.js 647.7/177.7 -> 654/178,
kineto.min.js 505.9/157.9 -> 511/158, UMD 504.0/157.3 -> 509/158,
Rolldown Vue consumer 182.2 -> 183.

Also tests/integrations/bootstrap-qa.mjs: the accordion wait timed out
about once in fifteen loaded runs (caught once in verify:push). Its new
state report showed the opened answer below the fold (scrollY 1593,
trigger start 1768): Bootstrap's scroll-behavior: smooth animates the
scroll Playwright makes for the click, and Reveal rightly waited. The
test scrolls the answer on screen first: 0 failures in 30 loaded runs.

Docs: CHANGELOG [Unreleased] EN/KO, QA_REPORT 2026-09-30.
Verified: lint, Node lane 65/65, Chromium browser lane 51/51 (verify:push),
panel-entrances / reveal-panel-reopen / text and lifecycle / components /
idle-cost / create-cost in WebKit and Firefox (9/9 each).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FauCMhuVzQvUy2RZAXchUa
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

This branch has not been deployed

No deployments
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