Choose the video avatar from large faces rather than a pop-up

Merged
DA
4d ago
+372-121

Second of two PRs for the plan Remove default avatar option and make previews bigger/easier to see (https://tryluke.dev/stage/plan/cbf135d8-d4f5-4cd4-9823-a367a5d46c9a). The first, #3249, removed Default and has merged.

The developer chose option D, "Stage + face strip", from the mockups.

Rebuilt on the design system. While this PR was open, main moved Settings onto @luke/ui (SettingsRow, SettingsSection, Select, #3404–#3451). I rebuilt the change on top of that instead of resolving the conflicts by hand, and squashed it into one commit.

What changes

  • Settings › Experimental › Avatar no longer uses a menu. Under the row's label and description you now see:
    • a large square picture of the chosen avatar, up to 200 px, with its name
    • all eight faces as round tiles up to 88 px, four per line, with names underneath
    • an accent ring around the chosen face
  • Narrow rows: below 480 px, the large picture moves above the faces.
  • Native radio group: the faces are hidden <input type="radio">s, so Tab reaches the chosen face and the arrow keys change the choice. A press or an arrow saves straight away. The keyboard focus ring is drawn on the face's circle.
  • Search: a Settings search result for Avatar lands on the whole row, so its ring is visible.
  • @luke/ui SettingsRow: new optional below slot for a control as wide as the row. It gets the same ids as the end-of-row controls, so the label names it and the description and error describe it. children is now optional. Nothing else uses below yet.
  • PictureChoiceRow (picture-choice-row.tsx) is a SettingsRow with the gallery in below. SchemaSettingRows uses it for any choice setting where every option has a picture. Today that is only the avatar, so nothing in the settings schema changes.
  • Removed: the menu's face path in SchemaChoiceRow and SelectRow, and PictureMark, which only they used.

Screenshots

These are rendered in Chromium from the real components and the built styles.css, not on a Mac. The light shot sits on my test page's dark background; only the card is real.

Dark, Orion chosen
Dark: the chosen avatar large beside all eight faces

Light
Light: the same row

Narrow, keyboard: the large picture sits above the faces. ArrowRight moved focus and the choice to Selene, and the ring is on her face. The HTML is static, so the large picture didn't update; in the app it follows the choice.
Narrow: the large picture above the faces, focus ring on Selene

Tests

  • settings-row.test.ts: a below control is named by the label, described by the description and the error, marked invalid on an error, and comes between the words and the error in reading order.
  • experimental-page.test.ts now checks:
    • Avatar is a fieldset in Video calls' card, under its switch
    • all eight faces show at once as one radio group, with Atlas checked first
    • each face loads Keyframe's photo, and the large picture shows the chosen avatar
    • the search anchor holds the whole row
    • pressing Celia saves celia

pnpm check:affected passes. The first run timed out one unrelated features test and ran out of memory in the service typecheck while the sandbox was under load. Both passed on a rerun.