feat(web): responsive design
- fix mobile accessibility
This commit is contained in:
+115
-83
@@ -15,7 +15,7 @@
|
|||||||
} from "./solver/types.ts";
|
} from "./solver/types.ts";
|
||||||
import SolverOutput from "./components/SolverOutput.svelte";
|
import SolverOutput from "./components/SolverOutput.svelte";
|
||||||
import { FolderGit2 } from "@lucide/svelte";
|
import { FolderGit2 } from "@lucide/svelte";
|
||||||
import { tick } from "svelte";
|
import { tick, onMount } from "svelte";
|
||||||
|
|
||||||
let guesses = $state([
|
let guesses = $state([
|
||||||
{
|
{
|
||||||
@@ -45,6 +45,19 @@
|
|||||||
let w_lines: WordleLine[] = $state([]);
|
let w_lines: WordleLine[] = $state([]);
|
||||||
let cursor = $state(0);
|
let cursor = $state(0);
|
||||||
|
|
||||||
|
let is_desktop = $state(false);
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const update = () => {
|
||||||
|
is_desktop = window.innerWidth >= 768;
|
||||||
|
};
|
||||||
|
|
||||||
|
update();
|
||||||
|
window.addEventListener("resize", update);
|
||||||
|
|
||||||
|
return () => window.removeEventListener("resize", update);
|
||||||
|
});
|
||||||
|
|
||||||
async function toggleSolver() {
|
async function toggleSolver() {
|
||||||
if (solving) {
|
if (solving) {
|
||||||
await stopSolver();
|
await stopSolver();
|
||||||
@@ -136,92 +149,111 @@
|
|||||||
<svelte:window onkeydown={handleKey} />
|
<svelte:window onkeydown={handleKey} />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="min-h-screen w-full max-w-full
|
class="h-dvh w-full max-w-full
|
||||||
bg-zinc-950 text-zinc-100
|
bg-zinc-950 text-zinc-100
|
||||||
flex flex-wrap
|
"
|
||||||
items-center justify-center p-10 gap-2
|
|
||||||
overflow-x-hidden
|
|
||||||
select-none
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<a
|
<div
|
||||||
class="fixed top-4 right-4"
|
class="h-full overflow-y-auto
|
||||||
href="https://git.jroeger.de/jonas/wordle-solver-rs"
|
flex flex-wrap md:flex-row
|
||||||
target="_blank"
|
items-center justify-center p-2 md:p-10 gap-4
|
||||||
|
overflow-hidden select-none"
|
||||||
>
|
>
|
||||||
<FolderGit2 />
|
<a
|
||||||
</a>
|
class="fixed top-4 right-4"
|
||||||
<div class="text-center">
|
href="https://git.jroeger.de/jonas/wordle-solver-rs"
|
||||||
<h1 class="mb-4 text-3xl font-bold">Wordle Solver</h1>
|
target="_blank"
|
||||||
|
|
||||||
<p class="text-sm text-zinc-500">
|
|
||||||
Use Wordle-Answers:
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
bind:checked={use_default_wordle_answers}
|
|
||||||
onfocus={(e) => {
|
|
||||||
if (e.currentTarget) {
|
|
||||||
e.currentTarget.blur();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onchange={reset}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="mt-0 text-sm text-zinc-500">
|
|
||||||
{#await solution_space}
|
|
||||||
loading
|
|
||||||
{:then s}
|
|
||||||
Solution-space: {s.size}, Uncertainty: {s.uncertainty.toFixed(
|
|
||||||
2,
|
|
||||||
)}bits
|
|
||||||
{:catch e}
|
|
||||||
{e}
|
|
||||||
{/await}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="ml-16 mt-2 flex flex-col gap-2">
|
|
||||||
{#each guesses as g, i (g)}
|
|
||||||
<WordleLine
|
|
||||||
active={i === guesses.length - 1}
|
|
||||||
on_guess_pressed={i === guesses.length - 1 ? doGuess : null}
|
|
||||||
bind:this={w_lines[i]}
|
|
||||||
bind:cursor
|
|
||||||
bind:letters={guesses[i].letters}
|
|
||||||
bind:colors={guesses[i].colors}
|
|
||||||
info_gained={infos_gained[i]}
|
|
||||||
/>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="mt-4 text-sm text-zinc-500 mx-auto w-3/4">
|
|
||||||
Type letters · ← → navigate · Space cycle color · Backspace delete ·
|
|
||||||
Enter apply · Shift+Enter solve · Escape abort solver · Ctrl+Esc
|
|
||||||
reset
|
|
||||||
</p>
|
|
||||||
<button
|
|
||||||
tabindex="-1"
|
|
||||||
class="mt-2 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full"
|
|
||||||
onclick={(e) => {
|
|
||||||
e.currentTarget.blur();
|
|
||||||
toggleSolver();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{#if solving}
|
<FolderGit2 />
|
||||||
Cancel
|
</a>
|
||||||
{:else}
|
<div class="text-center">
|
||||||
Solve
|
<h1 class="mb-4 text-3xl font-bold">Wordle Solver</h1>
|
||||||
|
|
||||||
|
<p class="text-sm text-zinc-500">
|
||||||
|
Use Wordle-Answers:
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={use_default_wordle_answers}
|
||||||
|
onfocus={(e) => {
|
||||||
|
if (e.currentTarget) {
|
||||||
|
e.currentTarget.blur();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onchange={reset}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="mt-0 text-sm text-zinc-500">
|
||||||
|
{#await solution_space}
|
||||||
|
loading
|
||||||
|
{:then s}
|
||||||
|
Solution-space: {s.size}, Uncertainty: {s.uncertainty.toFixed(
|
||||||
|
2,
|
||||||
|
)}bits
|
||||||
|
{:catch e}
|
||||||
|
{e}
|
||||||
|
{/await}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="mt-2 flex flex-col gap-2">
|
||||||
|
{#each guesses as g, i (g)}
|
||||||
|
<WordleLine
|
||||||
|
active={i === guesses.length - 1}
|
||||||
|
on_guess_pressed={i === guesses.length - 1
|
||||||
|
? doGuess
|
||||||
|
: null}
|
||||||
|
bind:this={w_lines[i]}
|
||||||
|
bind:cursor
|
||||||
|
bind:letters={guesses[i].letters}
|
||||||
|
bind:colors={guesses[i].colors}
|
||||||
|
info_gained={infos_gained[i]}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if is_desktop}
|
||||||
|
<p class="mt-4 text-sm text-zinc-500 mx-auto w-3/4">
|
||||||
|
Type letters · ← → navigate · Space cycle color · Backspace
|
||||||
|
delete · Enter apply · Shift+Enter solve · Escape abort
|
||||||
|
solver · Ctrl+Esc reset
|
||||||
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
<button
|
||||||
|
tabindex="-1"
|
||||||
|
class="mt-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full"
|
||||||
|
onclick={(e) => {
|
||||||
|
e.currentTarget.blur();
|
||||||
|
toggleSolver();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#if solving}
|
||||||
|
Cancel
|
||||||
|
{:else}
|
||||||
|
Solve
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{#if best_words}
|
||||||
|
<SolverOutput
|
||||||
|
data={best_words}
|
||||||
|
progress={best_words_progress}
|
||||||
|
insert_guess={(g) => {
|
||||||
|
guesses[guesses.length - 1].letters = g;
|
||||||
|
}}
|
||||||
|
bind:solving
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if best_words}
|
|
||||||
<SolverOutput
|
|
||||||
data={best_words}
|
|
||||||
progress={best_words_progress}
|
|
||||||
insert_guess={(g) => {
|
|
||||||
guesses[guesses.length - 1].letters = g;
|
|
||||||
}}
|
|
||||||
bind:solving
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global(body) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
overscroll-behavior: none;
|
||||||
|
background: #09090b;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
if (event.key === "Backspace") {
|
if (event.key === "Backspace") {
|
||||||
if (letters[cursor] === "" && cursor > 0) {
|
if (letters[cursor] === "" && cursor > 0) {
|
||||||
cursor--;
|
cursor--;
|
||||||
|
inputs[cursor].focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
@@ -69,7 +70,7 @@
|
|||||||
disabled={!active}
|
disabled={!active}
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="
|
class="
|
||||||
flex h-16 w-16 items-center justify-center
|
flex aspect-square max-w-16 w-1/6 items-center justify-center
|
||||||
rounded-lg border-2
|
rounded-lg border-2
|
||||||
text-3xl font-bold
|
text-3xl font-bold
|
||||||
transition-all text-center caret-transparent
|
transition-all text-center caret-transparent
|
||||||
@@ -111,7 +112,7 @@
|
|||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
<span
|
<span
|
||||||
class="w-16 text-sm text-zinc-500 self-center flex items-center justify-center"
|
class="max-w-14 w-1/6 text-sm text-zinc-500 self-center flex items-center justify-center"
|
||||||
onclick={info_gained === null ? on_guess_pressed : null}
|
onclick={info_gained === null ? on_guess_pressed : null}
|
||||||
>
|
>
|
||||||
{#if info_gained === null}
|
{#if info_gained === null}
|
||||||
|
|||||||
Reference in New Issue
Block a user