diff --git a/src/About.tsx b/src/About.tsx
new file mode 100644
index 0000000..d6e7f2b
--- /dev/null
+++ b/src/About.tsx
@@ -0,0 +1,70 @@
+import { Clue } from "./clue";
+import { Row, RowState } from "./Row";
+import { maxGuesses } from "./util";
+
+export function About() {
+ return (
+
+
+ hello wordl is a remake of the word game{" "}
+
+ Wordle
+ {" "}
+ by powerlanguage, which
+ I think is based on the TV show Lingo.
+
+
+ You get {maxGuesses} tries to guess a target word.
+
+ After each guess, you get Mastermind-style feedback:
+
+
|
+
+ W and O aren't in the target word at all.
+
+ R is correct! The third letter is R
+ .
+ D occurs elsewhere in the target word.
+
+
+ Let's move the D in our next guess:
+
+
|
+
So close!
+
|
+
Got it!
+
+ Report issues{" "}
+ here, or tweet{" "}
+ @chordbug.
+
+
+ );
+}
diff --git a/src/App.tsx b/src/App.tsx
index fe0a131..498fb45 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,85 +1,35 @@
import "./App.css";
-import { seed } from "./util";
+import { maxGuesses, seed } from "./util";
import Game from "./Game";
import { useState } from "react";
-import { Row, RowState } from "./Row";
-import { Clue } from "./clue";
+import { About } from "./About";
-const maxGuesses = 6;
-
-function About() {
- return (
-
-
- hello wordl is a remake of the word game{" "}
-
- Wordle
- {" "}
- by powerlanguage, which
- I think is based on the TV show Lingo.
-
-
- You get {maxGuesses} tries to guess a target word.
-
- After each guess, you get Mastermind-style feedback:
-
-
|
-
- W and O aren't in the target word at all.
-
- R is correct! The third letter is R
- .
- D occurs elsewhere in the target word.
-
-
- Let's move the D in our next guess:
-
-
|
-
So close!
-
|
-
Got it!
-
- Report issues{" "}
- here, or tweet{" "}
- @chordbug.
-
-
- );
-}
-
-function Settings() {
- return <>TODO: dark theme, hard mode, etc.>;
+function useSetting(key: string, initial: T): [T, (value: T | ((t: T) => T)) => void] {
+ const [current, setCurrent] = useState(() => {
+ try {
+ const item = window.localStorage.getItem(key);
+ return item ? JSON.parse(item) : initial;
+ } catch (e) {
+ return initial;
+ }
+ });
+ const setSetting = (value: T | ((t: T) => T)) => {
+ try {
+ const v = value instanceof Function ? value(current) : value;
+ setCurrent(v);
+ window.localStorage.setItem(key, JSON.stringify(v));
+ } catch (e) {}
+ };
+ return [current, setSetting];
}
function App() {
const [page, setPage] = useState<"game" | "about" | "settings">("game");
+ const prefersDark =
+ window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
+ const [dark, setDark] = useSetting("dark", prefersDark);
+ const [hard, setHard] = useSetting("hard", false);
+
return (
hello wordl
@@ -113,16 +63,36 @@ function App() {
onClick={() =>
(document.location = seed
? "?"
- : "?seed=" +
- new Date().toISOString().replace(/-/g, "").slice(0, 8))
+ : "?seed=" + new Date().toISOString().replace(/-/g, "").slice(0, 8))
}
>
{seed ? "Random" : "Today's"}
{page === "about" && }
- {page === "settings" && }
-
+ {page === "settings" && (
+
+ )}
+
);
}
diff --git a/src/Game.tsx b/src/Game.tsx
index c7beaf1..a8d085e 100644
--- a/src/Game.tsx
+++ b/src/Game.tsx
@@ -15,6 +15,7 @@ enum GameState {
interface GameProps {
maxGuesses: number;
hidden: boolean;
+ hard: boolean;
}
const targets = targetList.slice(0, targetList.indexOf("murky") + 1); // Words no rarer than this one
diff --git a/src/util.ts b/src/util.ts
index 62dad2e..d7fcdc6 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -1,5 +1,7 @@
import dictionary from "./dictionary.json";
+export const maxGuesses = 6;
+
export const dictionarySet: Set = new Set(dictionary);
function mulberry32(a: number) {