Skip to content

Commit 8f91b57

Browse files
committed
fix: release pointer capture when using onPointerLeave events
Certain input sources (such as touch) are "captured" when they press an element. This means the pointer is always considered "inside" the element by the browser, even when they visually are not. This caused some issues on mobile browsers where touch and stylus events could not connect table columns with each other. Just to be safe, I've added the required `releasePointerCapture` call everywhere `onPointerEnter` or `onPointerLeave` is used.
1 parent 80b47d7 commit 8f91b57

File tree

5 files changed

+34
-1
lines changed

5 files changed

+34
-1
lines changed

src/components/EditorCanvas/Note.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ export default function Note({ data, onPointerDown }) {
8585
<g
8686
onPointerEnter={(e) => e.isPrimary && setHovered(true)}
8787
onPointerLeave={(e) => e.isPrimary && setHovered(false)}
88+
onPointerDown={(e) => {
89+
// Required for onPointerLeave to trigger when a touch pointer leaves
90+
// https://stackoverflow.com/a/70976017/1137077
91+
e.target.releasePointerCapture(e.pointerId);
92+
}}
8893
>
8994
<path
9095
d={`M${data.x + fold} ${data.y} L${data.x + w - r} ${

src/components/EditorCanvas/Table.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ export default function Table(props) {
280280

281281
setHoveredField(-1);
282282
}}
283+
onPointerDown={(e) => {
284+
// Required for onPointerLeave to trigger when a touch pointer leaves
285+
// https://stackoverflow.com/a/70976017/1137077
286+
e.target.releasePointerCapture(e.pointerId);
287+
}}
283288
>
284289
<div
285290
className={`${

src/components/EditorHeader/ControlPanel.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,11 @@ export default function ControlPanel({
15401540
className="text-xl me-1"
15411541
onPointerEnter={(e) => e.isPrimary && setShowEditName(true)}
15421542
onPointerLeave={(e) => e.isPrimary && setShowEditName(false)}
1543+
onPointerDown={(e) => {
1544+
// Required for onPointerLeave to trigger when a touch pointer leaves
1545+
// https://stackoverflow.com/a/70976017/1137077
1546+
e.target.releasePointerCapture(e.pointerId);
1547+
}}
15431548
onClick={() => setModal(MODAL.RENAME)}
15441549
>
15451550
{window.name.split(" ")[0] === "t" ? "Templates/" : "Diagrams/"}

src/components/SimpleCanvas.jsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ function Table({ table, grab }) {
2424
width={tableWidth}
2525
height={height}
2626
className="drop-shadow-lg rounded-md cursor-move"
27-
onPointerDown={(e) => e.isPrimary && grab(e)}
27+
onPointerDown={(e) => {
28+
// Required for onPointerLeave to trigger when a touch pointer leaves
29+
// https://stackoverflow.com/a/70976017/1137077
30+
e.target.releasePointerCapture(e.pointerId);
31+
32+
if (!e.isPrimary) return;
33+
34+
grab(e);
35+
}}
2836
onPointerEnter={(e) => e.isPrimary && setIsHovered(true)}
2937
onPointerLeave={(e) => e.isPrimary && setIsHovered(false)}
3038
>
@@ -48,6 +56,11 @@ function Table({ table, grab }) {
4856
} h-[36px] px-2 py-1 flex justify-between`}
4957
onPointerEnter={(e) => e.isPrimary && setHoveredField(i)}
5058
onPointerLeave={(e) => e.isPrimary && setHoveredField(-1)}
59+
onPointerDown={(e) => {
60+
// Required for onPointerLeave to trigger when a touch pointer leaves
61+
// https://stackoverflow.com/a/70976017/1137077
62+
e.target.releasePointerCapture(e.pointerId);
63+
}}
5164
>
5265
<div className={hoveredField === i ? "text-zinc-500" : ""}>
5366
<button

src/components/Workspace.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,11 @@ export default function WorkSpace() {
352352
onPointerUp={(e) => e.isPrimary && setResize(false)}
353353
onPointerLeave={(e) => e.isPrimary && setResize(false)}
354354
onPointerMove={(e) => e.isPrimary && handleResize(e)}
355+
onPointerDown={(e) => {
356+
// Required for onPointerLeave to trigger when a touch pointer leaves
357+
// https://stackoverflow.com/a/70976017/1137077
358+
e.target.releasePointerCapture(e.pointerId);
359+
}}
355360
>
356361
{layout.sidebar && (
357362
<SidePanel resize={resize} setResize={setResize} width={width} />

0 commit comments

Comments
 (0)