feat!: B8a — own reduced motion and publish activity timing #69
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/motion-policy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
B8a makes motion a component-owned customization contract and separates ongoing activity from transition timing.
What's in
* !importantreduced-motion reset. The library now suppresses motion on its own parts and shared native-input skin; applications own their animations, including caller-provided slot content.--activity-period(1.2s) for Button loading, StatusDot pulse, TypingIndicator, default Icon spin and reconnect activity. Stagger/offsets scale with the period. Existing transition roles remain independent; the Icon knob and SpinDuration retain precedence.--dur-base, loses its hardcoded delay and has a visible static reduced-motion treatment; the framework driver and retry/resume behavior are unchanged.Validation
Browser evidence and limits
Desktop: 1280×1000, light, normal motion, captured with the collaborative preview. Narrow: 390×844, dark, reduced motion, actual native reconnect appearance, captured through the documented Playwright runner. Both images were inspected.
Still images show visible states; executable checks establish motion behavior. Reconnect is opened natively to verify appearance, not a real connection-failure/recovery scenario. Media playback, screen-reader speech and physical devices are outside this studio's claims. The consumer sentinels animate an unpainted custom value to test ownership without visible movement. Disabled/read-only interaction policy remains the separate B8b slice.
The library must merge before Shikigami adopts the actual merged revision, replaces its private spinner override with the shared period and narrows its app-owned reduced-motion rules.
Summary
Summary
Coverage
Kagaku.UI - 97.4%
Kagaku.UI.Fluxor - 97.7%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A whole motion ownership contract~ You didn't just delete the global
* !importantreset — you replaced it with per-part ownership, a published timing vocabulary, a migration guide, and a studio that spies on real compiled CSS with live preference flips. That's the kind of thoroughness that makes my wings flutter~ ♡Verdict: ✅ Looks good to me~
✅ What I liked~
transition:/animation:owner insrc/Kagaku.UI(grep sweep across all 27 files with motion) against a reduced-motion rule — every single owned part is covered, andTypingIndicator/Menu/ContextMenukeep their pre-existingno-preference-wrapped entry treatments. No orphaned motion, no consumer descendants touched. Thesample.cssboundary sentinels animating an unpainted custom property to prove the library doesn't rewrite caller timing are genuinely clever~::deepfixes are real bug fixes, not cosmetics..kg-disclosure__summary > svg:last-childcompiled to.kg-disclosure__summary[b-x] > svg:last-child[b-x]— which could never match theIconcomponent's svg (it carries Icon's scope attribute, not Disclosure's). The compiled bundle now emits.kg-disclosure__summary[b-x] > svg:last-child, and the contracts assert the rotated-chevron geometry (b ≈ -1collapsed,≈ 1expanded) — exactly right. Same story for.kg-nav__toggle ::deep .kg-icon..kg-navigation[data-kg-navigation-mode=…](0,2,0), so the old bare.kg-navigationreduce rule (0,1,0) could never win regardless of order.[data-kg-navigation-mode]restores the cascade. The native-dialog group verifiestranslate: 0px,:modalfocus and Escape→focus-return under reduce~display/:modalauthority (opacity: 1, no entrance delay, static ring, second ringdisplay: none), while entry/exit now ride--dur-base— and the contract checks the closed dialog disappears immediately (display: none). Stagger offsets scaling ascalc(var(--activity-period) / -2)keep the old 1.5s→delay rhythm at the new period..kg-btn__spinner { animation: none; }fromButton.razor.cssfails both reduce groups with the exact assertion (#busy-action .kg-btn__spinner motion policy — false !== true). The Icon fallback swap (var(--kg-icon-spin-duration, var(--activity-period))) is pinned by the updatedCssKnobTestsstring contract, andIcon.razor:45still writes the inline knob with explicitSpinDurationprecedence — the demo's#explicit-icon(2s) covers that path.One honest footnote~ my second probe (TypingIndicator
/8→/4stagger) was blocked by my sandbox's staticweb-assets staleness after in-place rebuilds (fingerprinted@importvs route table mismatch), not by anything in this PR — the assertion is millisecond-exact (0.3s/0.6sat a2.4speriod), so a/4substitution for dot 2 cannot survive it. CI's clean run already executed all 14 Chromium groups green.The timing behavior changes (Button spinner 300ms→1.2s, StatusDot 1.6s→1.2s, reconnect 1.5s→period) are all documented in
docs/motion.md's migration section — a proper breaking-change paper trail.--dur-slowremaining a consumer-facing knob with no in-library consumer is stated openly there too.Merge it and let Shikigami adopt it~ fufu~ ♪
Automated review by Jibril · 2026-10-24
CI: green for head SHA
22a0ea7d(build, test, shell-browser incl. motion leg) · Mutation probes: 2 run, 0 survived (1 killed; 1 inconclusive — sandbox asset-chain staleness, not PR) · Local suite: skipped (CI green)View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.