fix: reserve detail cover box and async-decode list/shelf covers

- The manga detail desktop overview cover had no reserved aspect-ratio, so
  the meta column reflowed when it decoded. Give .cover aspect-ratio: 2/3 +
  object-fit: cover (mirrors MangaCard).
- Add decoding="async" to the detail hero/overview covers and the list/shelf
  covers (bookmarks, history, continue-reading, collections, tagged rows) so
  decode stays off the main thread — previously only MangaCard had it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-06 21:43:21 +02:00
parent 9cb2f152d3
commit 3622dcc02f
12 changed files with 28 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "mangalord-frontend",
"version": "0.115.1",
"version": "0.115.2",
"private": true,
"type": "module",
"scripts": {

View File

@@ -23,6 +23,7 @@
alt=""
class="cover"
loading="lazy"
decoding="async"
/>
{:else}
<div class="cover cover-placeholder">

View File

@@ -26,6 +26,7 @@
alt=""
class="collage-cover"
loading="lazy"
decoding="async"
/>
{/each}
{/if}

View File

@@ -51,6 +51,7 @@
alt=""
class="cover"
loading="lazy"
decoding="async"
/>
{:else}
<span class="cover cover-placeholder">

View File

@@ -89,6 +89,7 @@
alt=""
class="cover"
loading="lazy"
decoding="async"
/>
{:else}
<div class="cover cover-placeholder">

View File

@@ -29,6 +29,16 @@ describe('HistoryList', () => {
expect(cont.getAttribute('href')).toBe('/manga/m1/chapter/c9');
});
it('renders covers with lazy loading and async decode', () => {
render(HistoryList, {
props: { entries: [entry({ manga_cover_image_path: 'mangas/m1/cover.jpg' })] }
});
const img = document.querySelector('img.cover') as HTMLImageElement;
expect(img).not.toBeNull();
expect(img.getAttribute('loading')).toBe('lazy');
expect(img.getAttribute('decoding')).toBe('async');
});
it('appends the page number to the continue line only past page 1', () => {
// The page suffix is a separate text node from "Continue Chapter N",
// so assert against the link's normalized text rather than getByText.

View File

@@ -27,7 +27,7 @@
<li class="row" data-testid={testid}>
<a {href} class="cover-link" aria-hidden="true" tabindex="-1">
{#if primaryCover}
<img src={fileUrl(primaryCover)} alt="" class="cover" loading="lazy" />
<img src={fileUrl(primaryCover)} alt="" class="cover" loading="lazy" decoding="async" />
{:else}
<div class="cover cover-placeholder"></div>
{/if}
@@ -46,7 +46,7 @@
{#if item.sample_storage_keys.length > 1}
<div class="samples">
{#each item.sample_storage_keys.slice(1) as key (key)}
<img src={fileUrl(key)} alt="" class="sample" loading="lazy" />
<img src={fileUrl(key)} alt="" class="sample" loading="lazy" decoding="async" />
{/each}
</div>
{/if}

View File

@@ -36,7 +36,7 @@
<li class="row" data-testid={testid}>
<a {href} class="cover-link" aria-hidden="true" tabindex="-1">
{#if primaryCover}
<img src={fileUrl(primaryCover)} alt="" class="cover" loading="lazy" />
<img src={fileUrl(primaryCover)} alt="" class="cover" loading="lazy" decoding="async" />
{:else}
<div class="cover cover-placeholder"></div>
{/if}
@@ -50,7 +50,7 @@
{#if sampleStrip.length > 0}
<div class="samples">
{#each sampleStrip as key (key)}
<img src={fileUrl(key)} alt="" class="sample" loading="lazy" />
<img src={fileUrl(key)} alt="" class="sample" loading="lazy" decoding="async" />
{/each}
</div>
{/if}

View File

@@ -35,6 +35,7 @@
alt=""
class="cover"
loading="lazy"
decoding="async"
/>
</a>
<div class="meta">

View File

@@ -380,6 +380,7 @@
src={fileUrl(manga.cover_image_path)}
alt=""
loading="eager"
decoding="async"
/>
{/if}
<div class="hero-text">
@@ -401,6 +402,7 @@
alt="{manga.title} cover"
class="cover"
loading="eager"
decoding="async"
data-testid="manga-cover"
/>
{/if}
@@ -791,7 +793,10 @@
.cover {
width: 100%;
height: auto;
/* Reserve the 2/3 box so the meta column doesn't reflow when the
cover decodes (mirrors MangaCard's cover). */
aspect-ratio: 2 / 3;
object-fit: cover;
border-radius: var(--radius-md);
background: var(--surface);
}