Skip to content

Commit 9a553eb

Browse files
committed
fix(gesture): only start gestures on the primary mouse button
A right click started the drag gesture of segment, range, toggle and the other gesture-based components. On macOS the context menu swallows the mouseup, so the gesture stayed active and moving the pointer changed the value until the next left click. resolves #29872
1 parent 6b5afec commit 9a553eb

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

‎core/src/components/segment/test/segment-events.e2e.ts‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,54 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
191191
});
192192
});
193193

194+
test.describe('when the segment is right clicked', () => {
195+
test('should not change the value when the pointer moves', async ({ page }) => {
196+
test.info().annotations.push({
197+
type: 'issue',
198+
description: 'https://github.com/ionic-team/ionic-framework/issues/29872',
199+
});
200+
201+
await page.setContent(
202+
`
203+
<ion-segment value="1">
204+
<ion-segment-button value="1">
205+
<ion-label>One</ion-label>
206+
</ion-segment-button>
207+
<ion-segment-button value="2">
208+
<ion-label>Two</ion-label>
209+
</ion-segment-button>
210+
<ion-segment-button value="3">
211+
<ion-label>Three</ion-label>
212+
</ion-segment-button>
213+
</ion-segment>
214+
`,
215+
config
216+
);
217+
218+
const ionChangeSpy = await page.spyOnEvent('ionChange');
219+
220+
const segment = page.locator('ion-segment');
221+
const firstButton = page.locator('ion-segment-button[value="1"]');
222+
const lastButton = page.locator('ion-segment-button[value="3"]');
223+
224+
/**
225+
* A right click should not start the drag gesture. On macOS the
226+
* context menu swallows the mouseup, so a drag started by a right
227+
* click follows the pointer until the next left click. Playwright
228+
* cannot open the native context menu, so the right button is held
229+
* down while the pointer moves instead.
230+
*/
231+
await firstButton.hover();
232+
await page.mouse.down({ button: 'right' });
233+
234+
await lastButton.hover();
235+
await page.mouse.up({ button: 'right' });
236+
237+
expect(await segment.evaluate((el: HTMLIonSegmentElement) => el.value)).toBe('1');
238+
expect(ionChangeSpy).toHaveReceivedEventTimes(0);
239+
});
240+
});
241+
194242
test('should not emit if the value has not changed on click', async ({ page }) => {
195243
await page.setContent(
196244
`

‎core/src/utils/gesture/pointer-events.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ export const createPointerEvents = (
5252
if (lastTouchEvent > Date.now()) {
5353
return;
5454
}
55+
/**
56+
* Only the primary button should start a gesture. On macOS, the
57+
* context menu opened by a right click swallows the mouseup, which
58+
* would leave the gesture active until the next click.
59+
*/
60+
if (ev.button > 0) {
61+
return;
62+
}
5563
if (!pointerDown(ev)) {
5664
return;
5765
}

0 commit comments

Comments
 (0)