Mijn aanvragen: list enter/leave animations + 204 null-body fix
- animate.enter/leave on aanvraag cards and upload rows (native Angular, no @angular/animations) - reduced-motion: skip animation → instant removal - api-client: null-body statuses (204/205/304) must pass null to Response() Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,7 @@ import { tasksFromProfile } from '@registratie/domain/tasks';
|
||||
<app-heading [level]="2" i18n="@@dashboard.mijnAanvragen">Mijn aanvragen</app-heading>
|
||||
<div class="app-stack app-section">
|
||||
@for (a of aanvragen(); track a.id) {
|
||||
<app-aanvraag-block [aanvraag]="a" (resume)="resume(a)" (cancel)="cancelAanvraag(a)" />
|
||||
<app-aanvraag-block animate.enter="app-item-enter" animate.leave="app-item-leave" [aanvraag]="a" (resume)="resume(a)" (cancel)="cancelAanvraag(a)" />
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -40,7 +40,9 @@ function httpClientFetch(http: HttpClient) {
|
||||
})
|
||||
.pipe(timeout(REQUEST_TIMEOUT_MS)),
|
||||
);
|
||||
return new Response(res.body ?? '', { status: res.status || 200 });
|
||||
// 204/205/304 are null-body statuses — new Response(body, …) throws for any non-null body.
|
||||
const nullBody = res.status === 204 || res.status === 205 || res.status === 304;
|
||||
return new Response(nullBody ? null : (res.body ?? ''), { status: res.status || 200 });
|
||||
} catch (e) {
|
||||
if (e instanceof TimeoutError) return new Response('', { status: 504 });
|
||||
const err = e as HttpErrorResponse;
|
||||
|
||||
@@ -50,6 +50,8 @@ import { SingleUploadComponent } from '../single-upload/single-upload.component'
|
||||
<div class="uploads">
|
||||
@for (u of uploads(); track u.localId) {
|
||||
<app-single-upload
|
||||
animate.enter="app-item-enter"
|
||||
animate.leave="app-item-leave"
|
||||
[upload]="u"
|
||||
[previewUrlFor]="previewUrlFor()"
|
||||
(remove)="onRemove(u)"
|
||||
|
||||
@@ -86,8 +86,26 @@ app-site-footer { view-transition-name: site-footer; }
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
/* List-item enter/leave for lists that add/remove at runtime (aanvraag cards, upload
|
||||
rows). Used via Angular's native `animate.enter`/`animate.leave` — no @angular/animations. */
|
||||
@keyframes app-item-enter { from { opacity: 0; transform: translateY(-0.5rem); } to { opacity: 1; transform: none; } }
|
||||
@keyframes app-item-leave {
|
||||
from { opacity: 1; max-block-size: 50rem; }
|
||||
to { opacity: 0; transform: translateY(-0.25rem); max-block-size: 0; margin-block: 0; padding-block: 0; }
|
||||
}
|
||||
.app-item-enter { animation: app-item-enter 220ms ease both; }
|
||||
.app-item-leave {
|
||||
display: block; /* collapse needs block formatting (host is inline/flex by default) */
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
/* ponytail: 50rem max-height hack; if an item is taller the collapse eases slightly late — measure height in JS then. */
|
||||
animation: app-item-leave 260ms ease both;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
::view-transition-group(*),
|
||||
::view-transition-old(*),
|
||||
::view-transition-new(*) { animation: none !important; }
|
||||
/* No animation → Angular removes the leaving node immediately (instant, no motion). */
|
||||
.app-item-enter, .app-item-leave { animation: none; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user