From 9cc72492782462556023e58c3d3c5b6629929e3c Mon Sep 17 00:00:00 2001 From: Julian Lechner Date: Thu, 14 May 2026 14:57:54 +0200 Subject: [PATCH] fix: fragmentation --- src/app/home/home.component.spec.ts | 18 +++++++++++++++--- src/app/home/home.component.ts | 5 ++++- src/styles.scss | 17 +++++++++++++---- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts index aa20c0f..4dccc5b 100644 --- a/src/app/home/home.component.spec.ts +++ b/src/app/home/home.component.spec.ts @@ -429,18 +429,30 @@ describe('HomeComponent', (): void => { // ── RAF debouncing (performance) ─────────────────────────────────────────── describe('Performance', (): void => { - it('should keep scroll effects enabled on small viewports when motion is allowed', (): void => { - spyOnProperty(window, 'innerWidth').and.returnValue(390); + it('should keep scroll effects enabled on desktop pointers when motion is allowed', (): void => { spyOn(window, 'matchMedia').and.callFake( (query: string): MediaQueryList => ({ - matches: query !== '(prefers-reduced-motion: reduce)', + matches: + query !== '(prefers-reduced-motion: reduce)' && + query !== '(hover: none) and (pointer: coarse)', }) as MediaQueryList, ); expect(comp.shouldEnableScrollEffects()).toBeTrue(); }); + it('should disable scroll effects on coarse touch pointers', (): void => { + spyOn(window, 'matchMedia').and.callFake( + (query: string): MediaQueryList => + ({ + matches: query === '(hover: none) and (pointer: coarse)', + }) as MediaQueryList, + ); + + expect(comp.shouldEnableScrollEffects()).toBeFalse(); + }); + it('should disable scroll effects when reduced motion is requested', (): void => { spyOn(window, 'matchMedia').and.callFake( (query: string): MediaQueryList => diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index e610cdb..66215b3 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -227,8 +227,11 @@ export class HomeComponent implements OnInit, AfterViewInit, OnDestroy { const prefersReducedMotion: boolean = window.matchMedia( '(prefers-reduced-motion: reduce)', ).matches; + const usesTouchScrolling: boolean = window.matchMedia( + '(hover: none) and (pointer: coarse)', + ).matches; - return !prefersReducedMotion; + return !prefersReducedMotion && !usesTouchScrolling; } private initNameGradientScrollAnimation(): void { diff --git a/src/styles.scss b/src/styles.scss index 0eb57d4..051e6a8 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1223,22 +1223,31 @@ hr { .projects-section, .story-section, .legal-section { - content-visibility: auto; - contain-intrinsic-size: 1px 720px; + content-visibility: visible; } } -@media (max-width: 700px) and (hover: none) and (pointer: coarse) { +@media (hover: none) and (pointer: coarse) { body { background: radial-gradient(circle at top left, rgba(217, 162, 140, 0.18), transparent 28%), radial-gradient(circle at bottom right, rgba(127, 78, 63, 0.24), transparent 32%), linear-gradient(180deg, rgba(9, 9, 12, 0.72), rgba(8, 8, 11, 0.96)), - url('assets/optimized/background.webp') center / cover fixed no-repeat; + url('assets/optimized/background.webp') center top / cover no-repeat; } } @media (hover: none) and (pointer: coarse) { + .about-scroll-anim-enabled .story-copy, + .about-scroll-anim-enabled .story-detail, + .project-entry, + .project-entry.project-entry-from-right, + .project-entry.project-entry-from-left { + opacity: 1; + transform: none; + will-change: auto; + } + .action-link:hover, .detail-toggle:hover, .back-link:hover,