A dame.is & pds.dad production bsky38.com

UX/design polish, changes to voting suggestions, footer upgrades #65

Merged pds.dad
targeting main
Merged opened by and assigned to pds.dad
targeting main

The vote page had three suggestion lists stacked down it — people you engage with, people you follow, the standings — each with the same row anatomy ending in the same Vote button. Run together they read as one very long list that kept restarting. They are now three tabs, Engaged / Followed / All, so choosing a mode is the reader saying which question they are asking: who do I talk to, who do I follow, who is winning. Each tab puts its list control in the same strip above the rows, with a count beside it to ground the sample — "233 accounts you follow", "6 nominees · 3 voters" — because a page of six faces means something the six on their own do not.

All three panels mount on load rather than on first visit, which is what makes "Surprise me" worth keeping. It used to ask the server for a random pool member, so the one thing it could never suggest was someone who did not already have a vote — on a page whose whole premise is that anyone can be voted for. It now draws from the union of all three lists, merging so a leaderboard row keeps the rank and tally the other two lack, and filtering out the reader, the face already showing, and everyone they have voted for. The server draw stays as the floor for a cold load, or a reader who engages with nobody and follows nobody. Its first draw also waits on myRecords now: fired on the session alone it raced the ballot load, and the exclude list was usually just the reader's own did.

Voting is a toggle. VoteButton is the one place a vote is cast or taken back, and "Voted" is a button carrying aria-pressed rather than the stamp-shaped span it was — press it again and the vote is gone. Deliberately unconfirmed: a mis-tap costs one press to undo, and a repo write either way, so a dialog would be asking about the cheaper of the two mistakes. That is what lets the ballot page drop its separate Remove button, and with it the "Counted" chip, which said the same thing as a filled "Voted" standing next to it. The badge still renders for over_limit, invalid, pending and frozen, since it is the only thing on the row explaining why a vote the reader can see is not counting.

Stepping out of the nominees is the one that asks. That one drops every vote cast for you off the board and rejoining restores the listing, not the standing — so it confirms inline, where it can say so, rather than through a browser dialog it cannot word.

Also on the ballot page: no rank chip. getProfile carries one and NomineeCard draws one whenever it is handed one, but a ballot is the people you picked in no order — the caption says as much — and a number in front of each face invites reading it as your ranking of them. The response was being stored behind an as Profile cast that does not declare rank, so it rode through untyped; the fields are copied explicitly now.

The chrome:

  • The signed-in account's own face, which was never there — auth held a did and a handle and nothing else. It comes from the same unauthenticated Slingshot getRecord the server's actor refresher makes, so it costs no token and no PDS hop. avatarCidOf moved into blob-url to be shared by both paths, legacy blob shape included.

  • A footer with room in it. The source link was a full btnOutline alone in the centre of the bar, which gave a footer link the weight of a call to action. It is now quiet text level with a byline crediting @pds.dad and @dame.is, each name opening the waypoints menu through a new name variant of OpenIn. The bar is a ruled sheet on the raised surface with the content sitting on opaque chips, because the rules ran straight through bare type.

  • Light is the default on a first visit, whatever the OS prefers. This is a printed page with an ink-on-newsprint palette; light is the design's home key, not a fallback, and dark stays a choice the toggle remembers.

  • The wordmark shows on a phone. It fits at 375px with room to spare, and the bare "38" mark alone read as an unlabelled icon; below about 355px it truncates rather than shoving the controls off the bar. On the leaderboard the tally column drops from 96px to 64px on mobile, which hands the name column a third more width — enough for most names to stop truncating — while still fitting a five-figure count.

And the surprise-me landing no longer scales. A zoom reads as the card coming toward the reader, a different gesture from the one the reel frames just made, and the size change was the part that caught the eye rather than the face. It travels down half a rem into place instead, and the spring's small overshoot does the rest.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

This pull request has no versions submitted yet.