68 lines
1.6 KiB
Svelte
68 lines
1.6 KiB
Svelte
<script lang="ts">
|
|
import Icon from '@iconify/svelte';
|
|
import type { Book } from '#lib/content';
|
|
import BookCard from './BookCard.svelte';
|
|
|
|
let { title, icon, books }: { title: string; icon: string; books: Book[] } = $props();
|
|
|
|
const collapsedCount = 12;
|
|
|
|
let showAll = $state(false);
|
|
|
|
const shownBooks = $derived(showAll ? books : books.slice(0, collapsedCount));
|
|
</script>
|
|
|
|
<h3 class="subheading"><Icon {icon} width="16" /> {title} <span class="muted">{books.length}</span></h3>
|
|
<div class="book-grid">
|
|
{#each shownBooks as book (book.goodreadsId)}
|
|
<BookCard {book} />
|
|
{/each}
|
|
</div>
|
|
|
|
{#if books.length > collapsedCount}
|
|
<button class="toggle" onclick={() => (showAll = !showAll)}>
|
|
<Icon icon={showAll ? 'mdi:chevron-up' : 'mdi:chevron-down'} width="16" />
|
|
{showAll ? 'Show less' : `Show all ${books.length}`}
|
|
</button>
|
|
{/if}
|
|
|
|
<style>
|
|
.subheading {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.4rem;
|
|
margin: 1.25rem 0 0.6rem;
|
|
color: var(--foreground);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.book-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
|
gap: 0.9rem 0.75rem;
|
|
}
|
|
|
|
.toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.3rem;
|
|
margin-top: 0.75rem;
|
|
padding: 0.3rem 0.7rem;
|
|
background: none;
|
|
border: 1px solid color-mix(in srgb, var(--foreground) 30%, transparent);
|
|
color: var(--foreground);
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.toggle:hover {
|
|
border-color: var(--accent);
|
|
color: var(--accent);
|
|
}
|
|
|
|
@container (max-width: 520px) {
|
|
.book-grid {
|
|
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
|
|
}
|
|
}
|
|
</style>
|