mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
TCGs
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
---
|
||||
/**
|
||||
* DeckCard.astro
|
||||
* ---------------------------------------------------------------------------
|
||||
* Card for a single Magic: The Gathering deck pulled live from Archidekt. Shows
|
||||
* the deck's featured card art (or a placeholder slab), the deck name as a link
|
||||
* to its Archidekt page, a row of mana-color pips sized by color presence, and
|
||||
* a meta line (card count, format, last-updated).
|
||||
*
|
||||
* Data shape matches ArchidektDeck in src/lib/archidekt.ts.
|
||||
*/
|
||||
import Icon from '@components/Icon.astro';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
href: string;
|
||||
featured?: string;
|
||||
colors?: { W: number; U: number; B: number; R: number; G: number };
|
||||
size?: number;
|
||||
formatLabel?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
const { name, href, featured, colors, size, formatLabel, updatedAt } = Astro.props;
|
||||
|
||||
// MTG mana colors. Used for the presence pips; a color shows only if count > 0.
|
||||
const MANA: Array<[key: 'W' | 'U' | 'B' | 'R' | 'G', hex: string]> = [
|
||||
['W', '#f8f4e8'],
|
||||
['U', '#3b7bd4'],
|
||||
['B', '#2b2b2b'],
|
||||
['R', '#d44b3b'],
|
||||
['G', '#3f9d52'],
|
||||
];
|
||||
const present = colors ? MANA.filter(([k]) => (colors[k] ?? 0) > 0) : [];
|
||||
|
||||
// Friendly relative-ish date (e.g. "Jul 2026"). Falls back gracefully.
|
||||
const updated = updatedAt ? new Date(updatedAt).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
year: 'numeric',
|
||||
}) : '';
|
||||
---
|
||||
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="card card-interactive group flex h-full flex-col gap-0 overflow-hidden p-0"
|
||||
>
|
||||
<div class="relative aspect-[4/3] w-full overflow-hidden">
|
||||
{
|
||||
featured ? (
|
||||
<img
|
||||
src={featured}
|
||||
alt={`${name} featured card`}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
class="h-full w-full object-cover transition-transform duration-700 group-hover:scale-105"
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
class="flex h-full w-full items-center justify-center"
|
||||
style="background: color-mix(in srgb, var(--color-secondary) 16%, transparent);"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<Icon
|
||||
name="cards-playing"
|
||||
class="h-12 w-12 opacity-50"
|
||||
style="color: var(--color-text-muted);"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{/* Legibility gradient at the bottom for the meta row. */}
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="absolute inset-x-0 bottom-0 h-1/3"
|
||||
style="background: linear-gradient(to top, rgba(0,0,0,0.55), transparent);"
|
||||
></div>
|
||||
|
||||
{
|
||||
/* Mana color pips, top-left over the art. */
|
||||
present.length > 0 && (
|
||||
<div class="absolute left-3 top-3 flex gap-1.5">
|
||||
{present.map(([key, hex]) => (
|
||||
<span
|
||||
class="h-3 w-3 rounded-full border border-black/30"
|
||||
style={`background:${hex};`}
|
||||
title={`${key} mana`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2 p-4">
|
||||
<h3
|
||||
class="font-sans text-base leading-tight underline-offset-4 group-hover:underline"
|
||||
style="color: var(--color-text);"
|
||||
>
|
||||
{name}
|
||||
</h3>
|
||||
<div
|
||||
class="flex flex-wrap items-center gap-2 font-mono text-[0.65rem] uppercase tracking-[0.16em]"
|
||||
style="color: var(--color-text-muted);"
|
||||
>
|
||||
{formatLabel && <span>{formatLabel}</span>}
|
||||
{formatLabel && (size || updated) && <span aria-hidden="true">·</span>}
|
||||
{size ? <span>{size} cards</span> : null}
|
||||
{updated && (size ? <span aria-hidden="true">·</span> : null)}
|
||||
{updated && <span>{updated}</span>}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
Reference in New Issue
Block a user