fix(review): the heid code-review and bug-hunt panels on r2c, folded (both 4/4 with retries)
- 1:1 start-aligns. The centred flex item overflowed both sides and the start was unreachable; measured, a 3000px picture hid its leftmost 980px. Auto margins still centre a small picture. - Drag lifecycle: a move with no button ends the drag, so a press released outside the stage never pans on a later hover. Capture is now load-bearing in a test. The threshold is 4px of total movement. - A press on the stage's own scrollbar is never a pan. The arrows clamp to the stage's client box, so they are never under a classic scrollbar. The test runs a browser without --hide-scrollbars and asserts the gutter exists. - Stacked, the arrows' CSS spot is the stage's centre (30vh), set in view.html because base.html lost to the page's later rule. - The stage reveal is `hidden` until bound, and keeps Fit's drop shadow when revealed. A blurred picture composes blur() drop-shadow(). - The mode follows another tab. A failed or unknown size returns the arrows to their CSS spot. - Tests: object-position, vertical centring, the Fit half of aria-pressed, a storage read that throws, a large picture's toggle, Fit forgetting 1:1, single-axis pan. - Declared: the r2b reveal test reads "no blur" (the shadow stays), and the r2_flow 360px-offset row is retired. Mutation tables 137/137 across four. 810 passed.
This commit is contained in:
@@ -32,9 +32,15 @@ assumptions:
|
||||
the image shows at fit size"): the size changes, the promise (one picture at a
|
||||
readable size, no judgment behind a script) holds.
|
||||
- The drop shadow follows the picture's own pixels (`drop-shadow`), not the
|
||||
letterboxed box.
|
||||
letterboxed box, on every path: blurred (`blur() drop-shadow()`, because
|
||||
`filter` is one property and a blur rule would replace the shadow),
|
||||
revealed, and under Reveal all.
|
||||
- **1:1 shows natural pixels**, centred when smaller than the stage and
|
||||
scrollable when larger. The upscale softness in Fit is exactly why 1:1 exists
|
||||
scrollable when larger, with EVERY pixel reachable. The stage aligns to its
|
||||
START edge in 1:1, and the picture's auto margins centre it when it is
|
||||
smaller. A centred flex item larger than its scroll box overflows both
|
||||
sides, and the start side can never be scrolled to (heid code-review,
|
||||
measured: a 3000px picture hid its leftmost 980px). The upscale softness in Fit is exactly why 1:1 exists
|
||||
and is always one click away.
|
||||
|
||||
## S2 — the toggle is always there for a picture
|
||||
@@ -54,7 +60,10 @@ assumptions:
|
||||
stage's CSS keys off it (`.stage-one .vstage`); the server renders the
|
||||
stage as plain `vstage` (Fit is the default, no class needed).
|
||||
- A stored value other than `one` reads as Fit. A read that throws reads as
|
||||
Fit; a write that throws still applies the click. Never raises.
|
||||
Fit; a write that throws still applies the click, the pressed state
|
||||
included. Never raises.
|
||||
- A mode chosen in another tab moves every open review (the `storage` event),
|
||||
as the theme does.
|
||||
- The buttons' pressed state is drawn from the `<html>` class, the one
|
||||
record of the mode on the page (storage is its memory, off the page).
|
||||
|
||||
@@ -62,12 +71,14 @@ assumptions:
|
||||
|
||||
- **Each arrow sits wholly outside the picture's DRAWN edge, its near edge 8px
|
||||
from the picture**, vertically centred on the stage. The measure is always
|
||||
the DRAWN picture, never the file's natural size: in Fit, the `object-fit:
|
||||
contain` content box (from the natural size and the box); in 1:1, the part of
|
||||
the picture visible in the stage (its box intersected with the stage's). A
|
||||
the DRAWN picture, never the file's natural size: the `object-fit: contain`
|
||||
content box (from the natural size and the box). In 1:1 (scale 1) that IS the
|
||||
picture's own box, and where it runs past the stage the clamp keeps the arrows
|
||||
inside. A
|
||||
video's own box counts the same way; audio keeps the stage-edge arrows.
|
||||
- **Clamped to the stage**: an arrow never goes past the stage's edge (8px
|
||||
inset), never over the rail, never off the stage. When there is no room for
|
||||
- **Clamped to the stage's CLIENT box**: an arrow never goes past the stage's
|
||||
edge (8px inset), never over the rail, never off the stage, and never under
|
||||
a classic scrollbar (the client box excludes it). When there is no room for
|
||||
it outside the drawn picture — the drawn picture spans, or nearly spans, the
|
||||
stage's width — it sits at the stage edge, over the picture. That is the
|
||||
ONLY case the arrows sit at the stage edge (the operator: "closer to the edge
|
||||
@@ -75,10 +86,17 @@ assumptions:
|
||||
width").
|
||||
- Re-placed on picture load (or at once when it is already loaded), stage
|
||||
resize (a `ResizeObserver`, which covers window resizes and the rail
|
||||
stacking), mode switch and 1:1 scroll.
|
||||
stacking) and mode switch. (Scrolling a 1:1 picture cannot move its drawn
|
||||
horizontal edges past the clamp, so it needs no re-placement.)
|
||||
- **Before the picture's size is known** (JS on, picture still loading), and if
|
||||
it fails to load, the arrows stay at today's stage-edge CSS; they move once
|
||||
the drawn box is known. Without JS they stay there.
|
||||
it fails to load, the arrows stay at their CSS spot; they move once the drawn
|
||||
box is known. Without JS they stay there. If the size ever becomes unknown
|
||||
again, a placed arrow returns to that spot rather than keeping a stale one.
|
||||
- That CSS spot is the STAGE's vertical centre. When stacked (≤900px) that
|
||||
is 30vh down: the stage is the body's first 60vh, and centring on the
|
||||
whole body put the arrows over a tall rail (heid code-review). The rule
|
||||
lives in view.html after `.vnav`, because a base.html rule loses to the
|
||||
page's own later one.
|
||||
- The anchors, their classes and their hrefs are unchanged (test_booth,
|
||||
test_navigation, test_flow pin them).
|
||||
|
||||
@@ -89,12 +107,24 @@ assumptions:
|
||||
`grabbing` while dragging, pointer capture.
|
||||
- **The picture follows the pointer** (the grab convention): a drag of +dx,
|
||||
+dy changes the stage's scroll by −dx, −dy.
|
||||
- A press that moves less than 4px is not a drag: nothing pans.
|
||||
- A press that moves less than 4px IN TOTAL (Euclidean) is not a drag:
|
||||
nothing pans. A (3, 3) diagonal is 4.24px, so it pans.
|
||||
- A press on the stage's own scrollbar is the scrollbar's, never a pan.
|
||||
- The drag is CAPTURED once it begins, so it keeps panning past the stage's
|
||||
edge. A press released outside the stage before the drag began never
|
||||
becomes a pan: a move with no button held ends it.
|
||||
- **Pan listens on the stage only**, and no control is in the stage's
|
||||
scrolled content: the arrows never were, and **the stage's own reveal
|
||||
button moves OUT of the stage to sit over it** (found building this: in
|
||||
1:1 a panned picture carried the button out of view with it). So a control
|
||||
is never a pan source and keeps its own click, at any scroll.
|
||||
- That reveal is JS-only, so it renders `hidden` until the script binds it,
|
||||
the toggle's pattern (heid bug-hunt: shown with scripts off, it did
|
||||
nothing). A revealed picture keeps Fit's drop shadow.
|
||||
- Accepted: no `touch-action`. On touch the stage scrolls natively, and the
|
||||
pan yields on `pointercancel`; `none` would take native touch scrolling
|
||||
away. The `dragstart` `preventDefault` sits beside `draggable=false` as a
|
||||
second layer.
|
||||
- **The picture cannot be dragged away**: `draggable="false"` on `#vimg` and a
|
||||
`dragstart` `preventDefault` on the stage.
|
||||
- Fit, or a 1:1 picture that fits: no pan, no grab cursor.
|
||||
@@ -130,6 +160,22 @@ assumptions:
|
||||
edge 8px (±2) from it; a landscape drawn as wide as the stage — arrows inside
|
||||
the stage at its edges, over the picture, never over the rail; after a window
|
||||
resize they follow the new drawn box.
|
||||
- `in_one_to_one_every_pixel_of_a_large_picture_is_reachable`: at scroll
|
||||
(0, 0) the picture's top-left is the stage's; at the far scroll its
|
||||
bottom-right is; a small picture is centred.
|
||||
- `a_pan_holds_past_the_stage_edge_and_never_starts_on_a_hover`: a drag
|
||||
carried past the stage's edge keeps panning; a press released outside,
|
||||
then a buttonless hover, pans nothing.
|
||||
- `before_placement_the_arrows_never_sit_over_the_rail_on_a_narrow_screen`:
|
||||
JS off at 390px with a rail taller than the stage, the arrows sit within
|
||||
the stage; a picture that fails to load leaves them unplaced, with no error.
|
||||
- `the_stage_reveal_never_shows_without_js_and_keeps_the_fit_shadow`.
|
||||
- `a_stage_mode_chosen_in_one_tab_moves_the_others`.
|
||||
- `a_classic_scrollbar_is_neither_under_an_arrow_nor_a_pan`: with a forced 15px
|
||||
classic bar (asserted real first: headless Chromium hides scrollbars), the
|
||||
next arrow sits inside the client box, and a press dispatched on the bar
|
||||
pans nothing.
|
||||
- `a_picture_that_overflows_one_axis_pans_along_it`.
|
||||
- `in_one_to_one_a_drag_pans_and_the_picture_cannot_be_dragged_away`: a picture
|
||||
overflowing both axes in 1:1 — a drag of (+80, +60) changes the scroll by
|
||||
(−80, −60); a 2px press pans nothing; a press on the stage's reveal button
|
||||
@@ -141,7 +187,9 @@ assumptions:
|
||||
| test | today | after | why |
|
||||
|---|---|---|---|
|
||||
| test_flow_browser `test_the_next_arrow_clears_the_rail_only_beside_it` | the next arrow's computed `right` is 360px wide / 0px narrow | replaced by `the_arrows_sit_just_outside_the_picture_and_clamp_to_the_stage` (never over the rail; at the picture's edge) | the arrows now track the picture, not the stage edge (operator) |
|
||||
| test_flow `test_only_a_picture_gets_the_fit_toggle_and_blur_stays_honest` | `id="vtoggle"` present for a picture (hidden by inline style); the stage is `class="vstage fit is-blurred"` | the same presence, now with the `hidden` attribute; the stage is `class="vstage is-blurred"` | the toggle is `hidden` until the script shows it; the mode moved to `<html>` (never flash) |
|
||||
| test_flow_browser `test_reveal_all_reveals_every_blurred_surface_and_survives_the_next_page` (r2b) | the revealed review stage's filter is `none` | it carries no blur (`blur(` absent); Fit's `drop-shadow` stays | the stage keeps its shadow on every path (S1) |
|
||||
| tests/mutations/r2_flow.toml, the row on the next arrow's 360px offset | proved `.vnext{right:360px}` wide / 0 narrow | retired, with successors in r2c.toml | its test was replaced (row one above) |
|
||||
| test_flow `test_only_a_picture_gets_the_fit_toggle_and_blur_stays_honest` | `id="vtoggle"` present for a picture (hidden by inline style); the stage is `class="vstage fit is-blurred"` | the same presence, now with the `hidden` attribute; the stage is `class="vstage is-img is-blurred"` | the toggle is `hidden` until the script shows it; the mode moved to `<html>` (never flash); `is-img` scopes the picture-only 1:1 rules |
|
||||
|
||||
## Out of scope
|
||||
|
||||
|
||||
Reference in New Issue
Block a user