Compare commits

...

2 Commits

Author SHA1 Message Date
root
dec11f0c01 fix: hero carousel — horizontal book spine stack instead of vertical overlap
All checks were successful
Release / Test backend (push) Successful in 49s
Release / Check ui (push) Successful in 1m55s
Release / Docker (push) Successful in 7m23s
Release / Gitea Release (push) Successful in 53s
2026-04-13 21:08:51 +05:00
root
0f1ded2269 feat: stacked card effect on home hero carousel (desktop sm+)
All checks were successful
Release / Test backend (push) Successful in 47s
Release / Check ui (push) Successful in 1m54s
Release / Docker (push) Successful in 7m15s
Release / Gitea Release (push) Successful in 27s
2026-04-13 19:56:51 +05:00

View File

@@ -136,12 +136,18 @@
<!-- ── Hero carousel ──────────────────────────────────────────────────────────── -->
{#if heroBook}
{@const stackBooks = heroBooks.length > 1
? Array.from({ length: Math.min(heroBooks.length - 1, 3) }, (_, i) =>
heroBooks[(heroIndex + 1 + i) % heroBooks.length])
: []}
<section class="mb-6">
<div class="relative">
<!-- Card — swipe to navigate -->
<!-- Outer flex row: front card + queued book spines (sm+ only) -->
<div class="relative flex items-stretch gap-0">
<!-- Front card — swipe to navigate -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="group relative flex gap-0 rounded-xl overflow-hidden bg-(--color-surface-2) border border-(--color-border) hover:border-(--color-brand)/50 transition-all"
class="group relative flex gap-0 rounded-xl overflow-hidden bg-(--color-surface-2) border border-(--color-border) hover:border-(--color-brand)/50 transition-all z-[2] flex-1 min-w-0"
ontouchstart={onSwipeStart}
ontouchend={onSwipeEnd}
>
@@ -198,23 +204,43 @@
</div>
</div>
<!-- Dot indicators -->
{#if heroBooks.length > 1}
<div class="flex items-center justify-center gap-2 mt-2.5">
{#each heroBooks as _, i}
<button
type="button"
onclick={() => heroDot(i)}
aria-label="Go to book {i + 1}"
>
<span class="block rounded-full transition-all duration-300 {i === heroIndex
? 'w-4 h-1.5 bg-(--color-brand)'
: 'w-1.5 h-1.5 bg-(--color-border) hover:bg-(--color-muted)'}"></span>
</button>
{/each}
</div>
{/if}
<!-- Queued book spines — visible sm+ only, peek to the right of the front card -->
{#each stackBooks as stackBook, i}
{@const opacity = i === 0 ? 'opacity-70' : 'opacity-40'}
{@const width = i === 0 ? 'sm:w-10' : 'sm:w-7'}
<a
href="/books/{stackBook.book.slug}/chapters/{stackBook.chapter}"
class="hidden sm:block shrink-0 {width} rounded-r-xl overflow-hidden border border-l-0 border-(--color-border) {opacity} hover:opacity-90 transition-opacity"
aria-label={stackBook.book.title}
tabindex="-1"
>
{#if stackBook.book.cover}
<img src={stackBook.book.cover} alt="" aria-hidden="true"
class="w-full h-full object-cover object-left" loading="lazy" />
{:else}
<div class="w-full h-full bg-(--color-surface-3)"></div>
{/if}
</a>
{/each}
</div>
<!-- Dot indicators -->
{#if heroBooks.length > 1}
<div class="flex items-center justify-center gap-2 mt-2.5">
{#each heroBooks as _, i}
<button
type="button"
onclick={() => heroDot(i)}
aria-label="Go to book {i + 1}"
>
<span class="block rounded-full transition-all duration-300 {i === heroIndex
? 'w-4 h-1.5 bg-(--color-brand)'
: 'w-1.5 h-1.5 bg-(--color-border) hover:bg-(--color-muted)'}"></span>
</button>
{/each}
</div>
{/if}
</section>
{/if}