Stack series covers and wrap series into rows
This commit is contained in:
1 parent
bad7b7d3b3
commit
30656cb580
2 files changed
+89
-13
No files matched your search
@@ -5,11 +5,8 @@
|
||||
|
||||
let { series }: { series: BookSeriesGroup } = $props();
|
||||
|
||||
const collapsedCount = 8;
|
||||
let expanded = $state(false);
|
||||
|
||||
let showAll = $state(false);
|
||||
|
||||
const shownBooks = $derived(showAll ? series.books : series.books.slice(0, collapsedCount));
|
||||
const total = $derived(series.books.length);
|
||||
const shelves = $derived([
|
||||
{ id: 'read', label: 'read', count: series.counts.read },
|
||||
@@ -18,7 +15,7 @@
|
||||
]);
|
||||
</script>
|
||||
|
||||
<section class="series">
|
||||
<section class="series" class:expanded>
|
||||
<header class="series-header">
|
||||
<a class="series-name" href={series.url} target="_blank" rel="noopener noreferrer">
|
||||
<Icon icon="mdi:bookshelf" width="16" />
|
||||
@@ -39,26 +36,52 @@
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if expanded}
|
||||
<div class="book-grid">
|
||||
{#each shownBooks as book (book.goodreadsId)}
|
||||
{#each series.books as book (book.goodreadsId)}
|
||||
<BookCard {book} showShelf />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if total > collapsedCount}
|
||||
<button class="toggle" onclick={() => (showAll = !showAll)}>
|
||||
<Icon icon={showAll ? 'mdi:chevron-up' : 'mdi:chevron-down'} width="16" />
|
||||
{showAll ? 'Show less' : `Show all ${total}`}
|
||||
</button>
|
||||
{:else}
|
||||
<div class="cover-stack">
|
||||
{#each series.books as book, index (book.goodreadsId)}
|
||||
<a
|
||||
class="stacked-cover {book.shelf}"
|
||||
style:z-index={total - index}
|
||||
href={book.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="{book.series?.position ?? ''} {book.title}"
|
||||
>
|
||||
{#if book.cover}
|
||||
<img src={book.cover} alt={book.title} loading="lazy" />
|
||||
{:else}
|
||||
<span class="cover-fallback"><Icon icon="mdi:book-outline" width="20" /></span>
|
||||
{/if}
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<button class="toggle" onclick={() => (expanded = !expanded)}>
|
||||
<Icon icon={expanded ? 'mdi:chevron-up' : 'mdi:chevron-down'} width="16" />
|
||||
{expanded ? 'Collapse series' : `Expand series (${total})`}
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.series {
|
||||
padding: 0.75rem;
|
||||
flex: 1 1 auto;
|
||||
min-width: min(100%, 280px);
|
||||
max-width: 100%;
|
||||
border: 1px solid color-mix(in srgb, var(--foreground) 15%, transparent);
|
||||
}
|
||||
|
||||
.series.expanded {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.series-header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -121,6 +144,58 @@
|
||||
background: var(--magenta);
|
||||
}
|
||||
|
||||
.cover-stack {
|
||||
display: flex;
|
||||
padding: 0.5rem 0 0.25rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.stacked-cover {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 84px;
|
||||
height: 126px;
|
||||
border-bottom: 3px solid var(--muted);
|
||||
box-shadow: 4px 0 10px color-mix(in srgb, black 45%, transparent);
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.stacked-cover + .stacked-cover {
|
||||
margin-left: -52px;
|
||||
}
|
||||
|
||||
.stacked-cover:hover {
|
||||
z-index: 1000 !important;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
.stacked-cover.read {
|
||||
border-bottom-color: var(--green);
|
||||
}
|
||||
|
||||
.stacked-cover.reading {
|
||||
border-bottom-color: var(--blue);
|
||||
}
|
||||
|
||||
.stacked-cover.want-to-read {
|
||||
border-bottom-color: var(--magenta);
|
||||
}
|
||||
|
||||
.stacked-cover img,
|
||||
.cover-fallback {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.cover-fallback {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: color-mix(in srgb, var(--foreground) 8%, var(--background));
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.book-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
|
||||
.series-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user