From 74c1f74e878a151127be265651d271496112aa9e Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Thu, 20 Aug 2026 06:01:56 +0200 Subject: [PATCH] feat: reorder games from settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The games chip row becomes a row per game, because a reorder affordance needs somewhere to put a handle and two arrows, and at fourteen games a list reads better than a wrapped row of pills anyway. Reordering lives here and nowhere else. The focus bar and the dailies strip are the fastest tap targets in the app, and a drag target sitting on top of a tick target costs somebody a streak the first time it misfires — so the live surfaces stay drag-free and this is the screen you visit on purpose. Both affordances ship. Touch fires no drag events at all, so the arrows are the mechanism and the handle is the pointer fast path; being ordinary buttons is also what makes the whole thing reachable by keyboard and screen reader without a second implementation of the same interaction. An arrow at either end is disabled rather than removed, because a control that disappears on the first row slides the other one under the finger aiming at it. A move writes back the whole displayed list: the indices are positions on screen, so applying them to a stored order that names only some lanes would move the wrong game. Reset writes the field away rather than storing an empty order. Co-Authored-By: Claude Opus 5 (1M context) --- src/client/components/Controls.tsx | 206 +++++++++++++++++++++++++---- test/controls.test.tsx | 37 ++++++ 2 files changed, 218 insertions(+), 25 deletions(-) diff --git a/src/client/components/Controls.tsx b/src/client/components/Controls.tsx index efbdfc4..589dcc4 100644 --- a/src/client/components/Controls.tsx +++ b/src/client/components/Controls.tsx @@ -1,7 +1,9 @@ +import { useState } from "react"; import type { LaneId } from "../../shared/custom.ts"; import type { Region } from "../../shared/schema.ts"; import { REGION_LABEL } from "../../shared/time.ts"; import { useGameMeta } from "../state/gameMeta.tsx"; +import { moveGame } from "../state/gameOrder.ts"; import type { ThemeChoice } from "../state/theme.ts"; import type { Prefs } from "../state/usePrefs.ts"; import { YourOwn } from "./YourOwn.tsx"; @@ -72,31 +74,19 @@ export function Controls({ you came to change. */}
-

Games

-
- {games.map((id) => { - const game = gameMeta(id); - const on = !prefs.hiddenGames.includes(id); - return ( - - ); - })} -
+