fix(annotator): the detail slider drags, and Select shows the plain arrow - #565
Merged
Conversation
A range input drags on its default action, so the `preventDefault` guarding the canvas' focus left a slider that looked alive and could only be moved with the brackets. Focus now goes back to the canvas on release instead, so the drag works and the chords are live again the moment it ends. The test that missed it asserted the guard *fired* — the one assertion a dead control passes. Replaced with a real pointer drag in chromium, which is the only place a range input's default action exists at all. cf. #557
Hovering a box, its edge band or a vertex showed the four-arrow move cursor. A press there selects, and only becomes a move if the pointer travels, so it advertised the rarer outcome. The hover highlight is unchanged and still reports which shape a press would take. A drag in flight keeps move, and a selected box's grips keep their resize keywords. This reverses a decision argued in the code; the new argument is at the change site and in DESIGN.md. cf. #567
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two fixes to the annotation editor, both found in the running app rather than by the suite.
Closes #564. Closes #567.
1. The Detail slider could not be moved with the pointer
Dragging the thumb did nothing, clicking the track did nothing, and
[/]were the only wayto change the setting.
The press was cancelled. The slider carried
onMouseDown={keepFocusOnCanvas}, which callspreventDefault(). That guard exists for a good reason — every chord in the editor is akeydownon the annotator's own root, so a control that holds focus switches[,],Escand
Enteroff with nothing on screen to say why — and it is correct on a button. It is wrongon a range input, because a range input drags on its default action.
The slider now takes focus for the duration of the gesture and hands it back on release
(
onMouseUp/onTouchEnd→returnFocusToCanvas), which reaches the root the wayFrameGalleryalready does after its overlay closes.Why nothing caught it. The test asserted the guard fired —
expect(fireEvent.mouseDown(slider)).toBe(false)— which is the one assertion a control thatdoes nothing at all will always pass. Nothing anywhere dragged the thumb and looked at the
value, and jsdom could not have: a range input's default action does not exist there. Replaced
with a real pointer drag in chromium, plus a jsdom test that the press is not cancelled and
that
mouseupreturns focus.fill()andlocator.click()both set the value withoutexercising the default action, so neither would have caught it either.
2. Select mode showed the four-arrow cursor over a shape
Hovering a box, its edge band, or a vertex of a selected polygon showed
move. It now shows theplain arrow.
This reverses a decision the code argued for, so the argument moved with it. The old one:
a press in that band starts a move, so
moveis what the cursor owes. What it missed is whichoutcome is being promised — a press on a shape selects it, and only becomes a move if the
pointer then travels. Selection is the common case by a wide margin, so
moveadvertised therarer one on every hover.
Nothing is withheld:
hotis unchanged, so the shape still highlights under the pointer, whichsays this is what a press would take without claiming what it would then do.
viewerAffordanceAthas held that position since it was written.Unchanged: a drag actually in flight still answers
move, a selected box's grips keep theirdirectional resize keywords, and drawing tools keep the crosshair.
A consequence worth naming: the cursor no longer distinguishes the read-only viewer from the
editor. Two tests were built on exactly that contrast and would have gone quietly hollow rather
than red — one vitest case and one e2e title — so both are re-pointed at what still separates
the modes, which is the grips.
DESIGN.mdis amended in the same commit for the same reason.Red before green
Both changes, by their own mutation:
The second is worth reading twice.
affordance.test.tsalso carries a union-coverage testasserting every
Cursormember is actually produced, and it sourcedmoveonly from ahover — so it would have broken as collateral and been "fixed" by deleting
movefrom theunion, taking the two drag states with it. It now sources
movefrom amovingstate instead,and it correctly stayed green under the mutation: only the four hover assertions moved,
which is the shape that proves they are the ones doing the work.
The gate
Both failures are timeouts, not assertions —
mouse.downandpage.reloadeach exceeded20 s under load, so neither test reached its claim. One is #550's known pair; the other is
perf.spec.ts's mutation-count gate, which passes in isolation along with all six perfspecs (
6 passed (1.2m)) — checked rather than assumed, since a cursor change is exactly thesort of thing that could add a style mutation. No Python is touched by either change.
Flags for Armando
fired is not a test that the control works. They are independent, and only the second is what
somebody uses.
onTouchEndis on argument, not evidence — no touch device in CI and I have not drivenone. If touch is out of scope for the editor, it comes out.