Implement plain direction fade API - #4
Merged
Conversation
petekp
added a commit
that referenced
this pull request
Jun 27, 2026
Engine fix: - src/tw-fade.css: add neutral block-axis defaults to the shared base block so a nested vertical fade no longer inherits a parent's t/b animation/timeline/range hook and run a spurious (inert) second scroll animation. Mirrors the existing l/r indirection pattern. Rebuilt dist/tw-fade.css (30,079 B, well under the 55,000 cap). Tests: - Document REJECTED_CLASSES intent: both the old physical names and the fully-logical inline/block aliases are deliberately excluded, so re-adding either is a conscious choice, not a silent regression. Docs: - MIGRATING.md: rewrite as a concise guide for humans and coding agents alike — inclusive lead + explicit agent callout, ordered judgment -> mechanical -> verify steps, full rename tables, the physical->logical RTL caveat, and a token-boundary verification grep. Drop the maintainer-only demo resync note. - README.md: qualify the RTL guarantees with the :dir() floor, rewrite Browser Support as a per-feature table, and point the migration section at the agent-executable guide. Packaging / release: - package.json: add rtl/direction-aware/logical-properties/bidi keywords; ship CHANGELOG.md. - CHANGELOG.md: new Keep a Changelog 0.7.0 breaking-rename entry. - .github/workflows/ci.yml: run npm test + the Chromium/WebKit verify chain on PRs and pushes to main, closing the PR-time enforcement gap. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
Engine fix: - src/tw-fade.css: add neutral block-axis defaults to the shared base block so a nested vertical fade no longer inherits a parent's t/b animation/timeline/range hook and run a spurious (inert) second scroll animation. Mirrors the existing l/r indirection pattern. Rebuilt dist/tw-fade.css (30,079 B, well under the 55,000 cap). Tests: - Document REJECTED_CLASSES intent: both the old physical names and the fully-logical inline/block aliases are deliberately excluded, so re-adding either is a conscious choice, not a silent regression. Docs: - MIGRATING.md: rewrite as a concise guide for humans and coding agents alike — inclusive lead + explicit agent callout, ordered judgment -> mechanical -> verify steps, full rename tables, the physical->logical RTL caveat, and a token-boundary verification grep. Drop the maintainer-only demo resync note. - README.md: qualify the RTL guarantees with the :dir() floor, rewrite Browser Support as a per-feature table, and point the migration section at the agent-executable guide. Packaging / release: - package.json: add rtl/direction-aware/logical-properties/bidi keywords; ship CHANGELOG.md. - CHANGELOG.md: new Keep a Changelog 0.7.0 breaking-rename entry. - .github/workflows/ci.yml: run npm test + the Chromium/WebKit verify chain on PRs and pushes to main, closing the PR-time enforcement gap. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
petekp
force-pushed
the
pkp/plain-direction-v1-fade
branch
from
June 27, 2026 03:07
ac31867 to
e64b5e9
Compare
Demo: new "Direction" segmented control (LTR/RTL) on the advanced type-specimen, ordered Edges → Direction → Fade size → Ramp. Flipping direction swaps fade-start/fade-end to the opposite physical edge via :dir(rtl); a safeguard auto-enables a horizontal edge when none is set. Includes the a11y Label-in-Name fix and RTL padding-inline-end symmetry fix. API rename: fade-reveal-* → fade-ramp-* (theme scale --fade-ramp-*, internal --tw-fade-ramp / --tw-fade-ramp-active, keyframes tw-fade-ramp-*, data-fade-ramp-*). "ramp" describes the scroll-travel distance over which a fade eases in/out, rather than implying nearness to the edge. The English verb "reveal" is deliberately preserved in prose/comments. Docs (README/MIGRATING/CHANGELOG), tests, verifiers, and generated dist/demo CSS updated accordingly. npm test 16/16; npm run verify exit 0 (all 9 verifiers green). Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
The demo runtime smoke drove the scroll-linked wave field with
`body.scrollTo({behavior:'instant'})` + a fixed 240ms wait, then asserted
the SVG wave morphed. This passed on macOS WebKit but failed only in CI's
headless Linux WebKit: that engine doesn't reliably emit a native `scroll`
event for a *programmatic* position change on the overflow body, so the
field's scroll listener never fired and the wave stayed frozen at its top
geometry (1629 -> 1629).
Set scrollTop directly, dispatch the `scroll` event the field listens for,
and poll (rAF-driven) for the morph instead of betting on a single fixed
delay. rAF itself works in CI WebKit (the mouse-spring check relies on it),
so the poll converges; the manual dispatch covers the missing native event.
This is a CI-environment artifact, not a real-user bug — genuine touch
scrolls do fire the event.
Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
Drop the .dir-toggle-group background fill from 62% to 35% of --demo-page-bg so the dark tint behind the Direction toggle reads softer. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
The beveled inner-border highlight on the demo containers (install-snippet, tuning-card, feature-column, support-tooltip, etc.) drew a circular arc while the hosts use corner-shape: superellipse(1.35). corner-shape is not inherited and border-radius: inherit copies only the radius, so the highlight diverged from the host edge at every corner regardless of whether it was drawn with a mask, box-shadow, or border. - Add corner-shape: inherit to the highlight pseudo-elements so the hairline follows the host squircle exactly. Unsupported browsers drop it and both host and highlight stay round. - Rework the single per-side border (which met its top/side/bottom colors at a hard miter seam at each corner) into two uniform-color borders: ::before is a light top layer, ::after a dark bottom layer, each faded with a linear-gradient mask so the catch and shadow taper off smoothly as they wrap the corner. - Add --demo-inner-border-taper to control the falloff distance. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
- CHANGELOG.md: fix the Changed-section wording and note that fade-x is now direction-aware. - test/plugin.test.mjs: add a test asserting the shipped CSS carries none of the retired reveal/range token names. - demo/index.html: update the tw-shimmer credit from 475k+ to 500k+ weekly npm downloads. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
- Edge transparency now rides --tw-fade-alpha-* (= min(1, t * onset), onset default 8), decoupled from band width. A leading edge's overflow clip is covered within travel ÷ onset of scroll, so content is never hard-clipped while the soft band is still easing open. - Default travel lowered to sm (was md): clip coverage no longer depends on it, so it is purely cosmetic band-open speed. - Rename the scroll-distance utility fade-ramp-* → fade-travel-* (theme --fade-travel-*, internal --tw-fade-travel[-active], keyframes tw-fade-travel-*). "ramp" read as a gradient/color ramp; "travel" names the scroll axis that distinguishes it from fade-size/fade-clear. MIGRATING maps fade-range-* → fade-travel-* directly (no ramp hop); the retired-token guard now bans the ramp token forms. - Demo: rename the Travel slider + marketing copy; fix the chat-demo answer for "make the fade wider?" → fade-size (was travel, now inaccurate post-decouple). Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
scripts/build-debug.mjs assembles a self-contained, gitignored debug/index.html from scripts/debug/ sources, inlining the compiled plugin CSS (same output dist/ ships) so the bench always reflects the real engine. Synchronized-scroll pressure test: every sample scroller is pinned to the same offset, so any regression is a side-by-side visual diff. Covers 7 directions + ~16 real-world/edge cases + travel/onset/size/clear sweeps, driving the engine via public custom props (no class explosion). onset=1 reproduces the old coupled hard-clip (the A/B); the static-fallback toggle mirrors the @supports-not path. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
- README: the prebuilt-CSS exclusion note listed "integer fade-size-* classes" — there is no integer fade-size form; fade-clear-* is the one with an integer scale. Corrected to fade-clear-*. - README: --tw-fade-onset is documented as a public edge-speed knob under Travel Distance, but the public-surface note declared the entire --tw-fade-* namespace internal — a contradiction. Carve onset out as the documented exception. - MIGRATING: note that the default travel changed md → sm (cosmetic, no action needed). It was documented only in the changelog. Found by the 6-dimension pre-publish review; all minor/nit, no behavior change. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
Set the CHANGELOG 0.7.0 date to the actual publish date (the entry shipped with a 2026-06-26 placeholder). dist/demo/version were already current at the prior commit, so this carries only the date correction. Claude-Session: https://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj
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.
Reconciled with the deployed demo (rebased onto
pkp/tw-shimmer-credit)This branch was rebased from
mainontopkp/tw-shimmer-credit, so the new API now sits on top of the latest demo/site work that's already deployed to pete.design. Becausetw-shimmer-credithas no PR of its own, this PR now also carries its 7 demo commits (tw-shimmer credit, smoothed wave background, container depth/motion refinements, rewritten chat copy, regenerated demo CSS). Merging therefore bringsmaincurrent with the deployed site and applies the plain-direction API in one shot. The API change itself is the two commits at the tip (Implement plain direction fade API,Address PR #4 review findings).During the rebase, demo conflicts were resolved by taking the upstream design and re-applying the new API names (e.g.
fade-size-2xl+fade/fade-always/fade-x/fade-reveal-sm), and the demo chat copy was updated from old vocabulary (fade-t, "range") to the new names (fade-top, "reveal").Post-rebase validation
npm test— 16/16 (incl. thedist === fresh compilefreshness gate and the plain-API inventory check that enforcesREJECTED_CLASSES)npm run verify— 9/9 verifiers green in real Chromium + WebKit, including RTL horizontal routing (15/15:fade-start→physical-right /fade-end→physical-left underdir=rtl, nesteddiroverrides,scroll(self inline)) and fade pixel masking (17/17)dist/tw-fade.cssis fresh at 30,077 bytes (under the 55 KB cap)MIGRATING.mdis the agent-oriented 0.7.0 upgrade guidehttps://claude.ai/code/session_01B1Gn7DoGHbzGCLMbA72Stj