integration: keep reveal transitions on the revealed state
Move the transition onto the base reveal-target selector so removing reveal-pending no longer drops the animation, while reduced-motion still suppresses it. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
@mixin reveal-target {
|
@mixin reveal-target {
|
||||||
&.reveal-pending {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(0.5rem);
|
|
||||||
transition:
|
transition:
|
||||||
opacity var(--duration-base) var(--ease-standard),
|
opacity var(--duration-base) var(--ease-standard),
|
||||||
transform var(--duration-base) var(--ease-standard);
|
transform var(--duration-base) var(--ease-standard);
|
||||||
|
|
||||||
|
&.reveal-pending {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0.5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-revealed {
|
&.is-revealed {
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
&,
|
||||||
&.reveal-pending,
|
&.reveal-pending,
|
||||||
&.is-revealed {
|
&.is-revealed {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|||||||
36
src/app/shared/motion/reveal.styles.spec.ts
Normal file
36
src/app/shared/motion/reveal.styles.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { readFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
const REVEAL_SCSS = readFileSync(join(process.cwd(), 'src/app/shared/motion/_reveal.scss'), 'utf8');
|
||||||
|
|
||||||
|
function mixinBody(source: string): string {
|
||||||
|
const start = source.indexOf('@mixin reveal-target');
|
||||||
|
expect(start).toBeGreaterThan(-1);
|
||||||
|
return source.slice(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('reveal-target mixin', () => {
|
||||||
|
it('keeps transition on the base selector so the revealed state can animate', () => {
|
||||||
|
const mixin = mixinBody(REVEAL_SCSS);
|
||||||
|
const transitionIndex = mixin.search(/transition\s*:/);
|
||||||
|
const pendingIndex = mixin.indexOf('&.reveal-pending');
|
||||||
|
const revealedIndex = mixin.indexOf('&.is-revealed');
|
||||||
|
|
||||||
|
expect(transitionIndex).toBeGreaterThan(-1);
|
||||||
|
expect(pendingIndex).toBeGreaterThan(-1);
|
||||||
|
expect(revealedIndex).toBeGreaterThan(pendingIndex);
|
||||||
|
expect(transitionIndex).toBeLessThan(pendingIndex);
|
||||||
|
|
||||||
|
const pendingBlock = mixin.match(/&\.reveal-pending\s*\{([^}]*)\}/)?.[1] ?? '';
|
||||||
|
expect(pendingBlock).toMatch(/opacity\s*:/);
|
||||||
|
expect(pendingBlock).not.toMatch(/transition\s*:/);
|
||||||
|
|
||||||
|
const revealedBlock = mixin.match(/&\.is-revealed\s*\{([^}]*)\}/)?.[1] ?? '';
|
||||||
|
expect(revealedBlock).toMatch(/opacity\s*:\s*1/);
|
||||||
|
expect(revealedBlock).not.toMatch(/transition\s*:/);
|
||||||
|
|
||||||
|
expect(mixin).toMatch(/prefers-reduced-motion:\s*reduce/);
|
||||||
|
expect(mixin).toMatch(/&\s*,\s*&\.reveal-pending/);
|
||||||
|
expect(mixin).toMatch(/&\.is-revealed\s*\{[\s\S]*transition:\s*none/);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user