From 439c66b750e215e9fde2233744973af8e402f874 Mon Sep 17 00:00:00 2001 From: siversm Date: Wed, 4 Nov 2026 15:45:13 +0100 Subject: [PATCH] =?UTF-8?q?"feat:=20Add=20keyboard=20navigation=20for=20Po?= =?UTF-8?q?k=C3=A9mon=20cards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reasoning: Convert Pokémon cards to native buttons so they can be reached with Tab and activated with Enter, improving keyboard accessibility. Co-authored-by: n/a" --- project2/src/App.tsx | 23 +++++++++++++++++++---- project2/src/components/PokemonCard.tsx | 4 ++-- project2/src/index.css | 17 +++++++++++++++-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/project2/src/App.tsx b/project2/src/App.tsx index e520cf6..ce65daf 100644 --- a/project2/src/App.tsx +++ b/project2/src/App.tsx @@ -150,6 +150,24 @@ function App() { ); } }, []); + + const closePokemonDetail = () => { + document.body.style.overflow = ''; + setSelectedId(null); + }; + useEffect(() => { + if(selectedId === null) return; + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + closePokemonDetail(); + } + }; + document.addEventListener('keydown', handleKeyDown); + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [selectedId]); const handleRate = async (pokemonId: number, rating: number) => { if (!ratingsReady || !voterId) return; @@ -334,10 +352,7 @@ function App() { ratingDisabled={!ratingsReady || savingRating} ratingError={ratingError} onRate={(rating) => void handleRate(selectedPokemon.id, rating)} - onBack={() => { - document.body.style.overflow = ''; - setSelectedId(null); - }} + onBack={closePokemonDetail} /> )} diff --git a/project2/src/components/PokemonCard.tsx b/project2/src/components/PokemonCard.tsx index d52dcc6..c30c609 100644 --- a/project2/src/components/PokemonCard.tsx +++ b/project2/src/components/PokemonCard.tsx @@ -24,7 +24,7 @@ function getTitleFontSize(name: string): string { export function PokemonCard({ pokemon, onSelect }: PokemonCardProps) { return ( -
onSelect(pokemon)}> +
+ ); } diff --git a/project2/src/index.css b/project2/src/index.css index 4f4cc2e..e4004f5 100644 --- a/project2/src/index.css +++ b/project2/src/index.css @@ -180,8 +180,21 @@ main { border-radius: 1.5rem; color: var(--card-text); cursor: pointer; + font: inherit; + width: 100%; + +} + +.pokemon-card:focus-visible { + outline: 2px solid currentColor; + outline-offset: 3px; } -.pokemon-card button { + +/* + * Legacy nested-button styles. + * Can be removed once the button-based card migration is complete. + */ +/* .pokemon-card button { padding: 0; width: 100%; background: none; @@ -189,7 +202,7 @@ main { font: inherit; color: inherit; cursor: pointer; -} +} */ .pokemon-image, .pokemon-detailed-image {