diff --git a/src/components/blocks/ChangeLens.astro b/src/components/blocks/ChangeLens.astro index aeea152..b0d6845 100644 --- a/src/components/blocks/ChangeLens.astro +++ b/src/components/blocks/ChangeLens.astro @@ -137,7 +137,8 @@ const isDiff = mode === 'diff'; .skill-diff { border: 1px solid var(--ink); color: var(--paper); - animation: lens-enter 0.28s ease both; + /* purpose: change lens reveal (state change) */ + animation: lens-enter 200ms cubic-bezier(0.2, 0, 0, 1) both; } .change-lens { diff --git a/src/components/blocks/VoteWidget.astro b/src/components/blocks/VoteWidget.astro index 21b7a19..60b6e11 100644 --- a/src/components/blocks/VoteWidget.astro +++ b/src/components/blocks/VoteWidget.astro @@ -139,4 +139,27 @@ const share = (count: number) => (total ? Math.round((count / total) * 100) : 0) flex-direction: column; } } + + .vote-buttons button b { + display: inline-block; + } + :global(.is-updating) { + /* purpose: vote widget tally update (feedback) */ + animation: tally-pop 200ms cubic-bezier(0.2, 0, 0, 1) both; + } + @keyframes tally-pop { + from { + opacity: 0; + transform: translateY(-4px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + @media (prefers-reduced-motion: reduce) { + :global(.is-updating) { + animation: none; + } + } diff --git a/src/components/islands/GuideSelector.astro b/src/components/islands/GuideSelector.astro index 1c2dc67..bdb2666 100644 --- a/src/components/islands/GuideSelector.astro +++ b/src/components/islands/GuideSelector.astro @@ -99,7 +99,11 @@ const { rootSelector, data } = Astro.props; function replace(target, markup) { const panel = root.querySelector(target); - if (panel) panel.innerHTML = markup; + if (!panel) return; + panel.innerHTML = markup; + panel.classList.remove('is-swapping'); + void panel.offsetWidth; + panel.classList.add('is-swapping'); } // Names deliberately match legacy functions until task 19 updates its checks. @@ -291,4 +295,24 @@ const { rootSelector, data } = Astro.props; outline: 3px solid var(--gold); outline-offset: -3px; } + + :global(.is-swapping > *) { + /* purpose: tab panel change in the guide (state change) */ + animation: guide-swap 200ms cubic-bezier(0.2, 0, 0, 1) both; + } + @keyframes guide-swap { + from { + opacity: 0.15; + transform: translateY(5px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + @media (prefers-reduced-motion: reduce) { + :global(.is-swapping > *) { + animation: none; + } + } diff --git a/src/components/islands/ReadingProgress.astro b/src/components/islands/ReadingProgress.astro index ad6d2f1..9956223 100644 --- a/src/components/islands/ReadingProgress.astro +++ b/src/components/islands/ReadingProgress.astro @@ -42,7 +42,7 @@ const { target = '.reading-progress span' } = Astro.props; function update() { const height = document.documentElement.scrollHeight - window.innerHeight; - span.style.width = (height > 0 ? (window.scrollY / height) * 100 : 0) + '%'; + span.style.transform = `scaleX(${height > 0 ? window.scrollY / height : 0})`; } // `{ passive: true }` is non-negotiable. The legacy app.js binds diff --git a/src/components/islands/SkillPackageExplorer.astro b/src/components/islands/SkillPackageExplorer.astro index dbb29a2..4132bfb 100644 --- a/src/components/islands/SkillPackageExplorer.astro +++ b/src/components/islands/SkillPackageExplorer.astro @@ -235,7 +235,8 @@ const packageFiles: PackageFile[] = [ } .package-preview.is-swapping { - animation: package-preview-in 0.34s ease both; + /* purpose: review-desk detail swap on selection (state change) */ + animation: package-preview-in 200ms cubic-bezier(0.2, 0, 0, 1) both; } @keyframes package-preview-in {