feat: settings become five groups that state their own answer
The panel was one open block of everything in two columns. That reads fine at four games and stops working at eighteen: the game list alone is eighteen rows of four controls each, and it sat above the checkbox somebody had scrolled down here to tick. Nothing was findable and everything was in the way. Collapsing it into groups is only half an answer, though — a group showing nothing but its name turns "what is my region set to?" into a click, which trades one kind of friction for another. So each summary carries its group's current state: "Europe · Dark", "17 of 18 on · A–Z", "plus finished, not started". Closed, the panel is a five-line report of how the app is configured; opening one is for changing an answer rather than reading it. The states are derived from `prefs` at render, never stored, so they cannot drift from the controls they describe. Native `<details>`, for the reason the reorder arrows are ordinary buttons: keyboard and screen reader reach it with no second implementation. `summary` is not an `a`, `button` or `[tabindex]`, so it needed its own focus-visible rule — the shared one does not reach it. Two things fell out along the way. The region and appearance rows had no accessible name at all, so a screen reader read six unlabelled buttons in a row; they and the board's split pills are one `PillGroup` now, with the `role="group"` the board's own controls already carry. And the empty states that point at "Show events that haven't started" now name the group holding it, which is what makes shipping the groups closed safe. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
14f6f2f0dc
commit
fb390c1af8
@@ -907,6 +907,19 @@ to an open page). Four things hold it up:
|
||||
because touch fires no drag events at all: the arrows are the mechanism and the drag is the pointer
|
||||
fast path, and being ordinary buttons is what makes the whole thing reachable by keyboard and
|
||||
screen reader without a second implementation of the same interaction.
|
||||
- **The settings panel is groups that state their own answer, and they ship closed.** Five
|
||||
`<details>` groups — games, reading, what you see, your own, your progress — each with its current
|
||||
state on the summary line (`Europe · Dark`, `17 of 18 on · A–Z`, `plus finished, not started`). It
|
||||
was one open block in two columns, which is readable at four games and not at eighteen, where the
|
||||
game list is eighteen rows of four controls sitting above the checkbox somebody came to tick. The
|
||||
state line is the half that makes collapsing honest: without it every question about how the app is
|
||||
set up costs a click, so the closed panel has to be a report and not a menu. Two rules follow.
|
||||
**Do not default a group open** to make something inside it findable — the empty states name the
|
||||
group as well as the switch, which is what makes that unnecessary. And the summaries are **derived
|
||||
from `prefs` at render**, never stored, so they cannot drift from the controls they describe.
|
||||
Native `<details>` for the reason the reorder arrows are ordinary buttons: keyboard and screen
|
||||
reader reach it without a second implementation. `summary` is not an `a`, `button` or `[tabindex]`,
|
||||
so it needs its own `:focus-visible` rule in `styles.css` — the shared one does not reach it.
|
||||
- **A game's dailies stay together, and grouping never re-sorts inside a group.** `dailyGroups`
|
||||
(`Dailies.tsx`) emits a game's standing chore followed by that game's repeating events, in the
|
||||
order those arrived; it replaced `[...chores, ...repeating]`, which put a game's chore and its own
|
||||
|
||||
Reference in New Issue
Block a user