- Feed header: large title, tappable game pill, circular progress ring, icon-in-field search, filter chips with live counts (All/Caught/Missing/Favorites) - Cards: left-aligned info, number chip, corner ghost number (no longer hidden behind the sprite), top-down type gradient, staggered entrance animation; caught toggle moved to top-left - Detail: hide the shiny toggle for Gen 1 games (shinies are Gen 2+); add Category (genus) to the About tab Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
59 lines
1.9 KiB
JavaScript
59 lines
1.9 KiB
JavaScript
import { el } from '../lib/dom.js';
|
|
import { Sprite } from './Sprite.js';
|
|
import { TypeChip } from './TypeChip.js';
|
|
import { entry, toggle } from '../store/selection.js';
|
|
import { typeHex } from '../lib/type-color.js';
|
|
|
|
/**
|
|
* One Pokémon in the dex feed. Tinted by its primary type: a soft top-down
|
|
* gradient, a type-coloured spotlight behind an oversized sprite that lifts
|
|
* above the card, a number chip, and a big ghost number in the corner.
|
|
*/
|
|
export function Card(species, number, { spriteStyle = 'official', versionGroup } = {}) {
|
|
const state = entry(species.id);
|
|
const mainType = (species.types || [])[0] || 'normal';
|
|
const num = String(number ?? species.id).padStart(3, '0');
|
|
|
|
const caughtBtn = el('button', {
|
|
class: 'card__caught',
|
|
type: 'button',
|
|
title: 'Toggle caught',
|
|
'aria-pressed': String(state.caught),
|
|
onclick: (event) => {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
toggle(species.id, 'caught');
|
|
const next = entry(species.id);
|
|
caughtBtn.setAttribute('aria-pressed', String(next.caught));
|
|
card.classList.toggle('is-caught', next.caught);
|
|
},
|
|
});
|
|
|
|
const card = el(
|
|
'a',
|
|
{
|
|
class: `card${state.caught ? ' is-caught' : ''}`,
|
|
href: `#/pokemon/${species.id}`,
|
|
dataset: { type: mainType, sprite: spriteStyle },
|
|
style: `--type-main:${typeHex(mainType)}`,
|
|
},
|
|
el('span', { class: 'card__ghost', 'aria-hidden': 'true' }, num),
|
|
el('span', { class: 'card__spot', 'aria-hidden': 'true' }),
|
|
el(
|
|
'div',
|
|
{ class: 'card__art' },
|
|
Sprite(species.id, { style: spriteStyle, versionGroup, alt: species.name, size: 116 }),
|
|
),
|
|
caughtBtn,
|
|
el(
|
|
'div',
|
|
{ class: 'card__body' },
|
|
el('span', { class: 'card__num' }, `#${num}`),
|
|
el('span', { class: 'card__name' }, species.name.replace(/-/g, ' ')),
|
|
el('span', { class: 'card__types' }, ...(species.types || []).map(TypeChip)),
|
|
),
|
|
);
|
|
|
|
return card;
|
|
}
|