Skip to content

Group the settings window into sections, and stop calling every pet a cat - #24

Merged
JOhnsonKC201 merged 1 commit into
mainfrom
design/settings-sections
Aug 7, 2026
Merged

Group the settings window into sections, and stop calling every pet a cat#24
JOhnsonKC201 merged 1 commit into
mainfrom
design/settings-sections

Conversation

@JOhnsonKC201

Copy link
Copy Markdown
Owner

The settings window is the only real UI the app has, and it had drifted: eleven
cards stacked in one column, the cat's nouns hard-coded into the markup, and a
header still reading "pixelcat" three commits after the rename.

Sections instead of one long scroll

About 3400px of content sat inside a window fixed at 560px, so reaching the
pomodoro or the calendar meant scrolling past ten cards you were not looking
for, with nothing to aim at and no sense of how much was left.

Five tabs now: Pet, Play, Sound, Focus, Feeds. Tallest panel is 1130px and
Sound fits on screen whole. Break/stretch moved out of Behaviour to sit with
the pomodoro, where it belongs.

before after
content height 3416px 1130px (tallest panel)
window 400x560, fixed 400x640, height draggable to 420

The rail is a real tablist: role/aria-selected/aria-controls, a roving
tabindex, and arrow/Home/End keys. Panel visibility is the hidden attribute
and nothing else, so there is no second source of truth to drift out of step.

One toggle, one description

A dog owner read "your cat", "the cat calls you by it", "Butterfly visits - a
butterfly drops by and the cat plays with it" and "Test meow", while the tray -
already reading the species registry - called that same toggle "Ball to chase".
renderer.js gives dogs a ball, not a butterfly, so the tray was right and the
settings window was wrong.

Those strings move into pets.js next to the tray's, as SETTINGS_TEXT keyed
by element id with %token% substitution. settings-renderer.js applies them
on every species change. Tests fail if a dog-facing string mentions a cat or a
meow, if a key targets an id the markup does not have, or if the play toggle
stops agreeing with the tray.

%percent% rather than braces on purpose: the reminders hint has to keep
advertising the {name} / {time} / {date} placeholders that
fillPlaceholders expands much later, and a resolver that also ate braces would
have quietly deleted the documentation for them. There is a test for that too.

Two bugs found on the way

  • The dog coat preview drew a cat. It read palettes off
    window.DOG_PATTERNS, but dog-sprite.js is a classic script whose top-level
    consts are global lexical bindings that never become window properties. The
    lookup came back undefined, the draw returned early and silently, and the
    preview had never once rendered a dog. cat-preview.js already reads them as
    bare identifiers, which is the fix.
  • The coat list could belong to the wrong species. The first config and the
    first custom-coat list arrive as two independent IPC replies, and only the
    themes reply rebuilt the dropdown, so whenever it won the race a dog owner was
    offered the cat's coats.

Also: visible focus rings (the toggles are appearance:none, which had taken
theirs with it, so tabbing showed nothing), and custom coats now say they are
cat-only instead of leaving dog owners staring at a list that never grows.

Testing

  • npm test 127 pass (10 new in tests/settings-copy.test.js), npm run lint clean
  • npm run test:boot green (launches the real app)
  • Both species and all five tabs driven in Chromium: copy resolves with no
    leftover tokens, keyboard arrows move the rail, no horizontal overflow at 400px,
    no page errors
  • Dog preview verified by sampling canvas pixels, not by eye: the bitmap changes
    cat -> dog and Golden Retriever -> Dalmatian
  • Window constraints checked against real Electron: asked for 900x800 and got
    401x802; asked for 400x300 and got 400x421

Not included

The overlay sprite art, the speech bubble and the marketing site are untouched.

…nguage

Eleven cards in one 3400px column inside a window fixed at 560px meant
reaching the pomodoro or the calendar was a blind scroll past ten cards you
were not looking for, with nothing to aim at. The window is five tabs now -
Pet, Play, Sound, Focus, Feeds - and the tallest is 1130px, with Sound
fitting on screen whole. The rail is keyboard-drivable (arrows, Home/End)
and carries the ARIA a tablist is supposed to.

The wording was the cat's, hard-coded in the markup, so a dog owner read
"your cat", "the cat calls you by it" and "Butterfly visits" while the tray,
reading the species registry, already called that same toggle "Ball to
chase". Those strings move into pets.js beside the tray's, so one toggle
cannot be described two ways, and a test fails if any dog-facing string
mentions a cat. The header also still read "pixelcat" after the 0.3.0
rename.

Two bugs surfaced on the way:

- The coat preview read its dog palettes off window.DOG_PATTERNS, but
  dog-sprite.js is a classic script whose top-level consts are global
  lexical bindings and never become window properties. The lookup came back
  undefined and the draw bailed out early and silently, so picking a breed
  relabelled everything and went on showing the cat. The preview had never
  once rendered a dog.
- Only the custom-coat IPC reply rebuilt the coat dropdown, so whenever it
  beat the config reply a dog owner was offered the cat's coats.

Also: the toggle switches are appearance:none, which had taken their focus
ring with it, so tabbing through the window showed nothing; and the height
is draggable now (420 min, 640 default) rather than frozen, with the width
still pinned to the one-column layout.
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pixelcat Ready Ready Preview Aug 7, 2026 6:27am

@JOhnsonKC201
JOhnsonKC201 merged commit 5ab1eca into main Aug 7, 2026
4 checks passed
@JOhnsonKC201
JOhnsonKC201 deleted the design/settings-sections branch August 7, 2026 06:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant