diff --git a/src/App.css b/src/App.css index 89fe02b..eae8b23 100644 --- a/src/App.css +++ b/src/App.css @@ -44,6 +44,10 @@ body { user-select: none; } +table.Game-rows { + margin: auto; +} + .Game-keyboard { display: flex; flex-direction: column; @@ -170,3 +174,13 @@ a:active { margin-top: 1em; font-variant-numeric: tabular-nums; } + +.Game-sr-feedback, +.sr-only { + position: absolute; + left: -10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; +} diff --git a/src/Game.tsx b/src/Game.tsx index 03f2044..af28dc4 100644 --- a/src/Game.tsx +++ b/src/Game.tsx @@ -1,10 +1,10 @@ import { useEffect, useState } from "react"; import { Row, RowState } from "./Row"; import dictionary from "./dictionary.json"; -import { Clue, clue } from "./clue"; +import { Clue, clue, describeClue } from "./clue"; import { Keyboard } from "./Keyboard"; import targetList from "./targets.json"; -import { dictionarySet, pick, resetRng, seed } from "./util"; +import { dictionarySet, pick, resetRng, seed, speak } from "./util"; enum GameState { Playing, @@ -17,8 +17,7 @@ interface GameProps { hidden: boolean; } -const targets = targetList - .slice(0, targetList.indexOf("murky") + 1); // Words no rarer than this one +const targets = targetList.slice(0, targetList.indexOf("murky") + 1); // Words no rarer than this one function randomTarget(wordLength: number) { const eligible = targets.filter((word) => word.length === wordLength); @@ -31,6 +30,7 @@ function Game(props: GameProps) { const [currentGuess, setCurrentGuess] = useState(""); const [wordLength, setWordLength] = useState(5); const [hint, setHint] = useState(`Make your first guess!`); + const [srStatus, setSrStatus] = useState(``); const [target, setTarget] = useState(() => { resetRng(); return randomTarget(wordLength); @@ -57,6 +57,7 @@ function Game(props: GameProps) { if (/^[a-z]$/.test(key)) { setCurrentGuess((guess) => (guess + key).slice(0, wordLength)); setHint(""); + setSrStatus(""); } else if (key === "Backspace") { setCurrentGuess((guess) => guess.slice(0, -1)); setHint(""); @@ -72,7 +73,9 @@ function Game(props: GameProps) { setGuesses((guesses) => guesses.concat([currentGuess])); setCurrentGuess((guess) => ""); if (currentGuess === target) { - setHint("You won! (Enter to play again)"); + setHint( + `You won! The answer was ${target.toUpperCase()}. (Enter to play again)` + ); setGameState(GameState.Won); } else if (guesses.length + 1 === props.maxGuesses) { setHint( @@ -81,6 +84,7 @@ function Game(props: GameProps) { setGameState(GameState.Lost); } else { setHint(""); + speak(describeClue(clue(currentGuess, target))); } } }; @@ -98,7 +102,7 @@ function Game(props: GameProps) { }, [currentGuess, gameState]); let letterInfo = new Map(); - const rowDivs = Array(props.maxGuesses) + const tableRows = Array(props.maxGuesses) .fill(undefined) .map((_, i) => { const guess = [...guesses, currentGuess][i] ?? ""; @@ -117,7 +121,13 @@ function Game(props: GameProps) { ); @@ -146,11 +156,10 @@ function Game(props: GameProps) { setTarget(randomTarget(length)); setWordLength(length); setHint(`${length} letters`); - (document.activeElement as HTMLElement)?.blur(); }} > - {rowDivs} -

{hint || `\u00a0`}

+ + {tableRows} +
+

{hint || `\u00a0`}

+ {/*

+ {srStatus} +

*/} {seed ? (
diff --git a/src/Keyboard.tsx b/src/Keyboard.tsx index ceb1c24..3413d53 100644 --- a/src/Keyboard.tsx +++ b/src/Keyboard.tsx @@ -13,7 +13,7 @@ export function Keyboard(props: KeyboardProps) { ]; return ( -
+