diff --git a/frontend/src/components/ui/CropFrame.dom.test.tsx b/frontend/src/components/ui/CropFrame.dom.test.tsx index e344bc80..a6b6d33c 100644 --- a/frontend/src/components/ui/CropFrame.dom.test.tsx +++ b/frontend/src/components/ui/CropFrame.dom.test.tsx @@ -99,6 +99,24 @@ describe("CropFrame", () => { expect(rect()).toBe("0.300 0.300 0.400 0.400"); }); + it("takes the focus on a press, so the arrows go on from where the pointer left it", () => { + render(); + const frame = screen.getByRole("group", { name: "common.cropFrame.frame" }); + fireEvent.pointerDown(frame, { button: 0, clientX: 500, clientY: 300 }); + fireEvent.pointerUp(frame, { clientX: 500, clientY: 300 }); + expect(document.activeElement).toBe(frame); + const se = screen.getByRole("group", { name: "common.cropFrame.se" }); + fireEvent.pointerDown(se, { button: 0, clientX: 960, clientY: 540 }); + expect(document.activeElement).toBe(se); + // An edge is the pointer's only: its press puts the focus on the frame it belongs to. + fireEvent.pointerDown(document.querySelector(".cursor-ew-resize")!, { + button: 0, + clientX: 960, + clientY: 400, + }); + expect(document.activeElement).toBe(frame); + }); + it("lets a press outside the frame through to the player, and keeps one on the frame", () => { const click = vi.fn(); render( diff --git a/frontend/src/components/ui/CropFrame.tsx b/frontend/src/components/ui/CropFrame.tsx index 460f7c04..c377ccdc 100644 --- a/frontend/src/components/ui/CropFrame.tsx +++ b/frontend/src/components/ui/CropFrame.tsx @@ -90,6 +90,9 @@ export function CropFrame({ aspect, rect, ratio, onChange, className }: Props) { // The press is the frame's: not the video's play / pause, not a scrub of anything under it. e.stopPropagation(); e.preventDefault(); + // preventDefault also stops the press from focusing: focused by hand, so the arrows go on from + // here (an edge is the pointer's only, so its frame takes the focus). + e.currentTarget.closest("[tabindex]")?.focus({ preventScroll: true }); try { e.currentTarget.setPointerCapture(e.pointerId); } catch {