iPhone: list screens, Settings and bars share one edge colour (#226 round 2) #279

Closed
kayg wants to merge 0 commits from issue/226-phone-bars-2 into dev
Owner

Fixes #226 (round 2). Replaces PR #254's approach for the edges; opened fresh because the forge ignores pushes to an existing PR.

Why round 1 passed its spec and failed on the phone

  1. The spec was circular. It read the pixel at the very edge row, and the edge row was my own fade band painted in the colour under test. It never compared the edge with the sheet next to it, so a flat grey band over a dark sheet passed.
  2. Photo estimate wrong. The page colour came from the photo's top sky (bright grey); the rest of the photo is dark. The band at the bottom faded to that grey. Sheet over photo had no relation to the guess.
  3. Two glass sheets. On a list screen the home screen stays mounted at -30% under the list, and is also glass. The backdrop was tinted twice on the left 70% of the width and once on the right 30%, so no single colour could match. This also cost a second backdrop blur.
  4. Settings was not covered. While Settings is up, PhoneStack cleared data-edge, so the status bar fell back to the raw backdrop colour and the .floor never showed. Settings is paper edge to edge, so it now gets data-edge="paper" and the paper reaches the bottom under the toolbar.
  5. Tall phone. The paper and sheet end at 100svh; with Safari's toolbar collapsed the screen is taller. The floor only existed when data-edge was set (see 4), and the spec never had a screen taller than --vh.
  6. A bug in my tint parser (un-premultiplied twice) made the estimate wrong for dark tints.

What changed

  • While a list is up, Backdrop fades the picture to one colour (--edge-key) at the top and bottom of the screen (.scrim; solid through the status bar and the last 130px). The glass over a uniform colour is exactly computable, so the sheet is the same colour at both edges and the bars match it; the fade bands in PhoneStack are now only a guarantee.
  • --edge-key for a photo is the real photo's average, sampled from the image's own pixels (16x16 canvas, dimmed as dark theme dims it). Sky and plain use their top colour.
  • A screen under another one is visibility: hidden once the top one has slid in (shown at once when going back and for the whole of a swipe): one glass sheet at a time, one blur less.
  • Settings (phone) is paper to the edges.
  • Tint parsing fixed.

Spec (e2e/phone-bars.spec.ts)

Screens: home, Journal, All notes, a note, Settings. Sizes 393x852 (all four hours), 430x932 and 390x844 (day and night). Light and dark; sky, plain and photo. Insets of an iPhone with a Dynamic Island (59 / 34), and the toolbar faked by shortening the app's --vh by 90px while the screen stays full height, as with the toolbar collapsed. Asserts, from real screenshot pixels: top and bottom row == html background == theme-color (dE < 2); the strip below the app (the toolbar's) is the page colour, never raw backdrop; and 36px / 98px in from each edge the screen is still within dE 15 of its edge colour (round 1's grey bands were dE ~30 off). 240 per engine: Chromium 240/240, WebKit 240/240. safe-areas.spec.ts passes (one existing assertion now waits for the overscan shadow's 380ms fade; it raced it).

Not testable here: real Safari tinting. kayg's phone is the judge.

🤖 Generated with Claude Code

https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T

Fixes #226 (round 2). Replaces PR #254's approach for the edges; opened fresh because the forge ignores pushes to an existing PR. ## Why round 1 passed its spec and failed on the phone 1. **The spec was circular.** It read the pixel at the very edge row, and the edge row was my own fade band painted in the colour under test. It never compared the edge with the sheet next to it, so a flat grey band over a dark sheet passed. 2. **Photo estimate wrong.** The page colour came from the photo's top sky (bright grey); the rest of the photo is dark. The band at the bottom faded to that grey. Sheet over photo had no relation to the guess. 3. **Two glass sheets.** On a list screen the home screen stays mounted at -30% under the list, and is also glass. The backdrop was tinted twice on the left 70% of the width and once on the right 30%, so no single colour could match. This also cost a second backdrop blur. 4. **Settings was not covered.** While Settings is up, PhoneStack cleared `data-edge`, so the status bar fell back to the raw backdrop colour and the `.floor` never showed. Settings is paper edge to edge, so it now gets `data-edge="paper"` and the paper reaches the bottom under the toolbar. 5. **Tall phone.** The paper and sheet end at `100svh`; with Safari's toolbar collapsed the screen is taller. The floor only existed when `data-edge` was set (see 4), and the spec never had a screen taller than `--vh`. 6. A bug in my tint parser (un-premultiplied twice) made the estimate wrong for dark tints. ## What changed - While a list is up, `Backdrop` fades the picture to **one colour (`--edge-key`) at the top and bottom of the screen** (`.scrim`; solid through the status bar and the last 130px). The glass over a uniform colour is exactly computable, so the sheet is the same colour at both edges and the bars match it; the fade bands in PhoneStack are now only a guarantee. - `--edge-key` for a photo is the **real photo's average, sampled from the image's own pixels** (16x16 canvas, dimmed as dark theme dims it). Sky and plain use their top colour. - A screen under another one is `visibility: hidden` once the top one has slid in (shown at once when going back and for the whole of a swipe): one glass sheet at a time, one blur less. - Settings (phone) is paper to the edges. - Tint parsing fixed. ## Spec (`e2e/phone-bars.spec.ts`) Screens: home, Journal, All notes, a note, Settings. Sizes 393x852 (all four hours), 430x932 and 390x844 (day and night). Light and dark; sky, plain and photo. Insets of an iPhone with a Dynamic Island (59 / 34), and the toolbar faked by shortening the app's `--vh` by 90px while the screen stays full height, as with the toolbar collapsed. Asserts, from real screenshot pixels: top and bottom row == `html` background == `theme-color` (dE < 2); the strip below the app (the toolbar's) is the page colour, never raw backdrop; and 36px / 98px in from each edge the screen is still within dE 15 of its edge colour (round 1's grey bands were dE ~30 off). 240 per engine: Chromium 240/240, WebKit 240/240. `safe-areas.spec.ts` passes (one existing assertion now waits for the overscan shadow's 380ms fade; it raced it). Not testable here: real Safari tinting. kayg's phone is the judge. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Phone bars, round 2 part 2: one glass sheet at a time, edge model fixed, wider spec (#226)
Some checks failed
CI / server (pull_request) Successful in 28s
CI / web (pull_request) Failing after 28s
CI / rust (pull_request) Failing after 1m26s
e1b356bdfd
- A screen under another one is hidden once the top one has slid in: two stacked glass
  sheets tinted the backdrop twice (and the part past the top one's edge once).
- glass-edge.ts: tints are straight channels from getImageData; they were un-premultiplied twice.
- Spec: Settings, 393x852 / 430x932 / 390x844, a faked collapsed toolbar (strip below the app
  must be page colour), and a no-flat-band check a little way in from each edge.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Author
Owner

Landed in merge train #282.

Landed in merge train #282.
kayg closed this pull request 2026-10-14 13:10:20 +00:00
Some checks failed
CI / server (pull_request) Successful in 28s
CI / web (pull_request) Failing after 28s
CI / rust (pull_request) Failing after 1m26s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!279
No description provided.