Files
minstrel/web/src/lib/components/AlphabeticalGrid.svelte
T
2026-05-01 20:21:34 -04:00

71 lines
1.5 KiB
Svelte

<script lang="ts" generics="T">
import type { Snippet } from 'svelte';
let {
items,
getKey,
item
}: {
items: T[];
getKey: (it: T) => string;
item: Snippet<[T]>;
} = $props();
// Compute the divider letter for each item; if it differs from the
// previous item's letter, that index gets a divider above it.
const segments = $derived.by(() => {
const out: { divider: string | null; item: T }[] = [];
let last: string | null = null;
for (const it of items) {
const k = (getKey(it) || '').charAt(0).toUpperCase();
if (k !== last) {
out.push({ divider: k, item: it });
last = k;
} else {
out.push({ divider: null, item: it });
}
}
return out;
});
</script>
<div class="alpha-grid">
{#each segments as seg, i (i)}
{#if seg.divider}
<div class="divider">
<span class="letter">{seg.divider}</span>
<span class="rule"></span>
</div>
{/if}
<div class="cell">
{@render item(seg.item)}
</div>
{/each}
</div>
<style>
.alpha-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 16px;
}
.divider {
grid-column: 1 / -1;
display: flex;
align-items: center;
gap: 12px;
padding-top: 8px;
}
.letter {
font-family: var(--fs-font-display);
font-size: 24px;
font-weight: 500;
color: var(--fs-parchment);
}
.rule {
flex: 1;
height: 1px;
background: var(--fs-pewter);
}
</style>