fix: hero carousel — horizontal book spine stack instead of vertical overlap
This commit is contained in:
@@ -136,40 +136,18 @@
|
|||||||
|
|
||||||
<!-- ── Hero carousel ──────────────────────────────────────────────────────────── -->
|
<!-- ── Hero carousel ──────────────────────────────────────────────────────────── -->
|
||||||
{#if heroBook}
|
{#if heroBook}
|
||||||
{@const stackBook1 = heroBooks[(heroIndex + 1) % heroBooks.length]}
|
{@const stackBooks = heroBooks.length > 1
|
||||||
{@const stackBook2 = heroBooks[(heroIndex + 2) % heroBooks.length]}
|
? Array.from({ length: Math.min(heroBooks.length - 1, 3) }, (_, i) =>
|
||||||
|
heroBooks[(heroIndex + 1 + i) % heroBooks.length])
|
||||||
|
: []}
|
||||||
<section class="mb-6">
|
<section class="mb-6">
|
||||||
<div class="relative">
|
<!-- Outer flex row: front card + queued book spines (sm+ only) -->
|
||||||
<!-- Stack layer 2 (furthest back) — only shown on sm+ when there are 3+ books -->
|
<div class="relative flex items-stretch gap-0">
|
||||||
{#if heroBooks.length >= 3}
|
|
||||||
<div class="hidden sm:block absolute inset-0 rounded-xl overflow-hidden pointer-events-none origin-bottom
|
|
||||||
translate-y-[-6px] translate-x-[10px] scale-[0.94] opacity-40 z-0">
|
|
||||||
{#if stackBook2.book.cover}
|
|
||||||
<img src={stackBook2.book.cover} alt="" aria-hidden="true"
|
|
||||||
class="w-full h-full object-cover" loading="lazy" />
|
|
||||||
{:else}
|
|
||||||
<div class="w-full h-full bg-(--color-surface-2)"></div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- Stack layer 1 (one behind front) — only shown on sm+ when there are 2+ books -->
|
|
||||||
{#if heroBooks.length >= 2}
|
|
||||||
<div class="hidden sm:block absolute inset-0 rounded-xl overflow-hidden pointer-events-none origin-bottom
|
|
||||||
translate-y-[-3px] translate-x-[5px] scale-[0.97] opacity-60 z-[1]">
|
|
||||||
{#if stackBook1.book.cover}
|
|
||||||
<img src={stackBook1.book.cover} alt="" aria-hidden="true"
|
|
||||||
class="w-full h-full object-cover" loading="lazy" />
|
|
||||||
{:else}
|
|
||||||
<div class="w-full h-full bg-(--color-surface-2)"></div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- Front card — swipe to navigate -->
|
<!-- Front card — swipe to navigate -->
|
||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<div
|
<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 z-[2]"
|
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}
|
ontouchstart={onSwipeStart}
|
||||||
ontouchend={onSwipeEnd}
|
ontouchend={onSwipeEnd}
|
||||||
>
|
>
|
||||||
@@ -226,23 +204,43 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Dot indicators -->
|
<!-- Queued book spines — visible sm+ only, peek to the right of the front card -->
|
||||||
{#if heroBooks.length > 1}
|
{#each stackBooks as stackBook, i}
|
||||||
<div class="flex items-center justify-center gap-2 mt-2.5">
|
{@const opacity = i === 0 ? 'opacity-70' : 'opacity-40'}
|
||||||
{#each heroBooks as _, i}
|
{@const width = i === 0 ? 'sm:w-10' : 'sm:w-7'}
|
||||||
<button
|
<a
|
||||||
type="button"
|
href="/books/{stackBook.book.slug}/chapters/{stackBook.chapter}"
|
||||||
onclick={() => heroDot(i)}
|
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="Go to book {i + 1}"
|
aria-label={stackBook.book.title}
|
||||||
>
|
tabindex="-1"
|
||||||
<span class="block rounded-full transition-all duration-300 {i === heroIndex
|
>
|
||||||
? 'w-4 h-1.5 bg-(--color-brand)'
|
{#if stackBook.book.cover}
|
||||||
: 'w-1.5 h-1.5 bg-(--color-border) hover:bg-(--color-muted)'}"></span>
|
<img src={stackBook.book.cover} alt="" aria-hidden="true"
|
||||||
</button>
|
class="w-full h-full object-cover object-left" loading="lazy" />
|
||||||
{/each}
|
{:else}
|
||||||
</div>
|
<div class="w-full h-full bg-(--color-surface-3)"></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
|
||||||
</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}
|
||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user